rpm  5.2.1
rpmiob.c
Go to the documentation of this file.
1 
4 #include "system.h"
5 #define _RPMIOB_INTERNAL
6 #include <rpmiotypes.h>
7 #include <rpmio.h>
8 #include "debug.h"
9 
10 /*@unchecked@*/
11 size_t _rpmiob_chunk = 1024;
12 
13 /*@unchecked@*/
15 
16 static void rpmiobFini(void * _iob)
17 {
18  rpmiob iob = _iob;
19 
20  iob->b = _free(iob->b);
21  iob->blen = 0;
22  iob->allocated = 0;
23 }
24 
25 /*@unchecked@*/ /*@only@*/ /*@null@*/
27 
28 static rpmiob rpmiobGetPool(/*@null@*/ rpmioPool pool)
29  /*@globals _rpmiobPool, fileSystem @*/
30  /*@modifies pool, _rpmiobPool, fileSystem @*/
31 {
32  rpmiob iob;
33 
34  if (_rpmiobPool == NULL) {
35  _rpmiobPool = rpmioNewPool("iob", sizeof(*iob), -1, _rpmiob_debug,
36  NULL, NULL, rpmiobFini);
37  pool = _rpmiobPool;
38  }
39  return (rpmiob) rpmioGetPool(pool, sizeof(*iob));
40 }
41 
42 rpmiob rpmiobNew(size_t len)
43 {
44  rpmiob iob = rpmiobGetPool(_rpmiobPool);
45  if (len == 0)
46  len = _rpmiob_chunk;
47  iob->allocated = len;
48  iob->blen = 0;
49  iob->b = xcalloc(iob->allocated+1, sizeof(*iob->b));
50  return rpmiobLink(iob);
51 }
52 
54 {
55 assert(iob != NULL);
56  iob->b[0] = '\0';
57  iob->blen = 0;
58  return iob;
59 }
60 
62 {
63 
64 assert(iob != NULL);
65  while (iob->blen > 0 && xisspace((int)iob->b[iob->blen-1]))
66  iob->b[--iob->blen] = (rpmuint8_t) '\0';
67  return iob;
68 }
69 
70 rpmiob rpmiobAppend(rpmiob iob, const char * s, size_t nl)
71 {
72  size_t ns = strlen(s);
73  rpmuint8_t * tail;
74 
75  if (nl > 0) ns++;
76 
77 assert(iob != NULL);
78  if ((iob->blen + ns) > iob->allocated) {
79  iob->allocated += ((ns+_rpmiob_chunk-1)/_rpmiob_chunk) * _rpmiob_chunk;
80  iob->b = xrealloc(iob->b, iob->allocated+1);
81  }
82 
83  tail = iob->b + iob->blen;
84  tail = (rpmuint8_t *) stpcpy((char *)tail, s);
85  if (nl > 0) {
86  *tail++ = (rpmuint8_t) '\n';
87  *tail = (rpmuint8_t) '\0';
88  }
89  iob->blen += ns;
90  return iob;
91 }
92 
94 {
95 assert(iob != NULL);
96 /*@-retalias -retexpose -usereleased @*/
97  return iob->b;
98 /*@=retalias =retexpose =usereleased @*/
99 }
100 
101 char * rpmiobStr(rpmiob iob)
102 {
103 assert(iob != NULL);
104 /*@-retalias -retexpose -usereleased @*/
105  return (char *) iob->b;
106 /*@=retalias =retexpose =usereleased @*/
107 }
108 
109 size_t rpmiobLen(rpmiob iob)
110 {
111  return (iob != NULL ? iob->blen : 0);
112 }
113 
114 int rpmiobSlurp(const char * fn, rpmiob * iobp)
115 {
116  static size_t blenmax = (32 * BUFSIZ);
117  rpmuint8_t * b = NULL;
118  size_t blen;
119  struct stat sb;
120  FD_t fd;
121  int rc = 0;
122  int xx;
123 
124  fd = Fopen(fn, "r%{?_rpmgio}");
125  if (fd == NULL || Ferror(fd)) {
126  rc = 2;
127  goto exit;
128  }
129  sb.st_size = 0;
130  if ((xx = Fstat(fd, &sb)) < 0 || sb.st_size == 0)
131  sb.st_size = blenmax;
132 #if defined(__linux__)
133  /* XXX st->st_size = 0 for /proc files on linux, see stat(2). */
134  /* XXX glibc mmap'd libio no workie for /proc files on linux?!? */
135  if (sb.st_size == 0 && !strncmp(fn, "/proc/", sizeof("/proc/")-1)) {
136  blen = blenmax;
137  b = xmalloc(blen+1);
138  b[0] = (rpmuint8_t) '\0';
139 
140  xx = read(Fileno(fd), b, blen);
141  blen = (size_t) (xx >= 0 ? xx : 0);
142  } else
143 #endif
144  {
145  blen = sb.st_size;
146  b = xmalloc(blen+1);
147  b[0] = (rpmuint8_t) '\0';
148 
149  blen = Fread(b, sizeof(*b), blen, fd);
150  if (Ferror(fd)) {
151  rc = 1;
152  goto exit;
153  }
154  }
155  if (blen < (size_t)sb.st_size)
156  b = xrealloc(b, blen+1);
157  b[blen] = (rpmuint8_t) '\0';
158 
159 exit:
160  if (fd != NULL) (void) Fclose(fd);
161 
162  if (rc == 0) {
163  if (iobp != NULL) {
164  /* XXX use rpmiobNew() if/when lazy iop->b alloc is implemented. */
165  rpmiob iob = rpmiobGetPool(_rpmiobPool);
166  iob->b = b;
167  iob->blen = blen;
168  iob->allocated = blen;
169  *iobp = iob;
170  }
171  } else {
172  if (iobp)
173  *iobp = NULL;
174  b = _free(b);
175  }
176 
177  return rc;
178 }