Use configurable helper application to deal with urls.

- hijack ufdOpen() operation to call an external helper (if configured)
  to fetch any remote url's, return fd to local temporary file
This commit is contained in:
Panu Matilainen 2007-09-12 11:51:52 +03:00
parent d36716c25c
commit 65012c4253
2 changed files with 63 additions and 50 deletions

View File

@ -1219,5 +1219,11 @@ done \
# #
%find_lang @RPMCONFIGDIR@/find-lang.sh %{buildroot} %find_lang @RPMCONFIGDIR@/find-lang.sh %{buildroot}
# Commands + opts to use for retrieving remote files
%__urlhelpercmd /usr/bin/curl
%__urlhelperopts --silent --show-error --fail --location -o
%_urlhelper %{__urlhelpercmd} %{__urlhelperopts}
# \endverbatim # \endverbatim
#*/ #*/

View File

@ -67,6 +67,9 @@ static int inet_aton(const char *cp, struct in_addr *inp)
#include "ugid.h" #include "ugid.h"
#include "rpmmessages.h" #include "rpmmessages.h"
#include "argv.h"
#include "rpmerr.h"
#include "rpmmacro.h"
#include "debug.h" #include "debug.h"
@ -1998,12 +2001,55 @@ exit:
return fd; return fd;
} }
/*
* Deal with remote url's by fetching them with a helper application
* and treat as local file afterwards.
* TODO:
* - better error checking + reporting
* - curl & friends don't know about hkp://, transform to http?
*/
static FD_t urlOpen(const char * url, int flags, mode_t mode)
{
FD_t fd = NULL;
char cmd[BUFSIZ];
char *dest = NULL;
char *urlhelper = NULL;
int rc;
pid_t pid, wait;
urlhelper = rpmExpand("%{?_urlhelper}", NULL);
dest = (char *) rpmGenPath(NULL, "%{_tmppath}/", "rpm-transfer.XXXXXX");
close(mkstemp(dest));
sprintf(cmd, "%s %s %s\n", urlhelper, dest, url);
urlhelper = _free(urlhelper);
if ((pid = fork()) == 0) {
ARGV_t argv = NULL;
argvSplit(&argv, cmd, " ");
execvp(argv[0], (char *const *)argv);
exit(-1); /* error out if exec fails */
}
wait = waitpid(pid, &rc, 0);
if (!WIFEXITED(rc) || WEXITSTATUS(rc)) {
rpmError(RPMERR_EXEC, _("URL helper failed: %s (%d)\n"),
cmd, WEXITSTATUS(rc));
} else {
fd = fdOpen(dest, flags, mode);
unlink(dest);
}
dest = _free(dest);
return fd;
}
static FD_t ufdOpen(const char * url, int flags, mode_t mode) static FD_t ufdOpen(const char * url, int flags, mode_t mode)
{ {
FD_t fd = NULL; FD_t fd = NULL;
const char * cmd;
urlinfo u;
const char * path; const char * path;
int timeout = 1;
urltype urlType = urlPath(url, &path); urltype urlType = urlPath(url, &path);
if (_rpmio_debug) if (_rpmio_debug)
@ -2011,71 +2057,32 @@ fprintf(stderr, "*** ufdOpen(%s,0x%x,0%o)\n", url, (unsigned)flags, (unsigned)mo
switch (urlType) { switch (urlType) {
case URL_IS_FTP: case URL_IS_FTP:
fd = ftpOpen(url, flags, mode, &u);
if (fd == NULL || u == NULL)
break;
/* XXX W2DO? use STOU rather than STOR to prevent clobbering */
cmd = ((flags & O_WRONLY)
? ((flags & O_APPEND) ? "APPE" :
((flags & O_CREAT) ? "STOR" : "STOR"))
: ((flags & O_CREAT) ? "STOR" : "RETR"));
u->openError = ftpReq(fd, cmd, path);
if (u->openError < 0) {
/* XXX make sure that we can exit through ufdClose */
fd = fdLink(fd, "error data (ufdOpen FTP)");
} else {
fd->bytesRemain = ((!strcmp(cmd, "RETR"))
? fd->contentLength : -1);
fd->wr_chunked = 0;
}
break;
case URL_IS_HTTPS: case URL_IS_HTTPS:
case URL_IS_HTTP: case URL_IS_HTTP:
case URL_IS_HKP: case URL_IS_HKP:
fd = httpOpen(url, flags, mode, &u); fd = urlOpen(url, flags, mode);
if (fd == NULL || u == NULL) /* we're dealing with local file when urlOpen() returns */
break; urlType = URL_IS_UNKNOWN;
cmd = ((flags & O_WRONLY)
? ((flags & O_APPEND) ? "PUT" :
((flags & O_CREAT) ? "PUT" : "PUT"))
: "GET");
u->openError = httpReq(fd, cmd, path);
if (u->openError < 0) {
/* XXX make sure that we can exit through ufdClose */
fd = fdLink(fd, "error ctrl (ufdOpen HTTP)");
fd = fdLink(fd, "error data (ufdOpen HTTP)");
} else {
fd->bytesRemain = ((!strcmp(cmd, "GET"))
? fd->contentLength : -1);
fd->wr_chunked = ((!strcmp(cmd, "PUT"))
? fd->wr_chunked : 0);
}
break; break;
case URL_IS_DASH: case URL_IS_DASH:
assert(!(flags & O_RDWR)); assert(!(flags & O_RDWR));
fd = fdDup( ((flags & O_WRONLY) ? STDOUT_FILENO : STDIN_FILENO) ); fd = fdDup( ((flags & O_WRONLY) ? STDOUT_FILENO : STDIN_FILENO) );
if (fd) { timeout = 600; /* XXX W2DO? 10 mins? */
fdSetIo(fd, ufdio);
fd->rd_timeoutsecs = 600; /* XXX W2DO? 10 mins? */
fd->contentLength = fd->bytesRemain = -1;
}
break; break;
case URL_IS_PATH: case URL_IS_PATH:
case URL_IS_UNKNOWN: case URL_IS_UNKNOWN:
default: default:
fd = fdOpen(path, flags, mode); fd = fdOpen(path, flags, mode);
if (fd) {
fdSetIo(fd, ufdio);
fd->rd_timeoutsecs = 1;
fd->contentLength = fd->bytesRemain = -1;
}
break; break;
} }
if (fd == NULL) return NULL; if (fd == NULL) return NULL;
fdSetIo(fd, ufdio);
fd->rd_timeoutsecs = timeout;
fd->contentLength = fd->bytesRemain = -1;
fd->urlType = urlType; fd->urlType = urlType;
if (Fileno(fd) < 0) { if (Fileno(fd) < 0) {
(void) ufdClose(fd); (void) ufdClose(fd);
return NULL; return NULL;