rpm 5.3.7

rpmio/rpmxar.c

Go to the documentation of this file.
00001 #include "system.h"
00002 
00003 /* XXX Get rid of the pugly #ifdef's */
00004 #if defined(WITH_XAR) && defined(HAVE_XAR_H)
00005 
00006 #include "xar.h"
00007 
00008 #if defined(__LCLINT__)
00009 /*@-incondefs -redecl@*/
00010 /*@null@*/
00011 xar_t xar_open(const char *file, int32_t flags)
00012         /*@*/;
00013 int xar_close(/*@only@*/ xar_t x)
00014         /*@globals fileSystem @*/
00015         /*@modifies x, fileSystem @*/;
00016 /*@null@*/
00017 xar_iter_t xar_iter_new(void)
00018         /*@*/;
00019 /*@null@*/
00020 xar_file_t xar_file_first(xar_t x, xar_iter_t i)
00021         /*@modifies x, i @*/;
00022 /*@null@*/
00023 xar_file_t xar_file_next(xar_iter_t i)
00024         /*@modifies i @*/;
00025 /*@null@*/
00026 xar_file_t xar_add_frombuffer(xar_t x, /*@null@*/ xar_file_t parent,
00027                 const char *name, char *buffer, size_t length)
00028         /*@globals fileSystem @*/
00029         /*@modifies x, fileSystem @*/;
00030 int32_t xar_extract_tobuffersz(xar_t x, xar_file_t f,
00031                 char **buffer, size_t *size)
00032         /*@globals fileSystem @*/
00033         /*@modifies x, f, *buffer, *size @*/;
00034 /*@only@*/
00035 char *xar_get_path(xar_file_t f)
00036         /*@*/;
00037 /*@=incondefs =redecl@*/
00038 
00039 #endif  /* __LCLINT__ */
00040 
00041 #else   /* WITH_XAR */
00042 #define READ    0
00043 #define WRITE   1
00044 #define xar_open(_fn, _f)       (NULL)
00045 #define xar_close(_x)   (1)
00046 #define xar_iter_new()          (NULL)
00047 #define xar_iter_free(_i)
00048 #define xar_file_first(_x, _i)  (NULL)
00049 #define xar_file_next(_i)       (NULL)
00050 #define xar_add_frombuffer(_x, _parent, _fn, _b, _bsize)        (NULL)
00051 #define xar_extract_tobuffersz(_x, _f, _b, _bsize)      (1)
00052 #define xar_get_path(_f)        "*No XAR*"
00053 #define xar_opt_set(_a1, _a2, _a3) (1)
00054 #define XAR_OPT_COMPRESSION 0
00055 #define XAR_OPT_VAL_NONE 0
00056 #define XAR_OPT_VAL_GZIP 0
00057 #endif  /* WITH_XAR */
00058 
00059 #define _RPMXAR_INTERNAL
00060 #include <rpmxar.h>
00061 #include <rpmio_internal.h>     /* for fdGetXAR */
00062 #include <rpmhash.h>            /* hashFunctionString */
00063 #include <ugid.h>
00064 
00065 #include "debug.h"
00066 
00067 /*@access FD_t @*/
00068 
00069 /*@unchecked@*/
00070 int _xar_debug = 0;
00071 
00072 /*@unchecked@*/ /*@only@*/ /*@null@*/
00073 rpmioPool _xarPool;
00074 
00075 /*@-globuse -mustmod@*/
00076 static void rpmxarFini(void * _xar)
00077         /*@globals fileSystem @*/
00078         /*@modifies _xar, fileSystem @*/
00079 {
00080     rpmxar xar =_xar;
00081     if (xar->i) {
00082         xar_iter_free(xar->i);
00083         xar->i = NULL;
00084     }
00085     if (xar->x) {
00086         int xx;
00087         xx = xar_close(xar->x);
00088         xar->x = NULL;
00089     }
00090 
00091     xar->member = _free(xar->member);
00092     xar->b = _free(xar->b);
00093 }
00094 /*@=globuse =mustmod@*/
00095 
00096 static rpmxar rpmxarGetPool(/*@null@*/ rpmioPool pool)
00097         /*@globals _xarPool, fileSystem @*/
00098         /*@modifies pool, _xarPool, fileSystem @*/
00099 {
00100     rpmxar xar;
00101 
00102     if (_xarPool == NULL) {
00103         _xarPool = rpmioNewPool("xar", sizeof(*xar), -1, _xar_debug,
00104                         NULL, NULL, rpmxarFini);
00105         pool = _xarPool;
00106     }
00107     xar = (rpmxar) rpmioGetPool(pool, sizeof(*xar));
00108     memset(((char *)xar)+sizeof(xar->_item), 0, sizeof(*xar)-sizeof(xar->_item));
00109     return xar;
00110 }
00111 
00112 rpmxar rpmxarNew(const char * fn, const char * fmode)
00113 {
00114     rpmxar xar = rpmxarGetPool(_xarPool);
00115     int flags = ((fmode && *fmode == 'w') ? WRITE : READ);
00116 
00117 assert(fn != NULL);
00118     xar->x = xar_open(fn, flags);
00119     if (flags == READ) {
00120         xar->i = xar_iter_new();
00121         xar->first = 1;
00122     }
00123 if (_xar_debug)
00124 fprintf(stderr, "<-- %s(%s,%s) xar %p i %p x %p first %d\n", __FUNCTION__, fn, fmode, xar, xar->i, xar->x, xar->first);
00125     return rpmxarLink(xar, __FUNCTION__);
00126 }
00127 
00128 int rpmxarNext(rpmxar xar)
00129 {
00130     int rc = 1;         /* assume failure */
00131 
00132 if (_xar_debug)
00133 fprintf(stderr, "--> %s(%p) i %p x %p first %d\n", __FUNCTION__, xar, (xar ? xar->i : NULL), (xar ? xar->x : NULL), (xar ? xar->first : -1));
00134     if (xar && xar->x) {
00135         if (xar->first) {
00136             xar->f = xar_file_first(xar->x, xar->i);
00137             xar->first = 0;
00138         } else
00139             xar->f = xar_file_next(xar->i);
00140     }
00141 
00142     rc = (xar && xar->f ? 0 : 1);
00143 if (_xar_debug)fprintf(stderr, "<-- %s(%p) rc %d\n", __FUNCTION__, xar, rc);
00144     return rc;
00145 }
00146 
00147 int rpmxarPush(rpmxar xar, const char * fn, unsigned char * b, size_t bsize)
00148 {
00149     int payload = !strcmp(fn, "Payload");
00150 
00151 /*@+charint@*/
00152 if (_xar_debug)
00153 fprintf(stderr, "--> rpmxarPush(%p, %s) %p[%u] %02x%02x%02x%02x%02x%02x%02x%02x\n", xar, fn, b, (unsigned)bsize, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
00154 /*@=charint@*/
00155 
00156     if (xar->x && b != NULL) {
00157         if (payload) /* payload is already compressed */
00158             (void) xar_opt_set(xar->x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_NONE);
00159         xar->f = xar_add_frombuffer(xar->x, NULL, fn, (char *)b, bsize);
00160         if (payload) /* restore default xar compression */
00161             (void) xar_opt_set(xar->x, XAR_OPT_COMPRESSION, XAR_OPT_VAL_GZIP);
00162         if (xar->f == NULL)
00163             return 2;
00164     }
00165     return 0;
00166 }
00167 
00168 int rpmxarPull(rpmxar xar, const char * fn)
00169 {
00170     int rc = 1;
00171 #ifdef  WITH_XAR
00172     const char * path = xar_get_path(xar->f);
00173 
00174     if (fn != NULL && strcmp(fn, path)) {
00175         path = _free(path);
00176         return rc;
00177     }
00178     xar->member = _free(xar->member);
00179     xar->member = path;
00180 
00181     xar->b = _free(xar->b);
00182     xar->bsize = xar->bx = 0;
00183 
00184 /*@-nullstate @*/
00185     rc = (int) xar_extract_tobuffersz(xar->x, xar->f, (char **)&xar->b, &xar->bsize);
00186 /*@=nullstate @*/
00187     if (rc)
00188         return 1;
00189 
00190 /*@+charint -nullpass -nullderef @*/
00191 if (_xar_debug) {
00192 unsigned char * b = xar->b;
00193 size_t bsize = xar->bsize;
00194 fprintf(stderr, "<-- rpmxarPull(%p, %s) %p[%u] %02x%02x%02x%02x%02x%02x%02x%02x\n", xar, fn, b, (unsigned)bsize, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
00195 }
00196 /*@=charint =nullpass =nullderef @*/
00197     rc = 0;
00198 #endif
00199 
00200     return rc;
00201 }
00202 
00203 int rpmxarSwapBuf(rpmxar xar, unsigned char * b, size_t bsize,
00204                 unsigned char ** obp, size_t * obsizep)
00205 {
00206 if (_xar_debug)
00207 fprintf(stderr, "--> rpmxarSwapBuf(%p, %p[%u], %p, %p) %p[%u]\n", xar, b, (unsigned) bsize, obp, obsizep, xar->b, (unsigned) xar->bsize);
00208 
00209     if (xar) {
00210         if (obsizep != NULL)
00211             *obsizep = xar->bsize;
00212         if (obp != NULL) {
00213 /*@-onlytrans@*/
00214             *obp = xar->b;
00215 /*@=onlytrans@*/
00216             xar->b = NULL;
00217         }
00218         xar->b = _free(xar->b);
00219 /*@-assignexpose -temptrans @*/
00220         xar->b = b;
00221 /*@=assignexpose =temptrans @*/
00222         xar->bsize = bsize;
00223     }
00224 /*@-nullstate@*/
00225     return 0;
00226 /*@=nullstate@*/
00227 }
00228 
00229 ssize_t xarRead(void * cookie, /*@out@*/ char * buf, size_t count)
00230 {
00231     FD_t fd = cookie;
00232     rpmxar xar = fdGetXAR(fd);
00233     ssize_t rc = 0;
00234 
00235 assert(xar != NULL);
00236 #if 0
00237     if ((xx = rpmxarNext(xar)) != 0)    return RPMRC_FAIL;
00238     if ((xx = rpmxarPull(xar, "Signature")) != 0) return RPMRC_FAIL;
00239     (void) rpmxarSwapBuf(xar, NULL, 0, &b, &nb);
00240 #endif
00241 
00242     rc = xar->bsize - xar->bx;
00243     if (rc > 0) {
00244         if (count < (size_t)rc) rc = count;
00245 assert(xar->b != NULL);
00246         memmove(buf, &xar->b[xar->bx], rc);
00247         xar->bx += rc;
00248     } else
00249     if (rc < 0) {
00250         rc = -1;
00251     } else
00252         rc = 0;
00253 
00254 if (_xar_debug)
00255 fprintf(stderr, "<-- %s(%p,%p,0x%x) %s %p[%u:%u] rc 0x%x\n", __FUNCTION__, cookie, buf, (unsigned)count, (xar->member ? xar->member : "(nil)"), xar->b, (unsigned)xar->bx, (unsigned)xar->bsize, (unsigned)rc);
00256 
00257     return rc;
00258 }
00259 
00260 const char * rpmxarPath(rpmxar xar)
00261 {
00262     const char * path = (xar && xar->f ? xar_get_path(xar->f) : NULL);
00263 if (_xar_debug)
00264 fprintf(stderr, "<-- %s(%p) %s\n", __FUNCTION__, xar, path);
00265     return path;
00266 }
00267 
00268 static mode_t xarMode(rpmxar xar)
00269         /*@*/
00270 {
00271     mode_t m = 0;
00272 #ifdef  WITH_XAR
00273     const char * t = NULL;
00274 
00275     xar_prop_get(xar->f, "mode", &t);
00276     m = (t ? (mode_t) strtoll(t, NULL, 8) : 0);
00277 
00278     xar_prop_get(xar->f, "type", &t);
00279     if (!strcmp(t, "file"))
00280         m |= S_IFREG;
00281     else if (!strcmp(t, "hardlink"))
00282         m |= S_IFREG;
00283     else if (!strcmp(t, "directory"))
00284         m |= S_IFDIR;
00285     else if (!strcmp(t, "symlink"))
00286         m |= S_IFLNK;
00287     else if (!strcmp(t, "fifo"))
00288         m |= S_IFIFO;
00289     else if (!strcmp(t, "character special"))
00290         m |= S_IFCHR;
00291     else if (!strcmp(t, "block special"))
00292         m |= S_IFBLK;
00293     else if (!strcmp(t, "socket"))
00294         m |= S_IFSOCK;
00295 #ifdef S_IFWHT
00296     else if (!strcmp(t, "whiteout"))
00297         m |= S_IFWHT;
00298 #endif
00299 #endif
00300 
00301     return m;
00302 }
00303 
00304 static dev_t xarDev(rpmxar xar)
00305         /*@*/
00306 {
00307     unsigned major = 0;
00308     unsigned minor = 0;
00309 #ifdef  WITH_XAR
00310     const char *t = NULL;
00311 
00312     xar_prop_get(xar->f, "device/major", &t);
00313     major = (t ? (unsigned) strtoll(t, NULL, 0) : 0);
00314     xar_prop_get(xar->f, "device/minor", &t);
00315     minor = (t ? (unsigned) strtoll(t, NULL, 0) : 0);
00316 #endif
00317 #ifdef makedev
00318     return makedev(major, minor);
00319 #else
00320     return (major << 8) | minor;
00321 #endif
00322 }
00323 
00324 static long long xarSize(rpmxar xar)
00325         /*@*/
00326 {
00327     long long ll = 0L;
00328 #ifdef  WITH_XAR
00329     char * t = NULL;
00330 #if defined(HAVE_XAR_GET_SIZE)
00331     t = xar_get_size(xar->x, xar->f);
00332     ll = strtoll(t, NULL, 0);
00333     t = _free(t);
00334 #else
00335     xar_prop_get(xar->f, "data/size", &t);
00336     if (t)
00337         ll = strtoll(t, NULL, 0);
00338 #endif
00339 #endif
00340     return ll;
00341 }
00342 
00343 static uid_t xarUid(rpmxar xar)
00344         /*@*/
00345 {
00346     uid_t u = 0;
00347 #ifdef  WITH_XAR
00348     const char * t = NULL;
00349 
00350     xar_prop_get(xar->f, "user", &t);
00351     if (t == NULL || unameToUid(t, &u) < 0) {
00352         xar_prop_get(xar->f, "uid", &t);
00353         u = (t ? (uid_t) strtoll(t, NULL, 0) : getuid());
00354     }
00355 #endif
00356     return u;
00357 }
00358 
00359 static gid_t xarGid(rpmxar xar)
00360         /*@*/
00361 {
00362     gid_t g = 0;
00363 #ifdef  WITH_XAR
00364     const char * t = NULL;
00365 
00366     xar_prop_get(xar->f, "group", &t);
00367     if (t == NULL || gnameToGid(t, &g) < 0) {
00368         xar_prop_get(xar->f, "gid", &t);
00369         g = (t ? (gid_t) strtoll(t, NULL, 0) : getgid());
00370     }
00371 #endif
00372     return g;
00373 }
00374 
00375 static void xarTime(rpmxar xar, const char * tprop, struct timeval *tv)
00376         /*@modifies *tvp */
00377 {
00378 #ifdef  WITH_XAR
00379     const char * t = NULL;
00380 
00381     xar_prop_get(xar->f, tprop, &t);
00382     if (t) {
00383         struct tm tm;
00384         strptime(t, "%FT%T", &tm);
00385         tv->tv_sec = timegm(&tm);
00386         tv->tv_usec = 0;
00387     } else
00388 #endif
00389     {
00390         tv->tv_sec = time(NULL);
00391         tv->tv_usec = 0;
00392     }
00393 }
00394 
00395 int rpmxarStat(rpmxar xar, struct stat * st)
00396 {
00397     int rc = -1;        /* assume failure */
00398 
00399     if (xar && xar->f) {
00400         const char * path = rpmxarPath(xar);
00401         memset(st, 0, sizeof(*st));
00402         st->st_dev = (dev_t)0;
00403         st->st_ino = hashFunctionString(0, path, 0);;
00404         path = _free(path);
00405         st->st_mode = xarMode(xar);
00406         st->st_nlink = (S_ISDIR(st->st_mode) ? 2 : 1);  /* XXX FIXME */
00407         st->st_uid = xarUid(xar);
00408         st->st_gid = xarGid(xar);
00409         st->st_rdev = (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
00410                 ? xarDev(xar) : (dev_t)0;
00411         st->st_size = xarSize(xar);
00412         st->st_blksize = (blksize_t) 0;
00413         st->st_blocks = (blkcnt_t) 0;
00414         xarTime(xar, "atime", (struct timeval *)&st->st_atime);
00415         xarTime(xar, "ctime", (struct timeval *)&st->st_ctime);
00416         xarTime(xar, "mtime", (struct timeval *)&st->st_mtime);
00417         rc = 0;
00418     }
00419 
00420 if (_xar_debug)
00421 fprintf(stderr, "<-- %s(%p,%p) rc %d\n", __FUNCTION__, xar, st, rc);
00422     return rc;
00423 }