rpm  5.4.15
rpmdir.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <rpmio.h>
8 #include <rpmurl.h>
9 #include <argv.h>
10 
11 #define _RPMDIR_INTERNAL
12 #include <rpmdir.h>
13 #include <rpmdav.h> /* ftpOpendir/davOpendir */
14 #include <rpmhash.h> /* hashFunctionString */
15 
16 #include "debug.h"
17 
18 /*@access DIR @*/
19 
20 #ifdef __cplusplus
21 GENfree(time_t *)
22 GENfree(size_t *)
23 GENfree(rpmuint16_t *)
24 GENfree(AVDIR)
25 #endif /* __cplusplus */
26 
27 /* =============================================================== */
28 static void avxFini(void * _avx)
29 {
30  rpmavx avx = (rpmavx) _avx;
31 
32  avx->mtimes = _free(avx->mtimes);
33  avx->sizes = _free(avx->sizes);
34  avx->modes = _free(avx->modes);
35  avx->st = NULL;
36  avx->av = argvFree(avx->av);
37  avx->nalloced = 0;
38  avx->ac = 0;
39  (void) urlFree(avx->u, __FUNCTION__);
40  avx->u = NULL;
41  avx->uri = _free(avx->uri);
42  avx->resrock = NULL;
43 }
44 
45 /*@unchecked@*/ /*@only@*/ /*@null@*/
47 
48 static rpmavx avxGetPool(/*@null@*/ rpmioPool pool)
49  /*@globals _avxPool, fileSystem @*/
50  /*@modifies pool, _avxPool, fileSystem @*/
51 {
52  rpmavx avx;
53 
54  if (_avxPool == NULL) {
55  _avxPool = rpmioNewPool("avx", sizeof(*avx), -1, _av_debug,
56  NULL, NULL, avxFini);
57  pool = _avxPool;
58  }
59  avx = (rpmavx) rpmioGetPool(pool, sizeof(*avx));
60  memset(((char *)avx)+sizeof(avx->_item), 0, sizeof(*avx)-sizeof(avx->_item));
61  return avx;
62 }
63 
64 void * rpmavxNew(const char *uri, struct stat *st)
65 {
66  rpmavx avx;
67  urlinfo u;
68 
69 /*@-globs@*/ /* FIX: h_errno annoyance. */
70  if (urlSplit(uri, &u))
71  return NULL;
72 /*@=globs@*/
73 
74  avx = avxGetPool(_avxPool);
75  avxFini(avx); /* XXX trash-and-burn */
76 
77  /* XXX +1 byte for pesky trailing '/' */
78  avx->uri = strcpy((char *)xmalloc(strlen(uri) + 1 + 1), uri);
79 
80  avx->u = urlLink(u, __FUNCTION__);
81 /*@-temptrans@*/ /* XXX note the assignment */
82  if ((avx->st = st) != NULL)
83  memset(avx->st, 0, sizeof(*avx->st));
84 /*@=temptrans@*/
85 
86  return rpmavxLink(avx);
87 }
88 
89 int rpmavxAdd(rpmavx avx, const char * path,
90  mode_t mode, size_t size, time_t mtime)
91 {
92  int xx;
93 
94 if (_av_debug < 0)
95 fprintf(stderr, "--> %s(%p,\"%s\", %06o, 0x%x, 0x%x)\n", __FUNCTION__, avx, path, (unsigned)mode, (unsigned)size, (unsigned)mtime);
96 
97  xx = argvAdd(&avx->av, path);
98 
99  while (avx->ac >= avx->nalloced) {
100  if (avx->nalloced <= 0)
101  avx->nalloced = 1;
102  avx->nalloced *= 2;
103  avx->modes = (rpmuint16_t *) xrealloc(avx->modes,
104  (sizeof(*avx->modes) * avx->nalloced));
105  avx->sizes = (size_t *) xrealloc(avx->sizes,
106  (sizeof(*avx->sizes) * avx->nalloced));
107  avx->mtimes = (time_t *) xrealloc(avx->mtimes,
108  (sizeof(*avx->mtimes) * avx->nalloced));
109  }
110 
111  avx->modes[avx->ac] = (rpmuint16_t)mode;
112  avx->sizes[avx->ac] = size;
113  avx->mtimes[avx->ac] = mtime;
114  avx->ac++;
115  return 0;
116 }
117 
118 int avClosedir(/*@only@*/ DIR * dir)
119 {
120  AVDIR avdir = (AVDIR)dir;
121 
122 if (_av_debug)
123 fprintf(stderr, "--> avClosedir(%p)\n", avdir);
124 
125 #if defined(WITH_PTHREADS)
126 /*@-moduncon -noeffectuncon @*/
127  (void) pthread_mutex_destroy(&avdir->lock);
128 /*@=moduncon =noeffectuncon @*/
129 #endif
130 
131  avdir = _free(avdir);
132  return 0;
133 }
134 
135 DIR * avOpendir(const char * path, const char ** av, rpmuint16_t * modes)
136 {
137  AVDIR avdir;
138  struct dirent * dp;
139  size_t nb;
140  const char ** nav;
141  unsigned char * dt;
142  char * t;
143  int ac, nac;
144 
145 if (_av_debug)
146 fprintf(stderr, "--> avOpendir(%s, %p, %p)\n", path, av, modes);
147 
148  nb = 0;
149  ac = 0;
150  if (av != NULL)
151  while (av[ac] != NULL)
152  nb += strlen(av[ac++]) + 1;
153  ac += 2; /* for "." and ".." */
154  nb += sizeof(".") + sizeof("..");
155 
156  nb += sizeof(*avdir) + sizeof(*dp) + ((ac + 1) * sizeof(*av)) + (ac + 1);
157  avdir = (AVDIR) xcalloc(1, nb);
158 /*@-abstract@*/
159  dp = (struct dirent *) (avdir + 1);
160  nav = (const char **) (dp + 1);
161  dt = (unsigned char *) (nav + (ac + 1));
162  t = (char *) (dt + ac + 1);
163 /*@=abstract@*/
164 
165  avdir->fd = avmagicdir;
166 /*@-usereleased@*/
167  avdir->data = (char *) dp;
168 /*@=usereleased@*/
169  avdir->allocation = nb;
170  avdir->size = ac;
171  avdir->offset = -1;
172  /* Hash the directory path for a d_ino analogue. */
173  avdir->filepos = hashFunctionString(0, path, 0);
174 
175 #if defined(WITH_PTHREADS)
176 /*@-moduncon -noeffectuncon -nullpass @*/
177  (void) pthread_mutex_init(&avdir->lock, NULL);
178 /*@=moduncon =noeffectuncon =nullpass @*/
179 #endif
180 
181  nac = 0;
182  /*@-dependenttrans -unrecog@*/
183  dt[nac] = (unsigned char)DT_DIR; nav[nac++] = t; t = stpcpy(t, "."); t++;
184  dt[nac] = (unsigned char)DT_DIR; nav[nac++] = t; t = stpcpy(t, ".."); t++;
185  /*@=dependenttrans =unrecog@*/
186 
187  /* Append av strings to DIR elements. */
188  ac = 0;
189  if (av != NULL)
190  while (av[ac] != NULL) {
191  if (modes != NULL)
192  switch (modes[ac] & S_IFMT) {
193  case S_IFIFO: dt[nac]=(unsigned char)DT_FIFO;/*@switchbreak@*/break;
194  case S_IFCHR: dt[nac]=(unsigned char)DT_CHR; /*@switchbreak@*/break;
195  case S_IFDIR: dt[nac]=(unsigned char)DT_DIR; /*@switchbreak@*/break;
196  case S_IFBLK: dt[nac]=(unsigned char)DT_BLK; /*@switchbreak@*/break;
197  case S_IFREG: dt[nac]=(unsigned char)DT_REG; /*@switchbreak@*/break;
198  case S_IFLNK: dt[nac]=(unsigned char)DT_LNK; /*@switchbreak@*/break;
199 /*@-unrecog@*/
200  case S_IFSOCK:dt[nac]=(unsigned char)DT_SOCK;/*@switchbreak@*/break;
201 /*@=unrecog@*/
202  default: dt[nac]=(unsigned char)DT_UNKNOWN;/*@switchbreak@*/break;
203  }
204  else
205  dt[nac] = (unsigned char)DT_UNKNOWN;
206 /*@-dependenttrans@*/
207  nav[nac++] = t;
208 /*@=dependenttrans@*/
209  t = stpcpy(t, av[ac++]);
210  t++; /* trailing \0 */
211  }
212  nav[nac] = NULL;
213 
214 /*@-kepttrans@*/
215  return (DIR *) avdir;
216 /*@=kepttrans@*/
217 }
218 
219 struct dirent * avReaddir(DIR * dir)
220 {
221  /* XXX Enabling breaks Readdir(3) compatibility. */
222  /* XXX Disabling triggers 302 retries with forced reconnects. */
223  static int _append_pesky_trailing_slash = 1;
224  AVDIR avdir = (AVDIR)dir;
225  struct dirent * dp;
226  const char ** av;
227  unsigned char * dt;
228  char * t;
229  int ac;
230  int i;
231 
232  if (avdir == NULL || !ISAVMAGIC(avdir) || avdir->data == NULL) {
233  errno = EFAULT; /* XXX better errno's */
234  dp = NULL;
235  goto exit;
236  }
237 
238  dp = (struct dirent *) avdir->data;
239  av = (const char **) (dp + 1);
240  ac = (int)avdir->size;
241  dt = (unsigned char *) (av + (ac + 1));
242  i = avdir->offset + 1;
243 
244  if (i < 0 || i >= ac || av[i] == NULL) {
245  errno = EFAULT; /* XXX better errno's */
246  dp = NULL;
247  goto exit;
248  }
249 
250  avdir->offset = i;
251 
252  /* XXX glob(3) uses REAL_DIR_ENTRY(dp) test on d_ino */
253 /*@-type@*/
254  /* Hash the name (starting with parent hash) for a d_ino analogue. */
255  dp->d_ino = hashFunctionString(avdir->filepos, dp->d_name, 0);
256 
257 #if !defined(__DragonFly__) && !defined(__CYGWIN__)
258  dp->d_reclen = 0; /* W2DO? */
259 #endif
260 
261 #if !(defined(hpux) || defined(__hpux) || defined(sun) || defined(RPM_OS_AIX) || defined(__CYGWIN__) || defined(__QNXNTO__))
262 #if !defined(__APPLE__) && !defined(__FreeBSD_kernel__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) && !defined(__OpenBSD__)
263  dp->d_off = (off_t)i;
264 #endif
265  dp->d_type = dt[i];
266 #endif
267 /*@=type@*/
268 
269  t = stpncpy(dp->d_name, av[i], sizeof(dp->d_name));
270 
271  /* XXX Always append the pesky trailing '/'? */
272  if (_append_pesky_trailing_slash) {
273  size_t nt = (t - dp->d_name);
274  if (nt > 0 && nt < sizeof(dp->d_name))
275  switch (dt[i]) {
276  case DT_DIR:
277  if (t[nt-1] != '/')
278  *t++ = '/';
279  *t = '\0';
280  /*@fallthrough@*/
281  default:
282  break;
283  }
284  }
285 
286 exit:
287 if (_av_debug)
288 fprintf(stderr, "<-- avReaddir(%p) %p %s\n", (void *)avdir, dp, (dp ? dp->d_name : ""));
289 
290  return dp;
291 }
292 
293 static void avRewinddir(DIR * dir)
294  /*@*/
295 {
296  AVDIR avdir = (AVDIR)dir;
297 
298  if (avdir != NULL && ISAVMAGIC(avdir))
299  avdir->offset = (off_t)-1;
300  return;
301 }
302 
303 static int avScandir(const char * path, struct dirent *** nl,
304  int (*filter) (const struct dirent *),
305  int (*compar) (const void *, const void *))
306  /*@*/
307 {
308  DIR * dir;
309  struct dirent * dp;
310  int rc = -1; /* assume failure */
311 
312  if ((dir = Opendir(path)) == NULL)
313  goto exit;
314 
315  rc = 0;
316  while ((dp = Readdir(dir)) != NULL) {
317  if (filter != NULL && !(*filter)(dp))
318  continue;
319  rc++;
320  if (nl == NULL)
321  continue;
322  *nl = (struct dirent **) (rc == 1
323  ? xmalloc(rc * sizeof(**nl))
324  : xrealloc(*nl, rc * sizeof(**nl)));
325  (*nl)[rc - 1] = (struct dirent *)
326  memcpy(xmalloc(sizeof(*dp)), dp, sizeof(*dp));
327  }
328 
329  (void) Closedir(dir);
330 
331  if (compar != NULL && nl != NULL && rc > 1)
332  qsort(*nl, rc, sizeof(**nl), compar);
333 
334 exit:
335  return rc;
336 }
337 
338 static void avSeekdir(DIR * dir, off_t offset)
339  /*@*/
340 {
341  AVDIR avdir = (AVDIR)dir;
342  struct dirent * dp;
343  const char ** av;
344  int ac;
345 
346  if (avdir == NULL || !ISAVMAGIC(avdir) || avdir->data == NULL)
347  return;
348 
349  dp = (struct dirent *) avdir->data;
350  av = (const char **) (dp + 1);
351  ac = (int)avdir->size;
352 
353  if (offset < 0 || offset >= ac || av[offset] == NULL)
354  return;
355 
356  avdir->offset = offset - 1; /* XXX set to previous entry */
357 
358  return;
359 }
360 
361 static off_t avTelldir(DIR * dir)
362  /*@globals errno @*/
363  /*@modifies errno @*/
364 {
365  AVDIR avdir = (AVDIR)dir;
366  off_t offset = -1;
367  struct dirent * dp;
368  const char ** av;
369  int ac;
370 
371  if (avdir != NULL && ISAVMAGIC(avdir) && avdir->data != NULL) {
372  dp = (struct dirent *) avdir->data;
373  av = (const char **) (dp + 1);
374  ac = (int)avdir->size;
375  offset = avdir->offset;
376  }
377 
378  if (offset < 0 || offset >= ac || av[offset] == NULL)
379  errno = EBADF;
380 
381  return offset;
382 }
383 
384 /* =============================================================== */
385 int Closedir(DIR * dir)
386 {
387 if (_rpmio_debug)
388 fprintf(stderr, "*** Closedir(%p)\n", (void *)dir);
389  if (dir == NULL)
390  return 0;
391  if (ISAVMAGIC(dir))
392  return avClosedir(dir);
393  return closedir(dir);
394 }
395 
396 DIR * Opendir(const char * path)
397  /*@globals ftpBufAlloced, ftpBuf @*/
398  /*@modifies ftpBufAlloced, ftpBuf @*/
399 {
400  const char * lpath;
401  int ut = urlPath(path, &lpath);
402 
403 if (_rpmio_debug)
404 fprintf(stderr, "*** Opendir(%s)\n", path);
405  switch (ut) {
406  case URL_IS_FTP:
407  return ftpOpendir(path);
408  /*@notreached@*/ break;
409  case URL_IS_HTTPS:
410  case URL_IS_HTTP:
411 #ifdef WITH_NEON
412  return davOpendir(path);
413 #endif
414  /*@notreached@*/ break;
415  case URL_IS_PATH:
416  path = lpath;
417  /*@fallthrough@*/
418  case URL_IS_UNKNOWN:
419  break;
420  case URL_IS_DASH:
421  case URL_IS_HKP:
422  case URL_IS_MONGO: /* XXX FIXME */
423  default:
424  return NULL;
425  /*@notreached@*/ break;
426  }
427  /*@-dependenttrans@*/
428  return opendir(path);
429  /*@=dependenttrans@*/
430 }
431 
432 struct dirent * Readdir(DIR * dir)
433 {
434 if (_rpmio_debug)
435 fprintf(stderr, "*** Readdir(%p)\n", (void *)dir);
436  if (dir == NULL)
437  return NULL;
438  if (ISAVMAGIC(dir))
439  return avReaddir(dir);
440  return readdir(dir);
441 }
442 
443 void Rewinddir(DIR * dir)
444 {
445 if (_rpmio_debug)
446 fprintf(stderr, "*** Rewinddir(%p)\n", (void *)dir);
447  if (ISAVMAGIC(dir))
448  avRewinddir(dir);
449  else
450  rewinddir(dir);
451  return;
452 }
453 
454 int Scandir(const char * path, struct dirent *** nl,
455  int (*filter) (const struct dirent *),
456  int (*compar) (const void *, const void *))
457 {
458  const char * lpath;
459  int ut = urlPath(path, &lpath);
460  int rc = 0;
461 
462  switch (ut) {
463  case URL_IS_DASH:
464  case URL_IS_HKP:
465  case URL_IS_FTP:
466  case URL_IS_HTTP:
467  case URL_IS_HTTPS:
468  case URL_IS_MONGO: /* XXX FIXME */
469  default:
470  rc = avScandir(path, nl, filter, compar);
471  break;
472  case URL_IS_UNKNOWN:
473  lpath = path;
474  /*@fallthrough@*/
475  case URL_IS_PATH:
476  break;
477  }
478 
479  if (!rc)
480  rc = scandir(lpath, nl, filter,
481  (int (*)(const struct dirent **, const struct dirent **))compar);
482 
483 if (_rpmio_debug)
484 fprintf(stderr, "*** Scandir(\"%s\", %p, %p, %p) rc %d\n", path, nl, filter, compar, rc);
485  return rc;
486 }
487 
488 int Alphasort(const void * a, const void * b)
489 {
490  struct dirent *const * adp = (struct dirent *const *) a;
491  struct dirent *const * bdp = (struct dirent *const *) b;
492 #if defined(HAVE_STRCOLL)
493  return strcoll((*adp)->d_name, (*bdp)->d_name);
494 #else
495  return strcmp((*adp)->d_name, (*bdp)->d_name);
496 #endif
497 }
498 
499 int Versionsort(const void * a, const void * b)
500 {
501  struct dirent *const * adp = (struct dirent *const *) a;
502  struct dirent *const * bdp = (struct dirent *const *) b;
503 #if defined(HAVE_STRVERSCMP)
504  return strverscmp((*adp)->d_name, (*bdp)->d_name);
505 #else
506  return strcmp((*adp)->d_name, (*bdp)->d_name);
507 #endif
508 }
509 
510 void Seekdir(DIR * dir, off_t offset)
511 {
512 if (_rpmio_debug)
513 fprintf(stderr, "*** Seekdir(%p,%ld)\n", (void *)dir, (long)offset);
514  if (ISAVMAGIC(dir))
515  avSeekdir(dir, offset);
516  else
517  seekdir(dir, offset);
518  return;
519 }
520 
521 off_t Telldir(DIR * dir)
522 {
523  off_t offset = 0;
524 
525  offset = (ISAVMAGIC(dir) ? avTelldir(dir) : telldir(dir));
526 if (_rpmio_debug)
527 fprintf(stderr, "*** Telldir(%p) off %ld\n", (void *)dir, (long)offset);
528  return offset;
529 }
const bson * b
Definition: bson.h:280
#define DT_BLK
Definition: rpmdir.h:16
int rpmavxAdd(rpmavx avx, const char *path, mode_t mode, size_t size, time_t mtime)
Definition: rpmdir.c:89
#define DT_CHR
Definition: rpmdir.h:14
#define DT_REG
Definition: rpmdir.h:17
int Versionsort(const void *a, const void *b)
Definition: rpmdir.c:499
URL control structure.
Definition: rpmurl.h:52
DIR * davOpendir(const char *path)
Create an argv directory from DAV collection.
Hash table implemenation.
int errno
unsigned short rpmuint16_t
Definition: rpmiotypes.h:27
#define DT_UNKNOWN
Definition: rpmdir.h:12
void * rpmavxNew(const char *uri, struct stat *st)
Definition: rpmdir.c:64
static off_t avTelldir(DIR *dir)
Definition: rpmdir.c:361
int avClosedir(DIR *dir)
Definition: rpmdir.c:118
#define DT_LNK
Definition: rpmdir.h:18
void Seekdir(DIR *dir, off_t offset)
seekdir(3) clone.
Definition: rpmdir.c:510
void * xcalloc(size_t nmemb, size_t size)
Definition: rpmmalloc.c:300
int _av_debug
Definition: rpmio.c:185
#define DT_DIR
Definition: rpmdir.h:15
const char * mode
Definition: mongo.h:440
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:220
#define ISAVMAGIC(_dir)
Definition: rpmdir.h:40
static void avxFini(void *_avx)
Definition: rpmdir.c:28
char * stpncpy(char *dest, const char *src, size_t n)
ARGV_t argvFree(ARGV_t argv)
Destroy an argv array.
Definition: argv.c:44
void Rewinddir(DIR *dir)
rewinddir(3) clone.
Definition: rpmdir.c:443
int argvAdd(ARGV_t *argvp, ARGstr_t val)
Add a string to an argv array.
Definition: argv.c:199
struct dirent * avReaddir(DIR *dir)
Definition: rpmdir.c:219
#define dirent
Definition: system.h:245
#define pthread_mutex_destroy(__mutex)
Definition: yarn.c:71
int Scandir(const char *path, struct dirent ***nl, int(*filter)(const struct dirent *), int(*compar)(const void *, const void *))
scandir(3) clone.
Definition: rpmdir.c:454
#define DT_FIFO
Definition: rpmdir.h:13
#define S_IFSOCK
Definition: system.h:647
struct __dirstream * AVDIR
Definition: rpmdir.h:21
static void avRewinddir(DIR *dir)
Definition: rpmdir.c:293
DIR * avOpendir(const char *path, const char **av, rpmuint16_t *modes)
Definition: rpmdir.c:135
int urlSplit(const char *url, urlinfo *uret)
Parse URL string into a control structure.
Definition: url.c:476
const char const int i
Definition: bson.h:778
urltype urlPath(const char *url, const char **pathp)
Return path component of URL.
Definition: url.c:430
int _rpmio_debug
Definition: rpmio.c:180
struct dirent * Readdir(DIR *dir)
readdir(3) clone.
Definition: rpmdir.c:432
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:109
int Alphasort(const void *a, const void *b)
Definition: rpmdir.c:488
char * stpcpy(char *dest, const char *src)
const char const char size_t size
Definition: bson.h:895
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
static int avScandir(const char *path, struct dirent ***nl, int(*filter)(const struct dirent *), int(*compar)(const void *, const void *))
Definition: rpmdir.c:303
int avmagicdir
Definition: rpmdav.c:2218
static rpmavx avxGetPool(rpmioPool pool)
Definition: rpmdir.c:48
static void avSeekdir(DIR *dir, off_t offset)
Definition: rpmdir.c:338
int Closedir(DIR *dir)
closedir(3) clone.
Definition: rpmdir.c:385
rpmuint32_t hashFunctionString(rpmuint32_t h, const void *data, size_t size)
Return hash value of a string.
Definition: rpmhash.c:83
#define DT_SOCK
Definition: rpmdir.h:19
#define xmalloc
Definition: system.h:32
DIR * Opendir(const char *path)
opendir(3) clone.
Definition: rpmdir.c:396
#define pthread_mutex_init(__mutex, __attr)
Definition: yarn.c:72
off_t Telldir(DIR *dir)
telldir(3) clone.
Definition: rpmdir.c:521
urlinfo urlFree(urlinfo u, const char *msg)
Dereference a URL control structure instance.
#define xrealloc
Definition: system.h:35
modes
Definition: rpmqv.c:136
rpmioPool _avxPool
Definition: rpmdir.c:46
DIR * ftpOpendir(const char *path)
Create an argv directory from an ftp:// URI.
Definition: rpmrpc.c:1254
urlinfo urlLink(urlinfo u, const char *msg)
Reference a URL control structure instance.