summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO1
-rw-r--r--src/Makefile1
-rw-r--r--src/apk_io.h3
-rw-r--r--src/database.c18
-rw-r--r--src/io.c35
-rw-r--r--src/url.c75
6 files changed, 106 insertions, 27 deletions
diff --git a/TODO b/TODO
index 953d4a1..ce9b485 100644
--- a/TODO
+++ b/TODO
@@ -6,7 +6,6 @@
- index/package fetching from URLs
- read from config file
- cache .apks on USB stick when using network repo for reboot
-- Installation of .APK files not in any repository
- Error handling and rollback
- Dependency manipulation API: deletion, overwrite, check compatibility
diff --git a/src/Makefile b/src/Makefile
index fbb3b5b..b6c0338 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -16,6 +16,7 @@ apk_OBJS = \
archive.o \
version.o \
io.o \
+ url.o \
gunzip.o \
blob.o \
hash.o \
diff --git a/src/apk_io.h b/src/apk_io.h
index 96dc7c9..d9522f6 100644
--- a/src/apk_io.h
+++ b/src/apk_io.h
@@ -42,11 +42,14 @@ struct apk_istream *apk_gunzip_bstream(struct apk_bstream *);
struct apk_istream *apk_istream_from_fd(int fd);
struct apk_istream *apk_istream_from_file(const char *file);
+struct apk_istream *apk_istream_from_url(const char *url);
size_t apk_istream_skip(struct apk_istream *istream, size_t size);
size_t apk_istream_splice(void *stream, int fd, size_t size);
struct apk_bstream *apk_bstream_from_istream(struct apk_istream *istream);
struct apk_bstream *apk_bstream_from_fd(int fd);
+struct apk_bstream *apk_bstream_from_file(const char *file);
+struct apk_bstream *apk_bstream_from_url(const char *url);
struct apk_istream *apk_istream_from_file_gz(const char *file);
diff --git a/src/database.c b/src/database.c
index 261011c..c30550b 100644
--- a/src/database.c
+++ b/src/database.c
@@ -840,7 +840,7 @@ int apk_db_install_pkg(struct apk_database *db,
struct install_ctx ctx;
csum_t csum;
char file[256];
- int fd, r;
+ int r;
if (fchdir(db->root_fd) < 0)
return errno;
@@ -866,22 +866,15 @@ int apk_db_install_pkg(struct apk_database *db,
snprintf(file, sizeof(file),
"%s/%s-%s.apk",
db->repos[0].url, newpkg->name->name, newpkg->version);
-
- fd = open(file, O_RDONLY);
+ bs = apk_bstream_from_url(file);
} else
- fd = open(newpkg->filename, O_RDONLY);
+ bs = apk_bstream_from_file(newpkg->filename);
- if (fd < 0) {
+ if (bs == NULL) {
apk_error("%s: %s", file, strerror(errno));
return errno;
}
- fcntl(fd, F_SETFD, FD_CLOEXEC);
-
- bs = apk_bstream_from_fd(fd);
- if (bs == NULL)
- goto err_close;
-
ctx = (struct install_ctx) {
.db = db,
.pkg = newpkg,
@@ -909,8 +902,7 @@ int apk_db_install_pkg(struct apk_database *db,
write(STDOUT_FILENO, ".", 1);
}
return r;
-
err_close:
- close(fd);
+ bs->close(bs, NULL);
return -1;
}
diff --git a/src/io.c b/src/io.c
index e4dfd33..2c92084 100644
--- a/src/io.c
+++ b/src/io.c
@@ -60,6 +60,9 @@ struct apk_istream *apk_istream_from_fd(int fd)
{
struct apk_fd_istream *fis;
+ if (fd < 0)
+ return NULL;
+
fis = malloc(sizeof(struct apk_fd_istream));
if (fis == NULL)
return NULL;
@@ -81,6 +84,8 @@ struct apk_istream *apk_istream_from_file(const char *file)
if (fd < 0)
return NULL;
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+
return apk_istream_from_fd(fd);
}
@@ -278,6 +283,9 @@ struct apk_bstream *apk_bstream_from_fd(int fd)
{
struct apk_bstream *bs;
+ if (fd < 0)
+ return NULL;
+
bs = apk_mmap_bstream_from_fd(fd);
if (bs != NULL)
return bs;
@@ -285,6 +293,18 @@ struct apk_bstream *apk_bstream_from_fd(int fd)
return apk_bstream_from_istream(apk_istream_from_fd(fd));
}
+struct apk_bstream *apk_bstream_from_file(const char *file)
+{
+ int fd;
+
+ fd = open(file, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ return apk_bstream_from_fd(fd);
+}
+
apk_blob_t apk_blob_from_istream(struct apk_istream *is, size_t size)
{
void *ptr;
@@ -338,7 +358,6 @@ int apk_file_get_info(const char *filename, struct apk_file_info *fi)
{
struct stat st;
struct apk_bstream *bs;
- int fd;
if (stat(filename, &st) != 0)
return -1;
@@ -352,11 +371,7 @@ int apk_file_get_info(const char *filename, struct apk_file_info *fi)
.device = st.st_dev,
};
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- return 0;
-
- bs = apk_bstream_from_fd(fd);
+ bs = apk_bstream_from_file(filename);
if (bs != NULL)
bs->close(bs, fi->csum);
@@ -365,12 +380,6 @@ int apk_file_get_info(const char *filename, struct apk_file_info *fi)
struct apk_istream *apk_istream_from_file_gz(const char *file)
{
- int fd;
-
- fd = open(file, O_RDONLY);
- if (fd < 0)
- return NULL;
-
- return apk_gunzip_bstream(apk_bstream_from_fd(fd));
+ return apk_gunzip_bstream(apk_bstream_from_file(file));
}
diff --git a/src/url.c b/src/url.c
new file mode 100644
index 0000000..0999399
--- /dev/null
+++ b/src/url.c
@@ -0,0 +1,75 @@
+/* url.c - Alpine Package Keeper (APK)
+ *
+ * Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
+ * Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation. See http://www.gnu.org/ for details.
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "apk_io.h"
+
+static const char *url_is_file(const char *url)
+{
+ if (strncmp(url, "file:", 5) == 0)
+ return &url[5];
+
+ if (strncmp(url, "http:", 5) != 0 &&
+ strncmp(url, "https:", 6) != 0 &&
+ strncmp(url, "ftp:", 4) != 0)
+ return url;
+
+ return NULL;
+}
+
+static int fork_wget(const char *url)
+{
+ pid_t pid;
+ int fds[2];
+
+ if (pipe(fds) < 0)
+ return -1;
+
+ pid = fork();
+ if (pid == -1) {
+ close(fds[0]);
+ close(fds[1]);
+ return -1;
+ }
+
+ if (pid == 0) {
+ setsid();
+ close(fds[0]);
+ dup2(open("/dev/null", O_WRONLY), STDERR_FILENO);
+ dup2(open("/dev/null", O_RDONLY), STDIN_FILENO);
+ dup2(fds[1], STDOUT_FILENO);
+ execlp("wget", "wget", "-O", "-", url, NULL);
+ exit(0);
+ }
+
+ close(fds[1]);
+ return fds[0];
+}
+
+struct apk_istream *apk_istream_from_url(const char *url)
+{
+ if (url_is_file(url) != NULL)
+ return apk_istream_from_file(url_is_file(url));
+
+ return apk_istream_from_fd(fork_wget(url));
+}
+
+struct apk_bstream *apk_bstream_from_url(const char *url)
+{
+ if (url_is_file(url))
+ return apk_bstream_from_file(url);
+
+ return apk_bstream_from_fd(fork_wget(url));
+}