diff --git a/CHANGES b/CHANGES index 1ecfcfe8a..99858f385 100644 --- a/CHANGES +++ b/CHANGES @@ -55,6 +55,7 @@ - fix: segfault with legacy packages missing RPMTAG_FILEINODES. - require db3 in default configuration. - create rpmio directory for librpmio. + - make librpmio standalone. 3.0.3 -> 3.0.4 - use compressed filenames on install side. diff --git a/lib/Makefile.am b/lib/Makefile.am index efc3ca3af..cd90323ec 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -27,7 +27,6 @@ librpm_la_SOURCES = \ rpmlead.c rpmrc.c signature.c stringbuf.c stubs.c \ tagName.c tagtable.c transaction.c uninstall.c verify.c librpm_la_LDFLAGS = -L$(top_builddir)/rpmio/.libs -lrpmio -# -L$(top_builddir)/popt -lpopt librpm_la_LIBADD = $(subst .c,.lo,$(DBLIBOBJS)) # XXX Drill out -L ldflags remnants until libtool-1.4 appears diff --git a/lib/rpmlib.h b/lib/rpmlib.h index 625ab3f1f..a39cbd708 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -6,6 +6,8 @@ /* and it shouldn't need these :-( */ #include "rpmio.h" +#include "rpmmessages.h" +#include "rpmerr.h" #include "header.h" #include "popt.h" @@ -320,26 +322,10 @@ void rpmSetMachine(const char * arch, const char * os); void rpmGetMachine( /*@out@*/ const char **arch, /*@out@*/ const char **os); void rpmFreeRpmrc(void); +/* ==================================================================== */ /** **/ - typedef /*@abstract@*/ struct rpmdb_s * rpmdb; -typedef enum rpmCallbackType_e { - RPMCALLBACK_INST_PROGRESS, RPMCALLBACK_INST_START, - RPMCALLBACK_INST_OPEN_FILE, RPMCALLBACK_INST_CLOSE_FILE, - RPMCALLBACK_TRANS_PROGRESS, RPMCALLBACK_TRANS_START, RPMCALLBACK_TRANS_STOP, - RPMCALLBACK_UNINST_PROGRESS, RPMCALLBACK_UNINST_START, RPMCALLBACK_UNINST_STOP -} rpmCallbackType; - -typedef void * (*rpmCallbackFunction)(const Header h, - const rpmCallbackType what, - const unsigned long amount, - const unsigned long total, - const void * pkgKey, void * data); - -void urlSetCallback(rpmCallbackFunction notify, void *notifyData, int notifyCount); - -/* ==================================================================== */ /** * @param dbp address of rpm database */ @@ -654,24 +640,6 @@ int rpmRunTransactions(rpmTransactionSet ts, rpmCallbackFunction notify, #define RPMPROB_FILTER_OLDPACKAGE (1 << 6) #define RPMPROB_FILTER_DISKSPACE (1 << 7) -/** messages.c **/ - -#define RPMMESS_DEBUG 1 -#define RPMMESS_VERBOSE 2 -#define RPMMESS_NORMAL 3 -#define RPMMESS_WARNING 4 -#define RPMMESS_ERROR 5 -#define RPMMESS_FATALERROR 6 - -#define RPMMESS_QUIET (RPMMESS_NORMAL + 1) - -void rpmIncreaseVerbosity(void); -void rpmSetVerbosity(int level); -int rpmGetVerbosity(void); -int rpmIsVerbose(void); -int rpmIsDebug(void); -void rpmMessage(int level, const char * format, ...); - /** rpmlead.c **/ #define RPMLEAD_BINARY 0 @@ -708,80 +676,6 @@ struct oldrpmlead { /* for version 1 packages */ unsigned int archiveOffset; } ; -/** rpmerr.c **/ - -typedef void (*rpmErrorCallBackType)(void); - -#if defined(__GNUC__) -void rpmError(int code, char * format, ...) __attribute__ ((__format__ (__printf__, 2, 3))); -#else -void rpmError(int code, char * format, ...); -#endif - -int rpmErrorCode(void); -char *rpmErrorCodeString(void); -char *rpmErrorString(void); -rpmErrorCallBackType rpmErrorSetCallback(rpmErrorCallBackType); - -#define RPMERR_GDBMOPEN -2 /* gdbm open failed */ -#define RPMERR_GDBMREAD -3 /* gdbm read failed */ -#define RPMERR_GDBMWRITE -4 /* gdbm write failed */ -#define RPMERR_INTERNAL -5 /* internal RPM error */ -#define RPMERR_DBCORRUPT -6 /* rpm database is corrupt */ -#define RPMERR_OLDDBCORRUPT -7 /* old style rpm database is corrupt */ -#define RPMERR_OLDDBMISSING -8 /* old style rpm database is missing */ -#define RPMERR_NOCREATEDB -9 /* cannot create new database */ -#define RPMERR_DBOPEN -10 /* database open failed */ -#define RPMERR_DBGETINDEX -11 /* database get from index failed */ -#define RPMERR_DBPUTINDEX -12 /* database get from index failed */ -#define RPMERR_NEWPACKAGE -13 /* package is too new to handle */ -#define RPMERR_BADMAGIC -14 /* bad magic for an RPM */ -#define RPMERR_RENAME -15 /* rename(2) failed */ -#define RPMERR_UNLINK -16 /* unlink(2) failed */ -#define RPMERR_RMDIR -17 /* rmdir(2) failed */ -#define RPMERR_PKGINSTALLED -18 /* package already installed */ -#define RPMERR_CHOWN -19 /* chown() call failed */ -#define RPMERR_NOUSER -20 /* user does not exist */ -#define RPMERR_NOGROUP -21 /* group does not exist */ -#define RPMERR_MKDIR -22 /* mkdir() call failed */ -#define RPMERR_FILECONFLICT -23 /* file being installed exists */ -#define RPMERR_RPMRC -24 /* bad line in rpmrc */ -#define RPMERR_NOSPEC -25 /* .spec file is missing */ -#define RPMERR_NOTSRPM -26 /* a source rpm was expected */ -#define RPMERR_FLOCK -27 /* locking the database failed */ -#define RPMERR_OLDPACKAGE -28 /* trying upgrading to old version */ -/*#define RPMERR_BADARCH -29 bad architecture or arch mismatch */ -#define RPMERR_CREATE -30 /* failed to create a file */ -#define RPMERR_NOSPACE -31 /* out of disk space */ -#define RPMERR_NORELOCATE -32 /* tried to do improper relocatation */ -/*#define RPMERR_BADOS -33 bad architecture or arch mismatch */ -#define RPMMESS_BACKUP -34 /* backup made during [un]install */ -#define RPMERR_MTAB -35 /* failed to read mount table */ -#define RPMERR_STAT -36 /* failed to stat something */ -#define RPMERR_BADDEV -37 /* file on device not listed in mtab */ -#define RPMMESS_ALTNAME -38 /* file written as .rpmnew */ -#define RPMMESS_PREREQLOOP -39 /* loop in prerequisites */ -#define RPMERR_BADRELOCATE -40 /* bad relocation was specified */ -#define RPMERR_OLDDB -41 /* old format database */ - -/* spec.c build.c pack.c */ -#define RPMERR_UNMATCHEDIF -107 /* unclosed %ifarch or %ifos */ -#define RPMERR_BADARG -109 -#define RPMERR_SCRIPT -110 /* errors related to script exec */ -#define RPMERR_READERROR -111 -#define RPMERR_UNKNOWNOS -112 -#define RPMERR_UNKNOWNARCH -113 -#define RPMERR_EXEC -114 -#define RPMERR_FORK -115 -#define RPMERR_CPIO -116 -#define RPMERR_GZIP -117 -#define RPMERR_BADSPEC -118 -#define RPMERR_LDD -119 /* couldn't understand ldd output */ -#define RPMERR_BADFILENAME -120 - -#define RPMERR_BADSIGTYPE -200 /* Unknown signature type */ -#define RPMERR_SIGGEN -201 /* Error generating signature */ - /** signature.c **/ /**************************************************/ diff --git a/po/rpm.pot b/po/rpm.pot index 87ae7f344..092b03c28 100644 --- a/po/rpm.pot +++ b/po/rpm.pot @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2000-06-09 15:18-0400\n" +"POT-Creation-Date: 2000-06-09 17:03-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -2387,7 +2387,7 @@ msgstr "" msgid "opening db file %s mode 0x%x\n" msgstr "" -#: lib/db1.c:430 rpmio/url.c:444 +#: lib/db1.c:430 rpmio/url.c:445 #, c-format msgid "failed to open %s: %s\n" msgstr "" @@ -3749,141 +3749,141 @@ msgstr "" msgid "Unsatisfied dependencies for %s-%s-%s: " msgstr "" -#: rpmio/rpmio.c:537 +#: rpmio/rpmio.c:532 msgid "Success" msgstr "" -#: rpmio/rpmio.c:540 +#: rpmio/rpmio.c:535 msgid "Bad server response" msgstr "" -#: rpmio/rpmio.c:543 +#: rpmio/rpmio.c:538 msgid "Server IO error" msgstr "" -#: rpmio/rpmio.c:546 +#: rpmio/rpmio.c:541 msgid "Server timeout" msgstr "" -#: rpmio/rpmio.c:549 +#: rpmio/rpmio.c:544 msgid "Unable to lookup server host address" msgstr "" -#: rpmio/rpmio.c:552 +#: rpmio/rpmio.c:547 msgid "Unable to lookup server host name" msgstr "" -#: rpmio/rpmio.c:555 +#: rpmio/rpmio.c:550 msgid "Failed to connect to server" msgstr "" -#: rpmio/rpmio.c:558 +#: rpmio/rpmio.c:553 msgid "Failed to establish data connection to server" msgstr "" -#: rpmio/rpmio.c:561 +#: rpmio/rpmio.c:556 msgid "IO error to local file" msgstr "" -#: rpmio/rpmio.c:564 +#: rpmio/rpmio.c:559 msgid "Error setting remote server to passive mode" msgstr "" -#: rpmio/rpmio.c:567 +#: rpmio/rpmio.c:562 msgid "File not found on server" msgstr "" -#: rpmio/rpmio.c:570 +#: rpmio/rpmio.c:565 msgid "Abort in progress" msgstr "" -#: rpmio/rpmio.c:574 +#: rpmio/rpmio.c:569 msgid "Unknown or unexpected error" msgstr "" -#: rpmio/rpmio.c:1107 +#: rpmio/rpmio.c:1164 #, c-format msgid "logging into %s as %s, pw %s\n" msgstr "" -#: rpmio/macro.c:160 +#: rpmio/macro.c:161 #, c-format msgid "======================== active %d empty %d\n" msgstr "" #. XXX just in case -#: rpmio/macro.c:255 +#: rpmio/macro.c:256 #, c-format msgid "%3d>%*s(empty)" msgstr "" -#: rpmio/macro.c:290 +#: rpmio/macro.c:291 #, c-format msgid "%3d<%*s(empty)\n" msgstr "" -#: rpmio/macro.c:469 +#: rpmio/macro.c:470 msgid "Macro %%%s has unterminated body" msgstr "" -#: rpmio/macro.c:495 +#: rpmio/macro.c:496 msgid "Macro %%%s has illegal name (%%define)" msgstr "" -#: rpmio/macro.c:501 +#: rpmio/macro.c:502 msgid "Macro %%%s has unterminated opts" msgstr "" -#: rpmio/macro.c:506 +#: rpmio/macro.c:507 msgid "Macro %%%s has empty body" msgstr "" -#: rpmio/macro.c:511 +#: rpmio/macro.c:512 msgid "Macro %%%s failed to expand" msgstr "" -#: rpmio/macro.c:536 +#: rpmio/macro.c:537 msgid "Macro %%%s has illegal name (%%undefine)" msgstr "" -#: rpmio/macro.c:613 +#: rpmio/macro.c:614 msgid "Macro %%%s (%s) was not used below level %d" msgstr "" -#: rpmio/macro.c:710 +#: rpmio/macro.c:711 #, c-format msgid "Unknown option %c in %s(%s)" msgstr "" -#: rpmio/macro.c:890 +#: rpmio/macro.c:891 #, c-format msgid "Recursion depth(%d) greater than max(%d)" msgstr "" -#: rpmio/macro.c:956 rpmio/macro.c:972 +#: rpmio/macro.c:957 rpmio/macro.c:973 #, c-format msgid "Unterminated %c: %s" msgstr "" -#: rpmio/macro.c:1012 +#: rpmio/macro.c:1013 msgid "A %% is followed by an unparseable macro" msgstr "" -#: rpmio/macro.c:1138 +#: rpmio/macro.c:1139 msgid "Macro %%%.*s not found, skipping" msgstr "" -#: rpmio/macro.c:1219 +#: rpmio/macro.c:1220 msgid "Target buffer overflow" msgstr "" #. XXX Fstrerror -#: rpmio/macro.c:1399 rpmio/macro.c:1405 +#: rpmio/macro.c:1400 rpmio/macro.c:1406 #, c-format msgid "File %s: %s" msgstr "" -#: rpmio/macro.c:1408 +#: rpmio/macro.c:1409 #, c-format msgid "File %s is smaller than %d bytes" msgstr "" @@ -3909,37 +3909,37 @@ msgstr "" msgid "memory alloc (%u bytes) returned NULL.\n" msgstr "" -#: rpmio/url.c:87 +#: rpmio/url.c:88 #, c-format msgid "warning: u %p ctrl %p nrefs != 0 (%s %s)\n" msgstr "" -#: rpmio/url.c:104 +#: rpmio/url.c:105 #, c-format msgid "warning: u %p data %p nrefs != 0 (%s %s)\n" msgstr "" -#: rpmio/url.c:131 +#: rpmio/url.c:132 #, c-format msgid "warning: uCache[%d] %p nrefs(%d) != 1 (%s %s)\n" msgstr "" -#: rpmio/url.c:217 +#: rpmio/url.c:218 #, c-format msgid "Password for %s@%s: " msgstr "" -#: rpmio/url.c:242 rpmio/url.c:268 +#: rpmio/url.c:243 rpmio/url.c:269 #, c-format msgid "error: %sport must be a number\n" msgstr "" -#: rpmio/url.c:404 +#: rpmio/url.c:405 msgid "url port must be a number\n" msgstr "" #. XXX Fstrerror -#: rpmio/url.c:461 +#: rpmio/url.c:462 #, c-format msgid "failed to create %s: %s\n" msgstr "" diff --git a/rpm.spec b/rpm.spec index 78d262ab1..3a326ea67 100644 --- a/rpm.spec +++ b/rpm.spec @@ -5,7 +5,7 @@ Summary: The Red Hat package management system. Name: rpm %define version 4.0 Version: %{version} -Release: 0.34 +Release: 0.35 Group: System Environment/Base Source: ftp://ftp.rpm.org/pub/rpm/dist/rpm-3.0.x/rpm-%{version}.tar.gz Copyright: GPL diff --git a/rpmio/Makefile.am b/rpmio/Makefile.am index 6c0d73e4b..4146796af 100644 --- a/rpmio/Makefile.am +++ b/rpmio/Makefile.am @@ -6,11 +6,12 @@ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/build -I$(top_srcdir)/lib \ -I$(top_srcdir)/popt @INCPATH@ pkgincdir = $(pkgincludedir) -pkginc_HEADERS = rpmio.h rpmurl.h rpmmacro.h +pkginc_HEADERS = rpmio.h rpmurl.h rpmmacro.h rpmmessages.h rpmerr.h noinst_HEADERS = rpmio_internal.h ugid.h lib_LTLIBRARIES = librpmio.la -librpmio_la_SOURCES = rpmio.c url.c macro.c ugid.c rpmmalloc.c rpmerr.c messages.c +librpmio_la_SOURCES = rpmrpc.c rpmio.c url.c macro.c \ + ugid.c rpmmalloc.c rpmerr.c messages.c librpmio_la_LDFLAGS = -L$(top_builddir)/popt/.libs -lpopt librpmio_la_LIBADD = @LIBMISC@ diff --git a/rpmio/macro.c b/rpmio/macro.c index 846e992a7..b9f5809cd 100644 --- a/rpmio/macro.c +++ b/rpmio/macro.c @@ -39,8 +39,9 @@ typedef FILE * FD_t; #else -#include #include +#include +#include #endif diff --git a/rpmio/messages.c b/rpmio/messages.c index 72595b2bd..5853758b3 100644 --- a/rpmio/messages.c +++ b/rpmio/messages.c @@ -2,7 +2,7 @@ #include -#include +#include static int minLevel = RPMMESS_NORMAL; diff --git a/rpmio/rpmerr.c b/rpmio/rpmerr.c index fc05e7e87..a15a26c92 100644 --- a/rpmio/rpmerr.c +++ b/rpmio/rpmerr.c @@ -2,7 +2,7 @@ #include -#include +#include static struct err { int code; diff --git a/rpmio/rpmerr.h b/rpmio/rpmerr.h new file mode 100644 index 000000000..e80bbcff9 --- /dev/null +++ b/rpmio/rpmerr.h @@ -0,0 +1,84 @@ +#ifndef H_RPMERR +#define H_RPMERR + +#define RPMERR_GDBMOPEN -2 /* gdbm open failed */ +#define RPMERR_GDBMREAD -3 /* gdbm read failed */ +#define RPMERR_GDBMWRITE -4 /* gdbm write failed */ +#define RPMERR_INTERNAL -5 /* internal RPM error */ +#define RPMERR_DBCORRUPT -6 /* rpm database is corrupt */ +#define RPMERR_OLDDBCORRUPT -7 /* old style rpm database is corrupt */ +#define RPMERR_OLDDBMISSING -8 /* old style rpm database is missing */ +#define RPMERR_NOCREATEDB -9 /* cannot create new database */ +#define RPMERR_DBOPEN -10 /* database open failed */ +#define RPMERR_DBGETINDEX -11 /* database get from index failed */ +#define RPMERR_DBPUTINDEX -12 /* database get from index failed */ +#define RPMERR_NEWPACKAGE -13 /* package is too new to handle */ +#define RPMERR_BADMAGIC -14 /* bad magic for an RPM */ +#define RPMERR_RENAME -15 /* rename(2) failed */ +#define RPMERR_UNLINK -16 /* unlink(2) failed */ +#define RPMERR_RMDIR -17 /* rmdir(2) failed */ +#define RPMERR_PKGINSTALLED -18 /* package already installed */ +#define RPMERR_CHOWN -19 /* chown() call failed */ +#define RPMERR_NOUSER -20 /* user does not exist */ +#define RPMERR_NOGROUP -21 /* group does not exist */ +#define RPMERR_MKDIR -22 /* mkdir() call failed */ +#define RPMERR_FILECONFLICT -23 /* file being installed exists */ +#define RPMERR_RPMRC -24 /* bad line in rpmrc */ +#define RPMERR_NOSPEC -25 /* .spec file is missing */ +#define RPMERR_NOTSRPM -26 /* a source rpm was expected */ +#define RPMERR_FLOCK -27 /* locking the database failed */ +#define RPMERR_OLDPACKAGE -28 /* trying upgrading to old version */ +/*#define RPMERR_BADARCH -29 bad architecture or arch mismatch */ +#define RPMERR_CREATE -30 /* failed to create a file */ +#define RPMERR_NOSPACE -31 /* out of disk space */ +#define RPMERR_NORELOCATE -32 /* tried to do improper relocatation */ +/*#define RPMERR_BADOS -33 bad architecture or arch mismatch */ +#define RPMMESS_BACKUP -34 /* backup made during [un]install */ +#define RPMERR_MTAB -35 /* failed to read mount table */ +#define RPMERR_STAT -36 /* failed to stat something */ +#define RPMERR_BADDEV -37 /* file on device not listed in mtab */ +#define RPMMESS_ALTNAME -38 /* file written as .rpmnew */ +#define RPMMESS_PREREQLOOP -39 /* loop in prerequisites */ +#define RPMERR_BADRELOCATE -40 /* bad relocation was specified */ +#define RPMERR_OLDDB -41 /* old format database */ + +/* spec.c build.c pack.c */ +#define RPMERR_UNMATCHEDIF -107 /* unclosed %ifarch or %ifos */ +#define RPMERR_BADARG -109 +#define RPMERR_SCRIPT -110 /* errors related to script exec */ +#define RPMERR_READERROR -111 +#define RPMERR_UNKNOWNOS -112 +#define RPMERR_UNKNOWNARCH -113 +#define RPMERR_EXEC -114 +#define RPMERR_FORK -115 +#define RPMERR_CPIO -116 +#define RPMERR_GZIP -117 +#define RPMERR_BADSPEC -118 +#define RPMERR_LDD -119 /* couldn't understand ldd output */ +#define RPMERR_BADFILENAME -120 + +#define RPMERR_BADSIGTYPE -200 /* Unknown signature type */ +#define RPMERR_SIGGEN -201 /* Error generating signature */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*rpmErrorCallBackType)(void); + +#if defined(__GNUC__) +void rpmError(int code, char * format, ...) __attribute__ ((__format__ (__printf__, 2, 3))); +#else +void rpmError(int code, char * format, ...); +#endif + +int rpmErrorCode(void); +char *rpmErrorCodeString(void); +char *rpmErrorString(void); +rpmErrorCallBackType rpmErrorSetCallback(rpmErrorCallBackType); + +#ifdef __cplusplus +} +#endif + +#endif /* H_RPMERR */ diff --git a/rpmio/rpmio.c b/rpmio/rpmio.c index 07017c201..f1e9ed5ed 100644 --- a/rpmio/rpmio.c +++ b/rpmio/rpmio.c @@ -60,9 +60,9 @@ static int inet_aton(const char *cp, struct in_addr *inp) #include "dns.h" #endif -#include #include -#include "misc.h" +#include "ugid.h" +#include "rpmmessages.h" #define FDNREFS(fd) (fd ? ((FD_t)fd)->nrefs : -9) #define FDTO(fd) (fd ? ((FD_t)fd)->rd_timeoutsecs : -99) @@ -90,11 +90,6 @@ static int httpTimeoutSecs = TIMEOUT_SECS; int _ftp_debug = 0; int _rpmio_debug = 0; -#define DBG(_f, _m, _x) \ - if ((_rpmio_debug | ((_f) ? ((FD_t)(_f))->flags : 0)) & (_m)) fprintf _x - -#define DBGIO(_f, _x) DBG((_f), RPMIO_DEBUG_IO, _x) -#define DBGREFS(_f, _x) DBG((_f), RPMIO_DEBUG_REFS, _x) /* =============================================================== */ @@ -465,7 +460,7 @@ int fdReadable(FD_t fd, int secs) /*@notreached@*/ } -static int fdFgets(FD_t fd, char * buf, size_t len) +int fdFgets(FD_t fd, char * buf, size_t len) { int fdno; int secs = fd->rd_timeoutsecs; @@ -951,7 +946,7 @@ errxit2: return rc; } -static int ftpReq(FD_t data, const char * ftpCmd, const char * ftpArg) +int ftpReq(FD_t data, const char * ftpCmd, const char * ftpArg) { urlinfo u = data->url; struct sockaddr_in dataAddress; @@ -1081,48 +1076,6 @@ errxit: return rc; } -static int urlConnect(const char * url, /*@out@*/ urlinfo * uret) -{ - urlinfo u; - int rc = 0; - - if (urlSplit(url, &u) < 0) - return -1; - - if (u->urltype == URL_IS_FTP) { - FD_t fd; - - if ((fd = u->ctrl) == NULL) { - fd = u->ctrl = fdNew("persist ctrl (urlConnect FTP)"); - fdSetIo(u->ctrl, ufdio); - } - - fd->rd_timeoutsecs = ftpTimeoutSecs; - fd->contentLength = fd->bytesRemain = -1; - fd->url = NULL; /* XXX FTP ctrl has not */ - fd->ftpFileDoneNeeded = 0; - fd = fdLink(fd, "grab ctrl (urlConnect FTP)"); - - if (fdFileno(u->ctrl) < 0) { - rpmMessage(RPMMESS_DEBUG, _("logging into %s as %s, pw %s\n"), - u->host, - u->user ? u->user : "ftp", - u->password ? u->password : "(username)"); - - if ((rc = ftpLogin(u)) < 0) { /* XXX save ftpLogin error */ - u->ctrl = fdFree(fd, "grab ctrl (urlConnect FTP)"); - u->openError = rc; - } - } - } - - if (uret != NULL) - *uret = urlLink(u, "urlConnect"); - u = urlFree(u, "urlSplit (urlConnect)"); - - return rc; -} - /*@null@*/ static rpmCallbackFunction urlNotify = NULL; /*@null@*/ static void * urlNotifyData = NULL; static int urlNotifyCount = -1; @@ -1185,6 +1138,48 @@ int ufdCopy(FD_t sfd, FD_t tfd) return rc; } +static int urlConnect(const char * url, /*@out@*/ urlinfo * uret) +{ + urlinfo u; + int rc = 0; + + if (urlSplit(url, &u) < 0) + return -1; + + if (u->urltype == URL_IS_FTP) { + FD_t fd; + + if ((fd = u->ctrl) == NULL) { + fd = u->ctrl = fdNew("persist ctrl (urlConnect FTP)"); + fdSetIo(u->ctrl, ufdio); + } + + fd->rd_timeoutsecs = ftpTimeoutSecs; + fd->contentLength = fd->bytesRemain = -1; + fd->url = NULL; /* XXX FTP ctrl has not */ + fd->ftpFileDoneNeeded = 0; + fd = fdLink(fd, "grab ctrl (urlConnect FTP)"); + + if (fdFileno(u->ctrl) < 0) { + rpmMessage(RPMMESS_DEBUG, _("logging into %s as %s, pw %s\n"), + u->host, + u->user ? u->user : "ftp", + u->password ? u->password : "(username)"); + + if ((rc = ftpLogin(u)) < 0) { /* XXX save ftpLogin error */ + u->ctrl = fdFree(fd, "grab ctrl (urlConnect FTP)"); + u->openError = rc; + } + } + } + + if (uret != NULL) + *uret = urlLink(u, "urlConnect"); + u = urlFree(u, "urlSplit (urlConnect)"); + + return rc; +} + int ufdGetFile(FD_t sfd, FD_t tfd) { int rc; @@ -1198,7 +1193,7 @@ int ufdGetFile(FD_t sfd, FD_t tfd) return rc; } -static int ftpCmd(const char * cmd, const char * url, const char * arg2) { +int ftpCmd(const char * cmd, const char * url, const char * arg2) { urlinfo u; int rc; const char * path; @@ -1213,38 +1208,6 @@ static int ftpCmd(const char * cmd, const char * url, const char * arg2) { return rc; } -static int ftpMkdir(const char * path, /*@unused@*/ mode_t mode) { - int rc; - if ((rc = ftpCmd("MKD", path, NULL)) != 0) - return rc; -#if NOTYET - { char buf[20]; - sprintf(buf, " 0%o", mode); - (void) ftpCmd("SITE CHMOD", path, buf); - } -#endif - return rc; -} - -static int ftpChdir(const char * path) { - return ftpCmd("CWD", path, NULL); -} - -static int ftpRmdir(const char * path) { - return ftpCmd("RMD", path, NULL); -} - -static int ftpRename(const char * oldpath, const char * newpath) { - int rc; - if ((rc = ftpCmd("RNFR", oldpath, NULL)) != 0) - return rc; - return ftpCmd("RNTO", newpath, NULL); -} - -static int ftpUnlink(const char * path) { - return ftpCmd("DELE", path, NULL); -} - /* XXX these aren't worth the pain of including correctly */ #if !defined(IAC) #define IAC 255 /* interpret as command: */ @@ -1605,7 +1568,7 @@ static inline int ufdSeek(void * cookie, off_t pos, int whence) { return fdSeek(cookie, pos, whence); } -static int ufdClose( /*@only@*/ void * cookie) +int ufdClose( /*@only@*/ void * cookie) { FD_t fd = c2f(cookie); @@ -1713,7 +1676,7 @@ fprintf(stderr, "-> \r\n"); return fdClose(fd); } -static /*@null@*/ FD_t ftpOpen(const char *url, /*@unused@*/ int flags, +/*@null@*/ FD_t ftpOpen(const char *url, /*@unused@*/ int flags, /*@unused@*/ mode_t mode, /*@out@*/ urlinfo *uret) { urlinfo u = NULL; @@ -2682,1085 +2645,6 @@ ssize_t Pwrite(FD_t fd, const void * buf, size_t count, off_t offset) { return Fwrite(buf, sizeof(char), count, fd); } -/* XXX rebuilddb.c: analogues to mkdir(2)/rmdir(2). */ -int Mkdir (const char *path, mode_t mode) { - const char * lpath; - int ut = urlPath(path, &lpath); - - switch (ut) { - case URL_IS_FTP: - return ftpMkdir(path, mode); - /*@notreached@*/ break; - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - path = lpath; - /*@fallthrough@*/ - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - return mkdir(path, mode); -} - -int Chdir (const char *path) { - const char * lpath; - int ut = urlPath(path, &lpath); - - switch (ut) { - case URL_IS_FTP: - return ftpChdir(path); - /*@notreached@*/ break; - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - path = lpath; - /*@fallthrough@*/ - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - return chdir(path); -} - -int Rmdir (const char *path) { - const char * lpath; - int ut = urlPath(path, &lpath); - - switch (ut) { - case URL_IS_FTP: - return ftpRmdir(path); - /*@notreached@*/ break; - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - path = lpath; - /*@fallthrough@*/ - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - return rmdir(path); -} - -/* XXX rpmdb.c: analogue to rename(2). */ - -int Rename (const char *oldpath, const char * newpath) { - const char *oe = NULL; - const char *ne = NULL; - int oldut, newut; - - /* XXX lib/install.c used to rely on this behavior. */ - if (!strcmp(oldpath, newpath)) return 0; - - oldut = urlPath(oldpath, &oe); - switch (oldut) { - case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - - newut = urlPath(newpath, &ne); - switch (newut) { - case URL_IS_FTP: -if (_rpmio_debug) -fprintf(stderr, "*** rename old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath); - if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) && - !strncasecmp(oldpath, newpath, (oe - oldpath)))) - return -2; - return ftpRename(oldpath, newpath); - /*@notreached@*/ break; - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - oldpath = oe; - newpath = ne; - break; - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - return rename(oldpath, newpath); -} - -int Link (const char *oldpath, const char * newpath) { - const char *oe = NULL; - const char *ne = NULL; - int oldut, newut; - - oldut = urlPath(oldpath, &oe); - switch (oldut) { - case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - - newut = urlPath(newpath, &ne); - switch (newut) { - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: -if (_rpmio_debug) -fprintf(stderr, "*** link old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath); - if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) && - !strncasecmp(oldpath, newpath, (oe - oldpath)))) - return -2; - oldpath = oe; - newpath = ne; - break; - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - return link(oldpath, newpath); -} - -/* XXX build/build.c: analogue to unlink(2). */ - -int Unlink(const char * path) { - const char * lpath; - int ut = urlPath(path, &lpath); - - switch (ut) { - case URL_IS_FTP: - return ftpUnlink(path); - /*@notreached@*/ break; - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - path = lpath; - /*@fallthrough@*/ - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - return unlink(path); -} - -/* XXX swiped from mc-4.5.39-pre9 vfs/ftpfs.c */ - -#define g_strdup xstrdup -#define g_free xfree - -/* - * FIXME: this is broken. It depends on mc not crossing border on month! - */ -static int current_mday; -static int current_mon; -static int current_year; - -/* Following stuff (parse_ls_lga) is used by ftpfs and extfs */ -#define MAXCOLS 30 - -static char *columns [MAXCOLS]; /* Points to the string in column n */ -static int column_ptr [MAXCOLS]; /* Index from 0 to the starting positions of the columns */ - -static int -vfs_split_text (char *p) -{ - char *original = p; - int numcols; - - - for (numcols = 0; *p && numcols < MAXCOLS; numcols++){ - while (*p == ' ' || *p == '\r' || *p == '\n'){ - *p = 0; - p++; - } - columns [numcols] = p; - column_ptr [numcols] = p - original; - while (*p && *p != ' ' && *p != '\r' && *p != '\n') - p++; - } - return numcols; -} - -static int -is_num (int idx) -{ - if (!columns [idx] || columns [idx][0] < '0' || columns [idx][0] > '9') - return 0; - return 1; -} - -static int -is_dos_date(char *str) -{ - if (strlen(str) == 8 && str[2] == str[5] && strchr("\\-/", (int)str[2]) != NULL) - return (1); - - return (0); -} - -static int -is_week (char *str, struct tm *tim) -{ - static char *week = "SunMonTueWedThuFriSat"; - char *pos; - - if((pos=strstr(week, str)) != NULL){ - if(tim != NULL) - tim->tm_wday = (pos - week)/3; - return (1); - } - return (0); -} - -static int -is_month (char *str, struct tm *tim) -{ - static char *month = "JanFebMarAprMayJunJulAugSepOctNovDec"; - char *pos; - - if((pos=strstr(month, str)) != NULL){ - if(tim != NULL) - tim->tm_mon = (pos - month)/3; - return (1); - } - return (0); -} - -static int -is_time (char *str, struct tm *tim) -{ - char *p, *p2; - - if ((p=strchr(str, ':')) && (p2=strrchr(str, ':'))) { - if (p != p2) { - if (sscanf (str, "%2d:%2d:%2d", &tim->tm_hour, &tim->tm_min, &tim->tm_sec) != 3) - return (0); - } - else { - if (sscanf (str, "%2d:%2d", &tim->tm_hour, &tim->tm_min) != 2) - return (0); - } - } - else - return (0); - - return (1); -} - -static int is_year(char *str, struct tm *tim) -{ - long year; - - if (strchr(str,':')) - return (0); - - if (strlen(str)!=4) - return (0); - - if (sscanf(str, "%ld", &year) != 1) - return (0); - - if (year < 1900 || year > 3000) - return (0); - - tim->tm_year = (int) (year - 1900); - - return (1); -} - -/* - * FIXME: this is broken. Consider following entry: - * -rwx------ 1 root root 1 Aug 31 10:04 2904 1234 - * where "2904 1234" is filename. Well, this code decodes it as year :-(. - */ - -static int -vfs_parse_filetype (char c) -{ - switch (c){ - case 'd': return S_IFDIR; - case 'b': return S_IFBLK; - case 'c': return S_IFCHR; - case 'l': return S_IFLNK; - case 's': -#ifdef IS_IFSOCK /* And if not, we fall through to IFIFO, which is pretty close */ - return S_IFSOCK; -#endif - case 'p': return S_IFIFO; - case 'm': case 'n': /* Don't know what these are :-) */ - case '-': case '?': return S_IFREG; - default: return -1; - } -} - -static int vfs_parse_filemode (char *p) -{ /* converts rw-rw-rw- into 0666 */ - int res = 0; - switch (*(p++)){ - case 'r': res |= 0400; break; - case '-': break; - default: return -1; - } - switch (*(p++)){ - case 'w': res |= 0200; break; - case '-': break; - default: return -1; - } - switch (*(p++)){ - case 'x': res |= 0100; break; - case 's': res |= 0100 | S_ISUID; break; - case 'S': res |= S_ISUID; break; - case '-': break; - default: return -1; - } - switch (*(p++)){ - case 'r': res |= 0040; break; - case '-': break; - default: return -1; - } - switch (*(p++)){ - case 'w': res |= 0020; break; - case '-': break; - default: return -1; - } - switch (*(p++)){ - case 'x': res |= 0010; break; - case 's': res |= 0010 | S_ISGID; break; - case 'l': /* Solaris produces these */ - case 'S': res |= S_ISGID; break; - case '-': break; - default: return -1; - } - switch (*(p++)){ - case 'r': res |= 0004; break; - case '-': break; - default: return -1; - } - switch (*(p++)){ - case 'w': res |= 0002; break; - case '-': break; - default: return -1; - } - switch (*(p++)){ - case 'x': res |= 0001; break; - case 't': res |= 0001 | S_ISVTX; break; - case 'T': res |= S_ISVTX; break; - case '-': break; - default: return -1; - } - return res; -} - -static int vfs_parse_filedate(int idx, time_t *t) -{ /* This thing parses from idx in columns[] array */ - - char *p; - struct tm tim; - int d[3]; - int got_year = 0; - - /* Let's setup default time values */ - tim.tm_year = current_year; - tim.tm_mon = current_mon; - tim.tm_mday = current_mday; - tim.tm_hour = 0; - tim.tm_min = 0; - tim.tm_sec = 0; - tim.tm_isdst = -1; /* Let mktime() try to guess correct dst offset */ - - p = columns [idx++]; - - /* We eat weekday name in case of extfs */ - if(is_week(p, &tim)) - p = columns [idx++]; - - /* Month name */ - if(is_month(p, &tim)){ - /* And we expect, it followed by day number */ - if (is_num (idx)) - tim.tm_mday = (int)atol (columns [idx++]); - else - return 0; /* No day */ - - } else { - /* We usually expect: - Mon DD hh:mm - Mon DD YYYY - But in case of extfs we allow these date formats: - Mon DD YYYY hh:mm - Mon DD hh:mm YYYY - Wek Mon DD hh:mm:ss YYYY - MM-DD-YY hh:mm - where Mon is Jan-Dec, DD, MM, YY two digit day, month, year, - YYYY four digit year, hh, mm, ss two digit hour, minute or second. */ - - /* Here just this special case with MM-DD-YY */ - if (is_dos_date(p)){ - p[2] = p[5] = '-'; - - if(sscanf(p, "%2d-%2d-%2d", &d[0], &d[1], &d[2]) == 3){ - /* We expect to get: - 1. MM-DD-YY - 2. DD-MM-YY - 3. YY-MM-DD - 4. YY-DD-MM */ - - /* Hmm... maybe, next time :)*/ - - /* At last, MM-DD-YY */ - d[0]--; /* Months are zerobased */ - /* Y2K madness */ - if(d[2] < 70) - d[2] += 100; - - tim.tm_mon = d[0]; - tim.tm_mday = d[1]; - tim.tm_year = d[2]; - got_year = 1; - } else - return 0; /* sscanf failed */ - } else - return 0; /* unsupported format */ - } - - /* Here we expect to find time and/or year */ - - if (is_num (idx)) { - if(is_time(columns[idx], &tim) || (got_year = is_year(columns[idx], &tim))) { - idx++; - - /* This is a special case for ctime() or Mon DD YYYY hh:mm */ - if(is_num (idx) && - ((got_year = is_year(columns[idx], &tim)) || is_time(columns[idx], &tim))) - idx++; /* time & year or reverse */ - } /* only time or date */ - } - else - return 0; /* Nor time or date */ - - /* - * If the date is less than 6 months in the past, it is shown without year - * other dates in the past or future are shown with year but without time - * This does not check for years before 1900 ... I don't know, how - * to represent them at all - */ - if (!got_year && - current_mon < 6 && current_mon < tim.tm_mon && - tim.tm_mon - current_mon >= 6) - - tim.tm_year--; - - if ((*t = mktime(&tim)) < 0) - *t = 0; - return idx; -} - -static int -vfs_parse_ls_lga (char *p, struct stat *s, char **filename, char **linkname) -{ - int idx, idx2, num_cols; - int i; - char *p_copy; - - if (strncmp (p, "total", 5) == 0) - return 0; - - p_copy = g_strdup(p); -/* XXX FIXME: parse out inode number from "NLST -lai ." */ -/* XXX FIXME: parse out sizein blocks from "NLST -lais ." */ - - if ((i = vfs_parse_filetype(*(p++))) == -1) - goto error; - - s->st_mode = i; - if (*p == ' ') /* Notwell 4 */ - p++; - if (*p == '['){ - if (strlen (p) <= 8 || p [8] != ']') - goto error; - /* Should parse here the Notwell permissions :) */ - if (S_ISDIR (s->st_mode)) - s->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IXUSR | S_IXGRP | S_IXOTH); - else - s->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR); - p += 9; - } else { - if ((i = vfs_parse_filemode(p)) == -1) - goto error; - s->st_mode |= i; - p += 9; - - /* This is for an extra ACL attribute (HP-UX) */ - if (*p == '+') - p++; - } - - g_free(p_copy); - p_copy = g_strdup(p); - num_cols = vfs_split_text (p); - - s->st_nlink = atol (columns [0]); - if (s->st_nlink < 0) - goto error; - - if (!is_num (1)) -#ifdef HACK - s->st_uid = finduid (columns [1]); -#else - unameToUid (columns [1], &s->st_uid); -#endif - else - s->st_uid = (uid_t) atol (columns [1]); - - /* Mhm, the ls -lg did not produce a group field */ - for (idx = 3; idx <= 5; idx++) - if (is_month(columns [idx], NULL) || is_week(columns [idx], NULL) || is_dos_date(columns[idx])) - break; - - if (idx == 6 || (idx == 5 && !S_ISCHR (s->st_mode) && !S_ISBLK (s->st_mode))) - goto error; - - /* We don't have gid */ - if (idx == 3 || (idx == 4 && (S_ISCHR(s->st_mode) || S_ISBLK (s->st_mode)))) - idx2 = 2; - else { - /* We have gid field */ - if (is_num (2)) - s->st_gid = (gid_t) atol (columns [2]); - else -#ifdef HACK - s->st_gid = findgid (columns [2]); -#else - gnameToGid (columns [1], &s->st_gid); -#endif - idx2 = 3; - } - - /* This is device */ - if (S_ISCHR (s->st_mode) || S_ISBLK (s->st_mode)){ - int maj, min; - - if (!is_num (idx2) || sscanf(columns [idx2], " %d,", &maj) != 1) - goto error; - - if (!is_num (++idx2) || sscanf(columns [idx2], " %d", &min) != 1) - goto error; - -#ifdef HAVE_ST_RDEV - s->st_rdev = ((maj & 0xff) << 8) | (min & 0xffff00ff); -#endif - s->st_size = 0; - - } else { - /* Common file size */ - if (!is_num (idx2)) - goto error; - - s->st_size = (size_t) atol (columns [idx2]); -#ifdef HAVE_ST_RDEV - s->st_rdev = 0; -#endif - } - - idx = vfs_parse_filedate(idx, &s->st_mtime); - if (!idx) - goto error; - /* Use resulting time value */ - s->st_atime = s->st_ctime = s->st_mtime; - s->st_dev = 0; - s->st_ino = 0; -#ifdef HAVE_ST_BLKSIZE - s->st_blksize = 512; -#endif -#ifdef HAVE_ST_BLOCKS - s->st_blocks = (s->st_size + 511) / 512; -#endif - - for (i = idx + 1, idx2 = 0; i < num_cols; i++ ) - if (strcmp (columns [i], "->") == 0){ - idx2 = i; - break; - } - - if (((S_ISLNK (s->st_mode) || - (num_cols == idx + 3 && s->st_nlink > 1))) /* Maybe a hardlink? (in extfs) */ - && idx2){ - int p; - char *s; - - if (filename){ -#ifdef HACK - s = g_strndup (p_copy + column_ptr [idx], column_ptr [idx2] - column_ptr [idx] - 1); -#else - int nb = column_ptr [idx2] - column_ptr [idx] - 1; - s = xmalloc(nb+1); - strncpy(s, p_copy + column_ptr [idx], nb); -#endif - *filename = s; - } - if (linkname){ - s = g_strdup (p_copy + column_ptr [idx2+1]); - p = strlen (s); - if (s [p-1] == '\r' || s [p-1] == '\n') - s [p-1] = 0; - if (s [p-2] == '\r' || s [p-2] == '\n') - s [p-2] = 0; - - *linkname = s; - } - } else { - /* Extract the filename from the string copy, not from the columns - * this way we have a chance of entering hidden directories like ". ." - */ - if (filename){ - /* - *filename = g_strdup (columns [idx++]); - */ - int p; - char *s; - - s = g_strdup (p_copy + column_ptr [idx++]); - p = strlen (s); - /* g_strchomp(); */ - if (s [p-1] == '\r' || s [p-1] == '\n') - s [p-1] = 0; - if (s [p-2] == '\r' || s [p-2] == '\n') - s [p-2] = 0; - - *filename = s; - } - if (linkname) - *linkname = NULL; - } - g_free (p_copy); - return 1; - -error: -#ifdef HACK - { - static int errorcount = 0; - - if (++errorcount < 5) { - message_1s (1, "Could not parse:", p_copy); - } else if (errorcount == 5) - message_1s (1, "More parsing errors will be ignored.", "(sorry)" ); - } -#endif - - if (p_copy != p) /* Carefull! */ - g_free (p_copy); - return 0; -} - -typedef enum { - DO_FTP_STAT = 1, - DO_FTP_LSTAT = 2, - DO_FTP_READLINK = 3, - DO_FTP_ACCESS = 4, - DO_FTP_GLOB = 5 -} ftpSysCall_t; -static size_t ftpBufAlloced = 0; -static char * ftpBuf = NULL; - -#define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s)) - -static int ftpNLST(const char * url, ftpSysCall_t ftpSysCall, - struct stat * st, char * rlbuf, size_t rlbufsiz) -{ - FD_t fd; - const char * path; - int bufLength, moretodo; - const char *n, *ne, *o, *oe; - char * s; - char * se; - const char * urldn; - char * bn = NULL; - int nbn = 0; - urlinfo u; - int rc; - - n = ne = o = oe = NULL; - (void) urlPath(url, &path); - if (*path == '\0') - return -2; - - switch (ftpSysCall) { - case DO_FTP_GLOB: - fd = ftpOpen(url, 0, 0, &u); - if (fd == NULL || u == NULL) - return -1; - - u->openError = ftpReq(fd, "NLST", path); - break; - default: - urldn = alloca_strdup(url); - if ((bn = strrchr(urldn, '/')) == NULL) - return -2; - else if (bn == path) - bn = "."; - else - *bn++ = '\0'; - nbn = strlen(bn); - - rc = ftpChdir(urldn); /* XXX don't care about CWD */ - if (rc < 0) - return rc; - - fd = ftpOpen(url, 0, 0, &u); - if (fd == NULL || u == NULL) - return -1; - - /* XXX possibly should do "NLST -lais" to get st_ino/st_blocks also */ - u->openError = ftpReq(fd, "NLST", "-la"); - break; - } - - if (u->openError < 0) { - fd = fdLink(fd, "error data (ftpStat)"); - rc = -2; - goto exit; - } - - if (ftpBufAlloced == 0 || ftpBuf == NULL) { - ftpBufAlloced = url_iobuf_size; - ftpBuf = xcalloc(ftpBufAlloced, sizeof(ftpBuf[0])); - } - *ftpBuf = '\0'; - - bufLength = 0; - moretodo = 1; - - do { - - /* XXX FIXME: realloc ftpBuf is < ~128 chars remain */ - if ((ftpBufAlloced - bufLength) < (1024+80)) { - ftpBufAlloced <<= 2; - ftpBuf = xrealloc(ftpBuf, ftpBufAlloced); - } - s = se = ftpBuf + bufLength; - *se = '\0'; - - rc = fdFgets(fd, se, (ftpBufAlloced - bufLength)); - if (rc <= 0) { - moretodo = 0; - break; - } - if (ftpSysCall == DO_FTP_GLOB) { /* XXX HACK */ - bufLength += strlen(se); - continue; - } - - for (s = se; *s != '\0'; s = se) { - int bingo; - - while (*se && *se != '\n') se++; - if (se > s && se[-1] == '\r') se[-1] = '\0'; - if (*se == '\0') break; - *se++ = '\0'; - - if (!strncmp(s, "total ", sizeof("total ")-1)) continue; - - o = NULL; - for (bingo = 0, n = se; n >= s; n--) { - switch (*n) { - case '\0': - oe = ne = n; - break; - case ' ': - if (o || !(n[-3] == ' ' && n[-2] == '-' && n[-1] == '>')) { - while (*(++n) == ' '); - bingo++; - break; - } - for (o = n + 1; *o == ' '; o++); - n -= 3; - ne = n; - break; - default: - break; - } - if (bingo) break; - } - - if (nbn != (ne - n)) continue; /* Same name length? */ - if (strncmp(n, bn, nbn)) continue; /* Same name? */ - - moretodo = 0; - break; - } - - if (moretodo && se > s) { - bufLength = se - s - 1; - if (s != ftpBuf) - memmove(ftpBuf, s, bufLength); - } else { - bufLength = 0; - } - } while (moretodo); - - switch (ftpSysCall) { - case DO_FTP_STAT: - if (o && oe) { - /* XXX FIXME: symlink, replace urldn/bn from [o,oe) and restart */ - } - /*@fallthrough@*/ - case DO_FTP_LSTAT: - if (st == NULL || !(n && ne)) { - rc = -1; - } else { - rc = ((vfs_parse_ls_lga(s, st, NULL, NULL) > 0) ? 0 : -1); - } - break; - case DO_FTP_READLINK: - if (rlbuf == NULL || !(o && oe)) { - rc = -1; - } else { - rc = oe - o; - if (rc > rlbufsiz) - rc = rlbufsiz; - memcpy(rlbuf, o, rc); - if (rc < rlbufsiz) - rlbuf[rc] = '\0'; - } - break; - case DO_FTP_ACCESS: - rc = 0; /* XXX WRONG WRONG WRONG */ - break; - case DO_FTP_GLOB: - rc = 0; /* XXX WRONG WRONG WRONG */ - break; - } - -exit: - ufdClose(fd); - return rc; -} - -static int ftpStat(const char * path, struct stat *st) -{ - return ftpNLST(path, DO_FTP_STAT, st, NULL, 0); -} - -static int ftpLstat(const char * path, struct stat *st) { - int rc; - rc = ftpNLST(path, DO_FTP_LSTAT, st, NULL, 0); -if (_rpmio_debug) -fprintf(stderr, "*** ftpLstat(%s) rc %d\n", path, rc); - return rc; -} - -static int ftpReadlink(const char * path, char * buf, size_t bufsiz) { - return ftpNLST(path, DO_FTP_READLINK, NULL, buf, bufsiz); -} - -static int ftpGlob(const char * path, int flags, - int errfunc(const char * epath, int eerno), glob_t * pglob) -{ - int rc; - - if (pglob == NULL) - return -2; - rc = ftpNLST(path, DO_FTP_GLOB, NULL, NULL, 0); -if (_rpmio_debug) -fprintf(stderr, "*** ftpGlob(%s,0x%x,%p,%p) ftpNLST rc %d\n", path, flags, errfunc, pglob, rc); - if (rc) - return rc; - rc = poptParseArgvString(ftpBuf, &pglob->gl_pathc, (const char ***)&pglob->gl_pathv); - pglob->gl_offs = -1; /* XXX HACK HACK HACK */ - return rc; -} - -static void ftpGlobfree(glob_t * pglob) { -if (_rpmio_debug) -fprintf(stderr, "*** ftpGlobfree(%p)\n", pglob); - if (pglob->gl_offs == -1) /* XXX HACK HACK HACK */ - xfree(pglob->gl_pathv); -} - -int Stat(const char * path, struct stat * st) { - const char * lpath; - int ut = urlPath(path, &lpath); - -if (_rpmio_debug) -fprintf(stderr, "*** Stat(%s,%p)\n", path, st); - switch (ut) { - case URL_IS_FTP: - return ftpStat(path, st); - /*@notreached@*/ break; - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - path = lpath; - /*@fallthrough@*/ - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - return stat(path, st); -} - -int Lstat(const char * path, struct stat * st) { - const char * lpath; - int ut = urlPath(path, &lpath); - -if (_rpmio_debug) -fprintf(stderr, "*** Lstat(%s,%p)\n", path, st); - switch (ut) { - case URL_IS_FTP: - return ftpLstat(path, st); - /*@notreached@*/ break; - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - path = lpath; - /*@fallthrough@*/ - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - return lstat(path, st); -} - -int Readlink(const char * path, char * buf, size_t bufsiz) { - const char * lpath; - int ut = urlPath(path, &lpath); - - switch (ut) { - case URL_IS_FTP: - return ftpReadlink(path, buf, bufsiz); - /*@notreached@*/ break; - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - path = lpath; - /*@fallthrough@*/ - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - return readlink(path, buf, bufsiz); -} - -int Access(const char * path, int amode) { - const char * lpath; - int ut = urlPath(path, &lpath); - -if (_rpmio_debug) -fprintf(stderr, "*** Access(%s,%d)\n", path, amode); - switch (ut) { - case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - path = lpath; - /*@fallthrough@*/ - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - return access(path, amode); -} - -int Glob(const char *path, int flags, - int errfunc(const char * epath, int eerrno), glob_t *pglob) -{ - const char * lpath; - int ut = urlPath(path, &lpath); - -if (_rpmio_debug) -fprintf(stderr, "*** Glob(%s,0x%x,%p,%p)\n", path, flags, errfunc, pglob); - switch (ut) { - case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ - return ftpGlob(path, flags, errfunc, pglob); - /*@notreached@*/ break; - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - path = lpath; - /*@fallthrough@*/ - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return -2; - /*@notreached@*/ break; - } - return glob(path, flags, errfunc, pglob); -} - -void Globfree(glob_t *pglob) -{ -if (_rpmio_debug) -fprintf(stderr, "*** Globfree(%p)\n", pglob); - if (pglob->gl_offs == -1) /* XXX HACK HACK HACK */ - ftpGlobfree(pglob); - else - globfree(pglob); -} - -DIR * Opendir(const char * path) -{ - const char * lpath; - int ut = urlPath(path, &lpath); - -if (_rpmio_debug) -fprintf(stderr, "*** Opendir(%s)\n", path); - switch (ut) { - case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ - case URL_IS_PATH: - path = lpath; - /*@fallthrough@*/ - case URL_IS_UNKNOWN: - break; - case URL_IS_DASH: - default: - return NULL; - /*@notreached@*/ break; - } - return opendir(path); -} - -struct dirent * Readdir(DIR * dir) -{ -if (_rpmio_debug) -fprintf(stderr, "*** Readdir(%p)\n", dir); - return readdir(dir); -} - -int Closedir(DIR * dir) -{ -if (_rpmio_debug) -fprintf(stderr, "*** Closedir(%p)\n", dir); - return closedir(dir); -} - static struct FDIO_s fpio_s = { ufdRead, ufdWrite, fdSeek, ufdClose, XfdLink, XfdFree, XfdNew, fdFileno, ufdOpen, NULL, fdGetFp, NULL, Mkdir, Chdir, Rmdir, Rename, Unlink diff --git a/rpmio/rpmio_internal.h b/rpmio/rpmio_internal.h index 6a61f6224..2146dd8aa 100644 --- a/rpmio/rpmio_internal.h +++ b/rpmio/rpmio_internal.h @@ -3,6 +3,7 @@ #include #include +#include typedef struct _FDSTACK_s { FDIO_t io; @@ -56,9 +57,31 @@ struct _FD_s { }; /*@access FD_t */ -#include #define FDSANE(fd) assert(fd && fd->magic == FDMAGIC) +extern int _rpmio_debug; + +#define DBG(_f, _m, _x) \ + if ((_rpmio_debug | ((_f) ? ((FD_t)(_f))->flags : 0)) & (_m)) fprintf _x + +#define DBGIO(_f, _x) DBG((_f), RPMIO_DEBUG_IO, _x) +#define DBGREFS(_f, _x) DBG((_f), RPMIO_DEBUG_REFS, _x) + +#define xfree(_p) free((void *)_p) + +#ifdef __cplusplus +extern "C" { +#endif + +int fdFgets(FD_t fd, char * buf, size_t len); + +/*@null@*/ FD_t ftpOpen(const char *url, /*@unused@*/ int flags, + /*@unused@*/ mode_t mode, /*@out@*/ urlinfo *uret); +int ftpReq(FD_t data, const char * ftpCmd, const char * ftpArg); +int ftpCmd(const char * cmd, const char * url, const char * arg2); + +int ufdClose( /*@only@*/ void * cookie); + static inline /*@null@*/ const FDIO_t fdGetIo(FD_t fd) { FDSANE(fd); return fd->fps[fd->nfps].io; @@ -241,4 +264,8 @@ static inline void fadSetFirstFree(FD_t fd, unsigned int firstFree) { fd->firstFree = firstFree; } +#ifdef __cplusplus +} +#endif + #endif /* H_RPMIO_INTERNAL */ diff --git a/rpmio/rpmmessages.h b/rpmio/rpmmessages.h new file mode 100644 index 000000000..67f2d1cc9 --- /dev/null +++ b/rpmio/rpmmessages.h @@ -0,0 +1,43 @@ +#ifndef H_RPMMESSAGES +#define H_RPMMESSAGES + +#define RPMMESS_DEBUG 1 +#define RPMMESS_VERBOSE 2 +#define RPMMESS_NORMAL 3 +#define RPMMESS_WARNING 4 +#define RPMMESS_ERROR 5 +#define RPMMESS_FATALERROR 6 + +#define RPMMESS_QUIET (RPMMESS_NORMAL + 1) + +typedef enum rpmCallbackType_e { + RPMCALLBACK_INST_PROGRESS, RPMCALLBACK_INST_START, + RPMCALLBACK_INST_OPEN_FILE, RPMCALLBACK_INST_CLOSE_FILE, + RPMCALLBACK_TRANS_PROGRESS, RPMCALLBACK_TRANS_START, RPMCALLBACK_TRANS_STOP, + RPMCALLBACK_UNINST_PROGRESS, RPMCALLBACK_UNINST_START, RPMCALLBACK_UNINST_STOP +} rpmCallbackType; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void * (*rpmCallbackFunction)(const void * h, + const rpmCallbackType what, + const unsigned long amount, + const unsigned long total, + const void * pkgKey, void * data); + +void urlSetCallback(rpmCallbackFunction notify, void *notifyData, int notifyCount); + +void rpmIncreaseVerbosity(void); +void rpmSetVerbosity(int level); +int rpmGetVerbosity(void); +int rpmIsVerbose(void); +int rpmIsDebug(void); +void rpmMessage(int level, const char * format, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* H_RPMMESSAGES */ diff --git a/rpmio/rpmrpc.c b/rpmio/rpmrpc.c new file mode 100644 index 000000000..bf69c154c --- /dev/null +++ b/rpmio/rpmrpc.c @@ -0,0 +1,1120 @@ +#include "system.h" + +#include +#include +#include "ugid.h" + +extern int _rpmio_debug; + +/* =============================================================== */ +static int ftpMkdir(const char * path, /*@unused@*/ mode_t mode) { + int rc; + if ((rc = ftpCmd("MKD", path, NULL)) != 0) + return rc; +#if NOTYET + { char buf[20]; + sprintf(buf, " 0%o", mode); + (void) ftpCmd("SITE CHMOD", path, buf); + } +#endif + return rc; +} + +static int ftpChdir(const char * path) { + return ftpCmd("CWD", path, NULL); +} + +static int ftpRmdir(const char * path) { + return ftpCmd("RMD", path, NULL); +} + +static int ftpRename(const char * oldpath, const char * newpath) { + int rc; + if ((rc = ftpCmd("RNFR", oldpath, NULL)) != 0) + return rc; + return ftpCmd("RNTO", newpath, NULL); +} + +static int ftpUnlink(const char * path) { + return ftpCmd("DELE", path, NULL); +} + +/* =============================================================== */ +/* XXX rebuilddb.c: analogues to mkdir(2)/rmdir(2). */ +int Mkdir (const char *path, mode_t mode) { + const char * lpath; + int ut = urlPath(path, &lpath); + + switch (ut) { + case URL_IS_FTP: + return ftpMkdir(path, mode); + /*@notreached@*/ break; + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + path = lpath; + /*@fallthrough@*/ + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + return mkdir(path, mode); +} + +int Chdir (const char *path) { + const char * lpath; + int ut = urlPath(path, &lpath); + + switch (ut) { + case URL_IS_FTP: + return ftpChdir(path); + /*@notreached@*/ break; + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + path = lpath; + /*@fallthrough@*/ + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + return chdir(path); +} + +int Rmdir (const char *path) { + const char * lpath; + int ut = urlPath(path, &lpath); + + switch (ut) { + case URL_IS_FTP: + return ftpRmdir(path); + /*@notreached@*/ break; + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + path = lpath; + /*@fallthrough@*/ + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + return rmdir(path); +} + +/* XXX rpmdb.c: analogue to rename(2). */ + +int Rename (const char *oldpath, const char * newpath) { + const char *oe = NULL; + const char *ne = NULL; + int oldut, newut; + + /* XXX lib/install.c used to rely on this behavior. */ + if (!strcmp(oldpath, newpath)) return 0; + + oldut = urlPath(oldpath, &oe); + switch (oldut) { + case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + + newut = urlPath(newpath, &ne); + switch (newut) { + case URL_IS_FTP: +if (_rpmio_debug) +fprintf(stderr, "*** rename old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath); + if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) && + !strncasecmp(oldpath, newpath, (oe - oldpath)))) + return -2; + return ftpRename(oldpath, newpath); + /*@notreached@*/ break; + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + oldpath = oe; + newpath = ne; + break; + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + return rename(oldpath, newpath); +} + +int Link (const char *oldpath, const char * newpath) { + const char *oe = NULL; + const char *ne = NULL; + int oldut, newut; + + oldut = urlPath(oldpath, &oe); + switch (oldut) { + case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + + newut = urlPath(newpath, &ne); + switch (newut) { + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: +if (_rpmio_debug) +fprintf(stderr, "*** link old %*s new %*s\n", (int)(oe - oldpath), oldpath, (int)(ne - newpath), newpath); + if (!(oldut == newut && oe && ne && (oe - oldpath) == (ne - newpath) && + !strncasecmp(oldpath, newpath, (oe - oldpath)))) + return -2; + oldpath = oe; + newpath = ne; + break; + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + return link(oldpath, newpath); +} + +/* XXX build/build.c: analogue to unlink(2). */ + +int Unlink(const char * path) { + const char * lpath; + int ut = urlPath(path, &lpath); + + switch (ut) { + case URL_IS_FTP: + return ftpUnlink(path); + /*@notreached@*/ break; + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + path = lpath; + /*@fallthrough@*/ + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + return unlink(path); +} + +/* XXX swiped from mc-4.5.39-pre9 vfs/ftpfs.c */ + +#define g_strdup xstrdup +#define g_free xfree + +/* + * FIXME: this is broken. It depends on mc not crossing border on month! + */ +static int current_mday; +static int current_mon; +static int current_year; + +/* Following stuff (parse_ls_lga) is used by ftpfs and extfs */ +#define MAXCOLS 30 + +static char *columns [MAXCOLS]; /* Points to the string in column n */ +static int column_ptr [MAXCOLS]; /* Index from 0 to the starting positions of the columns */ + +static int +vfs_split_text (char *p) +{ + char *original = p; + int numcols; + + + for (numcols = 0; *p && numcols < MAXCOLS; numcols++){ + while (*p == ' ' || *p == '\r' || *p == '\n'){ + *p = 0; + p++; + } + columns [numcols] = p; + column_ptr [numcols] = p - original; + while (*p && *p != ' ' && *p != '\r' && *p != '\n') + p++; + } + return numcols; +} + +static int +is_num (int idx) +{ + if (!columns [idx] || columns [idx][0] < '0' || columns [idx][0] > '9') + return 0; + return 1; +} + +static int +is_dos_date(char *str) +{ + if (strlen(str) == 8 && str[2] == str[5] && strchr("\\-/", (int)str[2]) != NULL) + return (1); + + return (0); +} + +static int +is_week (char *str, struct tm *tim) +{ + static char *week = "SunMonTueWedThuFriSat"; + char *pos; + + if((pos=strstr(week, str)) != NULL){ + if(tim != NULL) + tim->tm_wday = (pos - week)/3; + return (1); + } + return (0); +} + +static int +is_month (char *str, struct tm *tim) +{ + static char *month = "JanFebMarAprMayJunJulAugSepOctNovDec"; + char *pos; + + if((pos=strstr(month, str)) != NULL){ + if(tim != NULL) + tim->tm_mon = (pos - month)/3; + return (1); + } + return (0); +} + +static int +is_time (char *str, struct tm *tim) +{ + char *p, *p2; + + if ((p=strchr(str, ':')) && (p2=strrchr(str, ':'))) { + if (p != p2) { + if (sscanf (str, "%2d:%2d:%2d", &tim->tm_hour, &tim->tm_min, &tim->tm_sec) != 3) + return (0); + } + else { + if (sscanf (str, "%2d:%2d", &tim->tm_hour, &tim->tm_min) != 2) + return (0); + } + } + else + return (0); + + return (1); +} + +static int is_year(char *str, struct tm *tim) +{ + long year; + + if (strchr(str,':')) + return (0); + + if (strlen(str)!=4) + return (0); + + if (sscanf(str, "%ld", &year) != 1) + return (0); + + if (year < 1900 || year > 3000) + return (0); + + tim->tm_year = (int) (year - 1900); + + return (1); +} + +/* + * FIXME: this is broken. Consider following entry: + * -rwx------ 1 root root 1 Aug 31 10:04 2904 1234 + * where "2904 1234" is filename. Well, this code decodes it as year :-(. + */ + +static int +vfs_parse_filetype (char c) +{ + switch (c){ + case 'd': return S_IFDIR; + case 'b': return S_IFBLK; + case 'c': return S_IFCHR; + case 'l': return S_IFLNK; + case 's': +#ifdef IS_IFSOCK /* And if not, we fall through to IFIFO, which is pretty close */ + return S_IFSOCK; +#endif + case 'p': return S_IFIFO; + case 'm': case 'n': /* Don't know what these are :-) */ + case '-': case '?': return S_IFREG; + default: return -1; + } +} + +static int vfs_parse_filemode (char *p) +{ /* converts rw-rw-rw- into 0666 */ + int res = 0; + switch (*(p++)){ + case 'r': res |= 0400; break; + case '-': break; + default: return -1; + } + switch (*(p++)){ + case 'w': res |= 0200; break; + case '-': break; + default: return -1; + } + switch (*(p++)){ + case 'x': res |= 0100; break; + case 's': res |= 0100 | S_ISUID; break; + case 'S': res |= S_ISUID; break; + case '-': break; + default: return -1; + } + switch (*(p++)){ + case 'r': res |= 0040; break; + case '-': break; + default: return -1; + } + switch (*(p++)){ + case 'w': res |= 0020; break; + case '-': break; + default: return -1; + } + switch (*(p++)){ + case 'x': res |= 0010; break; + case 's': res |= 0010 | S_ISGID; break; + case 'l': /* Solaris produces these */ + case 'S': res |= S_ISGID; break; + case '-': break; + default: return -1; + } + switch (*(p++)){ + case 'r': res |= 0004; break; + case '-': break; + default: return -1; + } + switch (*(p++)){ + case 'w': res |= 0002; break; + case '-': break; + default: return -1; + } + switch (*(p++)){ + case 'x': res |= 0001; break; + case 't': res |= 0001 | S_ISVTX; break; + case 'T': res |= S_ISVTX; break; + case '-': break; + default: return -1; + } + return res; +} + +static int vfs_parse_filedate(int idx, time_t *t) +{ /* This thing parses from idx in columns[] array */ + + char *p; + struct tm tim; + int d[3]; + int got_year = 0; + + /* Let's setup default time values */ + tim.tm_year = current_year; + tim.tm_mon = current_mon; + tim.tm_mday = current_mday; + tim.tm_hour = 0; + tim.tm_min = 0; + tim.tm_sec = 0; + tim.tm_isdst = -1; /* Let mktime() try to guess correct dst offset */ + + p = columns [idx++]; + + /* We eat weekday name in case of extfs */ + if(is_week(p, &tim)) + p = columns [idx++]; + + /* Month name */ + if(is_month(p, &tim)){ + /* And we expect, it followed by day number */ + if (is_num (idx)) + tim.tm_mday = (int)atol (columns [idx++]); + else + return 0; /* No day */ + + } else { + /* We usually expect: + Mon DD hh:mm + Mon DD YYYY + But in case of extfs we allow these date formats: + Mon DD YYYY hh:mm + Mon DD hh:mm YYYY + Wek Mon DD hh:mm:ss YYYY + MM-DD-YY hh:mm + where Mon is Jan-Dec, DD, MM, YY two digit day, month, year, + YYYY four digit year, hh, mm, ss two digit hour, minute or second. */ + + /* Here just this special case with MM-DD-YY */ + if (is_dos_date(p)){ + p[2] = p[5] = '-'; + + if(sscanf(p, "%2d-%2d-%2d", &d[0], &d[1], &d[2]) == 3){ + /* We expect to get: + 1. MM-DD-YY + 2. DD-MM-YY + 3. YY-MM-DD + 4. YY-DD-MM */ + + /* Hmm... maybe, next time :)*/ + + /* At last, MM-DD-YY */ + d[0]--; /* Months are zerobased */ + /* Y2K madness */ + if(d[2] < 70) + d[2] += 100; + + tim.tm_mon = d[0]; + tim.tm_mday = d[1]; + tim.tm_year = d[2]; + got_year = 1; + } else + return 0; /* sscanf failed */ + } else + return 0; /* unsupported format */ + } + + /* Here we expect to find time and/or year */ + + if (is_num (idx)) { + if(is_time(columns[idx], &tim) || (got_year = is_year(columns[idx], &tim))) { + idx++; + + /* This is a special case for ctime() or Mon DD YYYY hh:mm */ + if(is_num (idx) && + ((got_year = is_year(columns[idx], &tim)) || is_time(columns[idx], &tim))) + idx++; /* time & year or reverse */ + } /* only time or date */ + } + else + return 0; /* Nor time or date */ + + /* + * If the date is less than 6 months in the past, it is shown without year + * other dates in the past or future are shown with year but without time + * This does not check for years before 1900 ... I don't know, how + * to represent them at all + */ + if (!got_year && + current_mon < 6 && current_mon < tim.tm_mon && + tim.tm_mon - current_mon >= 6) + + tim.tm_year--; + + if ((*t = mktime(&tim)) < 0) + *t = 0; + return idx; +} + +static int +vfs_parse_ls_lga (char *p, struct stat *s, char **filename, char **linkname) +{ + int idx, idx2, num_cols; + int i; + char *p_copy; + + if (strncmp (p, "total", 5) == 0) + return 0; + + p_copy = g_strdup(p); +/* XXX FIXME: parse out inode number from "NLST -lai ." */ +/* XXX FIXME: parse out sizein blocks from "NLST -lais ." */ + + if ((i = vfs_parse_filetype(*(p++))) == -1) + goto error; + + s->st_mode = i; + if (*p == ' ') /* Notwell 4 */ + p++; + if (*p == '['){ + if (strlen (p) <= 8 || p [8] != ']') + goto error; + /* Should parse here the Notwell permissions :) */ + if (S_ISDIR (s->st_mode)) + s->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR | S_IXUSR | S_IXGRP | S_IXOTH); + else + s->st_mode |= (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR); + p += 9; + } else { + if ((i = vfs_parse_filemode(p)) == -1) + goto error; + s->st_mode |= i; + p += 9; + + /* This is for an extra ACL attribute (HP-UX) */ + if (*p == '+') + p++; + } + + g_free(p_copy); + p_copy = g_strdup(p); + num_cols = vfs_split_text (p); + + s->st_nlink = atol (columns [0]); + if (s->st_nlink < 0) + goto error; + + if (!is_num (1)) +#ifdef HACK + s->st_uid = finduid (columns [1]); +#else + unameToUid (columns [1], &s->st_uid); +#endif + else + s->st_uid = (uid_t) atol (columns [1]); + + /* Mhm, the ls -lg did not produce a group field */ + for (idx = 3; idx <= 5; idx++) + if (is_month(columns [idx], NULL) || is_week(columns [idx], NULL) || is_dos_date(columns[idx])) + break; + + if (idx == 6 || (idx == 5 && !S_ISCHR (s->st_mode) && !S_ISBLK (s->st_mode))) + goto error; + + /* We don't have gid */ + if (idx == 3 || (idx == 4 && (S_ISCHR(s->st_mode) || S_ISBLK (s->st_mode)))) + idx2 = 2; + else { + /* We have gid field */ + if (is_num (2)) + s->st_gid = (gid_t) atol (columns [2]); + else +#ifdef HACK + s->st_gid = findgid (columns [2]); +#else + gnameToGid (columns [1], &s->st_gid); +#endif + idx2 = 3; + } + + /* This is device */ + if (S_ISCHR (s->st_mode) || S_ISBLK (s->st_mode)){ + int maj, min; + + if (!is_num (idx2) || sscanf(columns [idx2], " %d,", &maj) != 1) + goto error; + + if (!is_num (++idx2) || sscanf(columns [idx2], " %d", &min) != 1) + goto error; + +#ifdef HAVE_ST_RDEV + s->st_rdev = ((maj & 0xff) << 8) | (min & 0xffff00ff); +#endif + s->st_size = 0; + + } else { + /* Common file size */ + if (!is_num (idx2)) + goto error; + + s->st_size = (size_t) atol (columns [idx2]); +#ifdef HAVE_ST_RDEV + s->st_rdev = 0; +#endif + } + + idx = vfs_parse_filedate(idx, &s->st_mtime); + if (!idx) + goto error; + /* Use resulting time value */ + s->st_atime = s->st_ctime = s->st_mtime; + s->st_dev = 0; + s->st_ino = 0; +#ifdef HAVE_ST_BLKSIZE + s->st_blksize = 512; +#endif +#ifdef HAVE_ST_BLOCKS + s->st_blocks = (s->st_size + 511) / 512; +#endif + + for (i = idx + 1, idx2 = 0; i < num_cols; i++ ) + if (strcmp (columns [i], "->") == 0){ + idx2 = i; + break; + } + + if (((S_ISLNK (s->st_mode) || + (num_cols == idx + 3 && s->st_nlink > 1))) /* Maybe a hardlink? (in extfs) */ + && idx2){ + int p; + char *s; + + if (filename){ +#ifdef HACK + s = g_strndup (p_copy + column_ptr [idx], column_ptr [idx2] - column_ptr [idx] - 1); +#else + int nb = column_ptr [idx2] - column_ptr [idx] - 1; + s = xmalloc(nb+1); + strncpy(s, p_copy + column_ptr [idx], nb); +#endif + *filename = s; + } + if (linkname){ + s = g_strdup (p_copy + column_ptr [idx2+1]); + p = strlen (s); + if (s [p-1] == '\r' || s [p-1] == '\n') + s [p-1] = 0; + if (s [p-2] == '\r' || s [p-2] == '\n') + s [p-2] = 0; + + *linkname = s; + } + } else { + /* Extract the filename from the string copy, not from the columns + * this way we have a chance of entering hidden directories like ". ." + */ + if (filename){ + /* + *filename = g_strdup (columns [idx++]); + */ + int p; + char *s; + + s = g_strdup (p_copy + column_ptr [idx++]); + p = strlen (s); + /* g_strchomp(); */ + if (s [p-1] == '\r' || s [p-1] == '\n') + s [p-1] = 0; + if (s [p-2] == '\r' || s [p-2] == '\n') + s [p-2] = 0; + + *filename = s; + } + if (linkname) + *linkname = NULL; + } + g_free (p_copy); + return 1; + +error: +#ifdef HACK + { + static int errorcount = 0; + + if (++errorcount < 5) { + message_1s (1, "Could not parse:", p_copy); + } else if (errorcount == 5) + message_1s (1, "More parsing errors will be ignored.", "(sorry)" ); + } +#endif + + if (p_copy != p) /* Carefull! */ + g_free (p_copy); + return 0; +} + +typedef enum { + DO_FTP_STAT = 1, + DO_FTP_LSTAT = 2, + DO_FTP_READLINK = 3, + DO_FTP_ACCESS = 4, + DO_FTP_GLOB = 5 +} ftpSysCall_t; +static size_t ftpBufAlloced = 0; +static char * ftpBuf = NULL; + +#define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s)) + +static int ftpNLST(const char * url, ftpSysCall_t ftpSysCall, + struct stat * st, char * rlbuf, size_t rlbufsiz) +{ + FD_t fd; + const char * path; + int bufLength, moretodo; + const char *n, *ne, *o, *oe; + char * s; + char * se; + const char * urldn; + char * bn = NULL; + int nbn = 0; + urlinfo u; + int rc; + + n = ne = o = oe = NULL; + (void) urlPath(url, &path); + if (*path == '\0') + return -2; + + switch (ftpSysCall) { + case DO_FTP_GLOB: + fd = ftpOpen(url, 0, 0, &u); + if (fd == NULL || u == NULL) + return -1; + + u->openError = ftpReq(fd, "NLST", path); + break; + default: + urldn = alloca_strdup(url); + if ((bn = strrchr(urldn, '/')) == NULL) + return -2; + else if (bn == path) + bn = "."; + else + *bn++ = '\0'; + nbn = strlen(bn); + + rc = ftpChdir(urldn); /* XXX don't care about CWD */ + if (rc < 0) + return rc; + + fd = ftpOpen(url, 0, 0, &u); + if (fd == NULL || u == NULL) + return -1; + + /* XXX possibly should do "NLST -lais" to get st_ino/st_blocks also */ + u->openError = ftpReq(fd, "NLST", "-la"); + break; + } + + if (u->openError < 0) { + fd = fdLink(fd, "error data (ftpStat)"); + rc = -2; + goto exit; + } + + if (ftpBufAlloced == 0 || ftpBuf == NULL) { + ftpBufAlloced = url_iobuf_size; + ftpBuf = xcalloc(ftpBufAlloced, sizeof(ftpBuf[0])); + } + *ftpBuf = '\0'; + + bufLength = 0; + moretodo = 1; + + do { + + /* XXX FIXME: realloc ftpBuf is < ~128 chars remain */ + if ((ftpBufAlloced - bufLength) < (1024+80)) { + ftpBufAlloced <<= 2; + ftpBuf = xrealloc(ftpBuf, ftpBufAlloced); + } + s = se = ftpBuf + bufLength; + *se = '\0'; + + rc = fdFgets(fd, se, (ftpBufAlloced - bufLength)); + if (rc <= 0) { + moretodo = 0; + break; + } + if (ftpSysCall == DO_FTP_GLOB) { /* XXX HACK */ + bufLength += strlen(se); + continue; + } + + for (s = se; *s != '\0'; s = se) { + int bingo; + + while (*se && *se != '\n') se++; + if (se > s && se[-1] == '\r') se[-1] = '\0'; + if (*se == '\0') break; + *se++ = '\0'; + + if (!strncmp(s, "total ", sizeof("total ")-1)) continue; + + o = NULL; + for (bingo = 0, n = se; n >= s; n--) { + switch (*n) { + case '\0': + oe = ne = n; + break; + case ' ': + if (o || !(n[-3] == ' ' && n[-2] == '-' && n[-1] == '>')) { + while (*(++n) == ' '); + bingo++; + break; + } + for (o = n + 1; *o == ' '; o++); + n -= 3; + ne = n; + break; + default: + break; + } + if (bingo) break; + } + + if (nbn != (ne - n)) continue; /* Same name length? */ + if (strncmp(n, bn, nbn)) continue; /* Same name? */ + + moretodo = 0; + break; + } + + if (moretodo && se > s) { + bufLength = se - s - 1; + if (s != ftpBuf) + memmove(ftpBuf, s, bufLength); + } else { + bufLength = 0; + } + } while (moretodo); + + switch (ftpSysCall) { + case DO_FTP_STAT: + if (o && oe) { + /* XXX FIXME: symlink, replace urldn/bn from [o,oe) and restart */ + } + /*@fallthrough@*/ + case DO_FTP_LSTAT: + if (st == NULL || !(n && ne)) { + rc = -1; + } else { + rc = ((vfs_parse_ls_lga(s, st, NULL, NULL) > 0) ? 0 : -1); + } + break; + case DO_FTP_READLINK: + if (rlbuf == NULL || !(o && oe)) { + rc = -1; + } else { + rc = oe - o; + if (rc > rlbufsiz) + rc = rlbufsiz; + memcpy(rlbuf, o, rc); + if (rc < rlbufsiz) + rlbuf[rc] = '\0'; + } + break; + case DO_FTP_ACCESS: + rc = 0; /* XXX WRONG WRONG WRONG */ + break; + case DO_FTP_GLOB: + rc = 0; /* XXX WRONG WRONG WRONG */ + break; + } + +exit: + ufdClose(fd); + return rc; +} + +static int ftpStat(const char * path, struct stat *st) +{ + return ftpNLST(path, DO_FTP_STAT, st, NULL, 0); +} + +static int ftpLstat(const char * path, struct stat *st) { + int rc; + rc = ftpNLST(path, DO_FTP_LSTAT, st, NULL, 0); +if (_rpmio_debug) +fprintf(stderr, "*** ftpLstat(%s) rc %d\n", path, rc); + return rc; +} + +static int ftpReadlink(const char * path, char * buf, size_t bufsiz) { + return ftpNLST(path, DO_FTP_READLINK, NULL, buf, bufsiz); +} + +static int ftpGlob(const char * path, int flags, + int errfunc(const char * epath, int eerno), glob_t * pglob) +{ + int rc; + + if (pglob == NULL) + return -2; + rc = ftpNLST(path, DO_FTP_GLOB, NULL, NULL, 0); +if (_rpmio_debug) +fprintf(stderr, "*** ftpGlob(%s,0x%x,%p,%p) ftpNLST rc %d\n", path, flags, errfunc, pglob, rc); + if (rc) + return rc; + rc = poptParseArgvString(ftpBuf, &pglob->gl_pathc, (const char ***)&pglob->gl_pathv); + pglob->gl_offs = -1; /* XXX HACK HACK HACK */ + return rc; +} + +static void ftpGlobfree(glob_t * pglob) { +if (_rpmio_debug) +fprintf(stderr, "*** ftpGlobfree(%p)\n", pglob); + if (pglob->gl_offs == -1) /* XXX HACK HACK HACK */ + xfree(pglob->gl_pathv); +} + +int Stat(const char * path, struct stat * st) { + const char * lpath; + int ut = urlPath(path, &lpath); + +if (_rpmio_debug) +fprintf(stderr, "*** Stat(%s,%p)\n", path, st); + switch (ut) { + case URL_IS_FTP: + return ftpStat(path, st); + /*@notreached@*/ break; + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + path = lpath; + /*@fallthrough@*/ + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + return stat(path, st); +} + +int Lstat(const char * path, struct stat * st) { + const char * lpath; + int ut = urlPath(path, &lpath); + +if (_rpmio_debug) +fprintf(stderr, "*** Lstat(%s,%p)\n", path, st); + switch (ut) { + case URL_IS_FTP: + return ftpLstat(path, st); + /*@notreached@*/ break; + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + path = lpath; + /*@fallthrough@*/ + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + return lstat(path, st); +} + +int Readlink(const char * path, char * buf, size_t bufsiz) { + const char * lpath; + int ut = urlPath(path, &lpath); + + switch (ut) { + case URL_IS_FTP: + return ftpReadlink(path, buf, bufsiz); + /*@notreached@*/ break; + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + path = lpath; + /*@fallthrough@*/ + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + return readlink(path, buf, bufsiz); +} + +int Access(const char * path, int amode) { + const char * lpath; + int ut = urlPath(path, &lpath); + +if (_rpmio_debug) +fprintf(stderr, "*** Access(%s,%d)\n", path, amode); + switch (ut) { + case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + path = lpath; + /*@fallthrough@*/ + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + return access(path, amode); +} + +int Glob(const char *path, int flags, + int errfunc(const char * epath, int eerrno), glob_t *pglob) +{ + const char * lpath; + int ut = urlPath(path, &lpath); + +if (_rpmio_debug) +fprintf(stderr, "*** Glob(%s,0x%x,%p,%p)\n", path, flags, errfunc, pglob); + switch (ut) { + case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ + return ftpGlob(path, flags, errfunc, pglob); + /*@notreached@*/ break; + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + path = lpath; + /*@fallthrough@*/ + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return -2; + /*@notreached@*/ break; + } + return glob(path, flags, errfunc, pglob); +} + +void Globfree(glob_t *pglob) +{ +if (_rpmio_debug) +fprintf(stderr, "*** Globfree(%p)\n", pglob); + if (pglob->gl_offs == -1) /* XXX HACK HACK HACK */ + ftpGlobfree(pglob); + else + globfree(pglob); +} + +DIR * Opendir(const char * path) +{ + const char * lpath; + int ut = urlPath(path, &lpath); + +if (_rpmio_debug) +fprintf(stderr, "*** Opendir(%s)\n", path); + switch (ut) { + case URL_IS_FTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_HTTP: /* XXX WRONG WRONG WRONG */ + case URL_IS_PATH: + path = lpath; + /*@fallthrough@*/ + case URL_IS_UNKNOWN: + break; + case URL_IS_DASH: + default: + return NULL; + /*@notreached@*/ break; + } + return opendir(path); +} + +struct dirent * Readdir(DIR * dir) +{ +if (_rpmio_debug) +fprintf(stderr, "*** Readdir(%p)\n", dir); + return readdir(dir); +} + +int Closedir(DIR * dir) +{ +if (_rpmio_debug) +fprintf(stderr, "*** Closedir(%p)\n", dir); + return closedir(dir); +} diff --git a/rpmio/url.c b/rpmio/url.c index a49877e14..6374757a8 100644 --- a/rpmio/url.c +++ b/rpmio/url.c @@ -9,7 +9,8 @@ #include #endif /* __LCLINT__ */ -#include +#include +#include #include #ifndef IPPORT_FTP @@ -28,10 +29,10 @@ int url_iobuf_size = URL_IOBUF_SIZE; #define RPMURL_DEBUG_REFS 0x20000000 int _url_debug = 0; -#define DBG(_f, _m, _x) if ((_url_debug | (_f)) & (_m)) fprintf _x +#define URLDBG(_f, _m, _x) if ((_url_debug | (_f)) & (_m)) fprintf _x -#define DBGIO(_f, _x) DBG((_f), RPMURL_DEBUG_IO, _x) -#define DBGREFS(_f, _x) DBG((_f), RPMURL_DEBUG_REFS, _x) +#define URLDBGIO(_f, _x) URLDBG((_f), RPMURL_DEBUG_IO, _x) +#define URLDBGREFS(_f, _x) URLDBG((_f), RPMURL_DEBUG_REFS, _x) /*@only@*/ /*@null@*/ static urlinfo *uCache = NULL; static int uCount = 0; @@ -40,7 +41,7 @@ urlinfo XurlLink(urlinfo u, const char *msg, const char *file, unsigned line) { URLSANE(u); u->nrefs++; -DBGREFS(0, (stderr, "--> url %p ++ %d %s at %s:%u\n", u, u->nrefs, msg, file, line)); +URLDBGREFS(0, (stderr, "--> url %p ++ %d %s at %s:%u\n", u, u->nrefs, msg, file, line)); return u; } @@ -67,7 +68,7 @@ urlinfo XurlNew(const char *msg, const char *file, unsigned line) urlinfo XurlFree(urlinfo u, const char *msg, const char *file, unsigned line) { URLSANE(u); -DBGREFS(0, (stderr, "--> url %p -- %d %s at %s:%u\n", u, u->nrefs, msg, file, line)); +URLDBGREFS(0, (stderr, "--> url %p -- %d %s at %s:%u\n", u, u->nrefs, msg, file, line)); if (--u->nrefs > 0) return u; if (u->ctrl) { @@ -108,16 +109,16 @@ DBGREFS(0, (stderr, "--> url %p -- %d %s at %s:%u\n", u, u->nrefs, msg, file, li free(u->buf); u->buf = NULL; } - FREE(u->url); - FREE(u->service); - FREE(u->user); - FREE(u->password); - FREE(u->host); - FREE(u->portstr); - FREE(u->proxyu); - FREE(u->proxyh); + if (u->url) xfree(u->url); + if (u->service) xfree(u->service); + if (u->user) xfree(u->user); + if (u->password) xfree(u->password); + if (u->host) xfree(u->host); + if (u->portstr) xfree(u->portstr); + if (u->proxyu) xfree(u->proxyu); + if (u->proxyh) xfree(u->proxyh); - /*@-refcounttrans@*/ FREE(u); /*@-refcounttrans@*/ + /*@-refcounttrans@*/ xfree(u); /*@-refcounttrans@*/ return NULL; } @@ -206,7 +207,7 @@ static void urlFind(urlinfo *uret, int mustAsk) /* Zap proxy host and port in case they have been reset */ u->proxyp = -1; - FREE(u->proxyh); + if (u->proxyh) xfree(u->proxyh); /* Perform one-time FTP initialization */ if (u->urltype == URL_IS_FTP) { @@ -215,7 +216,7 @@ static void urlFind(urlinfo *uret, int mustAsk) char * prompt; prompt = alloca(strlen(u->host) + strlen(u->user) + 256); sprintf(prompt, _("Password for %s@%s: "), u->user, u->host); - FREE(u->password); + if (u->password) xfree(u->password); u->password = xstrdup( /*@-unrecog@*/ getpass(prompt) /*@=unrecog@*/ ); }