2be3ceb8bfc9a02badab7a1e10a05ecf197f06a8
[platform/upstream/rpm.git] / rpmio / rpmio_internal.h
1 #ifndef H_RPMIO_INTERNAL
2 #define H_RPMIO_INTERNAL
3
4 /** \ingroup rpmio
5  * \file rpmio/rpmio_internal.h
6  */
7
8
9 #include <rpmio.h>
10 #include <rpmurl.h>
11
12 #include <beecrypt/types.h>
13 #include <rpmpgp.h>
14 #include <rpmsw.h>
15
16 /* Drag in the beecrypt includes. */
17 #include <beecrypt/beecrypt.h>
18 #include <beecrypt/base64.h>
19 #include <beecrypt/dsa.h>
20 #include <beecrypt/endianness.h>
21 #include <beecrypt/md5.h>
22 #include <beecrypt/mp32.h>
23 #include <beecrypt/rsa.h>
24 #include <beecrypt/rsapk.h>
25 #include <beecrypt/sha1.h>
26
27 /** \ingroup rpmio
28  * Values parsed from OpenPGP signature/pubkey packet(s).
29  */
30 struct pgpDigParams_s {
31 /*@only@*/ /*@null@*/
32     const char * userid;
33 /*@only@*/ /*@null@*/
34     const byte * hash;
35     const char * params[4];
36     byte tag;
37
38     byte version;               /*!< version number. */
39     byte time[4];               /*!< time that the key was created. */
40     byte pubkey_algo;           /*!< public key algorithm. */
41
42     byte hash_algo;
43     byte sigtype;
44     byte hashlen;
45     byte signhash16[2];
46     byte signid[8];
47     byte saved;
48 #define PGPDIG_SAVED_TIME       (1 << 0)
49 #define PGPDIG_SAVED_ID         (1 << 1)
50
51 };
52
53 /** \ingroup rpmio
54  * Container for values parsed from an OpenPGP signature and public key.
55  */
56 struct pgpDig_s {
57     struct pgpDigParams_s signature;
58     struct pgpDigParams_s pubkey;
59
60     size_t nbytes;              /*!< No. bytes of plain text. */
61
62 /*@only@*/ /*@null@*/
63     DIGEST_CTX sha1ctx;         /*!< (dsa) sha1 hash context. */
64 /*@only@*/ /*@null@*/
65     DIGEST_CTX hdrsha1ctx;      /*!< (dsa) header sha1 hash context. */
66 /*@only@*/ /*@null@*/
67     void * sha1;                /*!< (dsa) V3 signature hash. */
68     size_t sha1len;             /*!< (dsa) V3 signature hash length. */
69
70 /*@only@*/ /*@null@*/
71     DIGEST_CTX md5ctx;          /*!< (rsa) md5 hash context. */
72 #ifdef  NOTYET
73 /*@only@*/ /*@null@*/
74     DIGEST_CTX hdrmd5ctx;       /*!< (rsa) header md5 hash context. */
75 #endif
76 /*@only@*/ /*@null@*/
77     void * md5;                 /*!< (rsa) V3 signature hash. */
78     size_t md5len;              /*!< (rsa) V3 signature hash length. */
79
80     /* DSA parameters. */
81     mp32barrett p;
82     mp32barrett q;
83     mp32number g;
84     mp32number y;
85     mp32number hm;
86     mp32number r;
87     mp32number s;
88
89     /* RSA parameters. */
90     rsapk rsa_pk;
91     mp32number m;
92     mp32number c;
93     mp32number rsahm;
94 };
95
96 /** \ingroup rpmio
97  */
98 typedef struct _FDSTACK_s {
99     FDIO_t              io;
100 /*@dependent@*/ void *  fp;
101     int                 fdno;
102 } FDSTACK_t;
103
104 /** \ingroup rpmio
105  * Identify per-desciptor I/O operation statistics.
106  */
107 enum FDSTAT_e {
108     FDSTAT_READ         = 0,    /*!< Read statistics index. */
109     FDSTAT_WRITE        = 1,    /*!< Write statistics index. */
110     FDSTAT_SEEK         = 2,    /*!< Seek statistics index. */
111     FDSTAT_CLOSE        = 3,    /*!< Close statistics index */
112     FDSTAT_DIGEST       = 4,    /*!< Digest statistics index. */
113     FDSTAT_MAX          = 5
114 };
115
116 /** \ingroup rpmio
117  * Cumulative statistics for a descriptor.
118  */
119 typedef /*@abstract@*/ struct {
120     struct rpmop_s      ops[FDSTAT_MAX];        /*!< Cumulative statistics. */
121 } * FDSTAT_t;
122
123 /** \ingroup rpmio
124  */
125 typedef struct _FDDIGEST_s {
126     pgpHashAlgo         hashalgo;
127     DIGEST_CTX          hashctx;
128 } * FDDIGEST_t;
129
130 /** \ingroup rpmio
131  * The FD_t File Handle data structure.
132  */
133 struct _FD_s {
134 /*@refs@*/
135     int         nrefs;
136     int         flags;
137 #define RPMIO_DEBUG_IO          0x40000000
138 #define RPMIO_DEBUG_REFS        0x20000000
139     int         magic;
140 #define FDMAGIC                 0x04463138
141     int         nfps;
142     FDSTACK_t   fps[8];
143     int         urlType;        /* ufdio: */
144
145 /*@dependent@*/
146     void *      url;            /* ufdio: URL info */
147     int         rd_timeoutsecs; /* ufdRead: per FD_t timer */
148     ssize_t     bytesRemain;    /* ufdio: */
149     ssize_t     contentLength;  /* ufdio: */
150     int         persist;        /* ufdio: */
151     int         wr_chunked;     /* ufdio: */
152
153     int         syserrno;       /* last system errno encountered */
154 /*@observer@*/
155     const void *errcookie;      /* gzdio/bzdio/ufdio: */
156
157     FDSTAT_t    stats;          /* I/O statistics */
158
159     int         ndigests;
160 #define FDDIGEST_MAX    4
161     struct _FDDIGEST_s  digests[FDDIGEST_MAX];
162
163     int         ftpFileDoneNeeded; /* ufdio: (FTP) */
164     unsigned int firstFree;     /* fadio: */
165     long int    fileSize;       /* fadio: */
166     long int    fd_cpioPos;     /* cpio: */
167 };
168 /*@access FD_t@*/
169
170 #define FDSANE(fd)      assert(fd && fd->magic == FDMAGIC)
171
172 /*@-redecl@*/
173 /*@unchecked@*/
174 extern int _rpmio_debug;
175 /*@=redecl@*/
176
177 /*@-redecl@*/
178 /*@unchecked@*/
179 extern int _ftp_debug;
180 /*@=redecl@*/
181
182 #define DBG(_f, _m, _x) \
183     if ((_rpmio_debug | ((_f) ? ((FD_t)(_f))->flags : 0)) & (_m)) fprintf _x
184
185 #if defined(__LCLINT__XXX)
186 #define DBGIO(_f, _x)
187 #define DBGREFS(_f, _x)
188 #else
189 #define DBGIO(_f, _x)   DBG((_f), RPMIO_DEBUG_IO, _x)
190 #define DBGREFS(_f, _x) DBG((_f), RPMIO_DEBUG_REFS, _x)
191 #endif
192
193 #ifdef __cplusplus
194 extern "C" {
195 #endif
196
197 /** \ingroup rpmio
198  */
199 int fdFgets(FD_t fd, char * buf, size_t len)
200         /*@globals errno, fileSystem @*/
201         /*@modifies *buf, fd, errno, fileSystem @*/;
202
203 /** \ingroup rpmio
204  */
205 /*@null@*/ FD_t ftpOpen(const char *url, /*@unused@*/ int flags,
206                 /*@unused@*/ mode_t mode, /*@out@*/ urlinfo *uret)
207         /*@globals fileSystem, internalState @*/
208         /*@modifies *uret, fileSystem, internalState @*/;
209
210 /** \ingroup rpmio
211  */
212 int ftpReq(FD_t data, const char * ftpCmd, const char * ftpArg)
213         /*@globals fileSystem, internalState @*/
214         /*@modifies data, fileSystem, internalState @*/;
215
216 /** \ingroup rpmio
217  */
218 int ftpCmd(const char * cmd, const char * url, const char * arg2)
219         /*@globals fileSystem, internalState @*/
220         /*@modifies fileSystem, internalState @*/;
221
222 /** \ingroup rpmio
223  */
224 int ufdClose( /*@only@*/ void * cookie)
225         /*@globals fileSystem, internalState @*/
226         /*@modifies cookie, fileSystem, internalState @*/;
227
228 /** \ingroup rpmio
229  */
230 /*@unused@*/ static inline
231 /*@null@*/ FDIO_t fdGetIo(FD_t fd)
232         /*@*/
233 {
234     FDSANE(fd);
235 /*@-boundsread@*/
236     return fd->fps[fd->nfps].io;
237 /*@=boundsread@*/
238 }
239
240 /** \ingroup rpmio
241  */
242 /*@-nullstate@*/ /* FIX: io may be NULL */
243 /*@unused@*/ static inline
244 void fdSetIo(FD_t fd, /*@kept@*/ /*@null@*/ FDIO_t io)
245         /*@modifies fd @*/
246 {
247     FDSANE(fd);
248 /*@-boundswrite@*/
249     /*@-assignexpose@*/
250     fd->fps[fd->nfps].io = io;
251     /*@=assignexpose@*/
252 /*@=boundswrite@*/
253 }
254 /*@=nullstate@*/
255
256 /** \ingroup rpmio
257  */
258 /*@unused@*/ static inline
259 /*@exposed@*/ /*@dependent@*/ /*@null@*/ FILE * fdGetFILE(FD_t fd)
260         /*@*/
261 {
262     FDSANE(fd);
263 /*@-boundsread@*/
264     /*@+voidabstract@*/
265     return ((FILE *)fd->fps[fd->nfps].fp);
266     /*@=voidabstract@*/
267 /*@=boundsread@*/
268 }
269
270 /** \ingroup rpmio
271  */
272 /*@unused@*/ static inline
273 /*@exposed@*/ /*@dependent@*/ /*@null@*/ void * fdGetFp(FD_t fd)
274         /*@*/
275 {
276     FDSANE(fd);
277 /*@-boundsread@*/
278     return fd->fps[fd->nfps].fp;
279 /*@=boundsread@*/
280 }
281
282 /** \ingroup rpmio
283  */
284 /*@-nullstate@*/ /* FIX: fp may be NULL */
285 /*@unused@*/ static inline
286 void fdSetFp(FD_t fd, /*@kept@*/ /*@null@*/ void * fp)
287         /*@modifies fd @*/
288 {
289     FDSANE(fd);
290 /*@-boundswrite@*/
291     /*@-assignexpose@*/
292     fd->fps[fd->nfps].fp = fp;
293     /*@=assignexpose@*/
294 /*@=boundswrite@*/
295 }
296 /*@=nullstate@*/
297
298 /** \ingroup rpmio
299  */
300 /*@unused@*/ static inline
301 int fdGetFdno(FD_t fd)
302         /*@*/
303 {
304     FDSANE(fd);
305 /*@-boundsread@*/
306     return fd->fps[fd->nfps].fdno;
307 /*@=boundsread@*/
308 }
309
310 /** \ingroup rpmio
311  */
312 /*@unused@*/ static inline
313 void fdSetFdno(FD_t fd, int fdno)
314         /*@modifies fd @*/
315 {
316     FDSANE(fd);
317 /*@-boundswrite@*/
318     fd->fps[fd->nfps].fdno = fdno;
319 /*@=boundswrite@*/
320 }
321
322 /** \ingroup rpmio
323  */
324 /*@unused@*/ static inline
325 void fdSetContentLength(FD_t fd, ssize_t contentLength)
326         /*@modifies fd @*/
327 {
328     FDSANE(fd);
329     fd->contentLength = fd->bytesRemain = contentLength;
330 }
331
332 /** \ingroup rpmio
333  */
334 /*@unused@*/ static inline
335 void fdPush(FD_t fd, FDIO_t io, void * fp, int fdno)
336         /*@modifies fd @*/
337 {
338     FDSANE(fd);
339     if (fd->nfps >= (sizeof(fd->fps)/sizeof(fd->fps[0]) - 1))
340         return;
341     fd->nfps++;
342     fdSetIo(fd, io);
343     fdSetFp(fd, fp);
344     fdSetFdno(fd, fdno);
345 }
346
347 /** \ingroup rpmio
348  */
349 /*@unused@*/ static inline void fdPop(FD_t fd)
350         /*@modifies fd @*/
351 {
352     FDSANE(fd);
353     if (fd->nfps < 0) return;
354     fdSetIo(fd, NULL);
355     fdSetFp(fd, NULL);
356     fdSetFdno(fd, -1);
357     fd->nfps--;
358 }
359
360 /** \ingroup rpmio
361  */
362 /*@unused@*/ static inline
363 void fdstat_enter(/*@null@*/ FD_t fd, int opx)
364         /*@globals internalState @*/
365         /*@modifies fd, internalState @*/
366 {
367     if (fd == NULL) return;
368 /*@-boundswrite@*/
369     if (fd->stats != NULL)
370         (void) rpmswEnter(&fd->stats->ops[opx], 0);
371 /*@=boundswrite@*/
372 }
373
374 /** \ingroup rpmio
375  */
376 /*@unused@*/ static inline
377 void fdstat_exit(/*@null@*/ FD_t fd, int opx, ssize_t rc)
378         /*@globals internalState @*/
379         /*@modifies fd, internalState @*/
380 {
381     if (fd == NULL) return;
382     if (rc == -1)
383         fd->syserrno = errno;
384     else if (rc > 0 && fd->bytesRemain > 0)
385         fd->bytesRemain -= rc;
386 /*@-boundswrite@*/
387     if (fd->stats != NULL)
388         (void) rpmswExit(&fd->stats->ops[opx], rc);
389 /*@=boundswrite@*/
390 }
391
392 /** \ingroup rpmio
393  */
394 /*@-boundsread@*/
395 /*@unused@*/ static inline
396 void fdstat_print(/*@null@*/ FD_t fd, const char * msg, FILE * fp)
397         /*@globals fileSystem @*/
398         /*@modifies *fp, fileSystem @*/
399 {
400     static int usec_scale = (1000*1000);
401     int opx;
402
403     if (fd == NULL || fd->stats == NULL) return;
404     for (opx = 0; opx < 4; opx++) {
405         rpmop op = &fd->stats->ops[opx];
406         if (op->count <= 0) continue;
407         switch (opx) {
408         case FDSTAT_READ:
409             if (msg) fprintf(fp, "%s:", msg);
410             fprintf(fp, "%8d reads, %8ld total bytes in %d.%06d secs\n",
411                 op->count, (long)op->bytes,
412                 (int)(op->usecs/usec_scale), (int)(op->usecs%usec_scale));
413             /*@switchbreak@*/ break;
414         case FDSTAT_WRITE:
415             if (msg) fprintf(fp, "%s:", msg);
416             fprintf(fp, "%8d writes, %8ld total bytes in %d.%06d secs\n",
417                 op->count, (long)op->bytes,
418                 (int)(op->usecs/usec_scale), (int)(op->usecs%usec_scale));
419             /*@switchbreak@*/ break;
420         case FDSTAT_SEEK:
421             /*@switchbreak@*/ break;
422         case FDSTAT_CLOSE:
423             /*@switchbreak@*/ break;
424         }
425     }
426 }
427 /*@=boundsread@*/
428
429 /** \ingroup rpmio
430  */
431 /*@unused@*/ static inline
432 void fdSetSyserrno(FD_t fd, int syserrno, /*@kept@*/ const void * errcookie)
433         /*@modifies fd @*/
434 {
435     FDSANE(fd);
436     fd->syserrno = syserrno;
437     /*@-assignexpose@*/
438     fd->errcookie = errcookie;
439     /*@=assignexpose@*/
440 }
441
442 /** \ingroup rpmio
443  */
444 /*@unused@*/ static inline
445 int fdGetRdTimeoutSecs(FD_t fd)
446         /*@*/
447 {
448     FDSANE(fd);
449     return fd->rd_timeoutsecs;
450 }
451
452 /** \ingroup rpmio
453  */
454 /*@unused@*/ static inline
455 long int fdGetCpioPos(FD_t fd)
456         /*@*/
457 {
458     FDSANE(fd);
459     return fd->fd_cpioPos;
460 }
461
462 /** \ingroup rpmio
463  */
464 /*@unused@*/ static inline
465 void fdSetCpioPos(FD_t fd, long int cpioPos)
466         /*@modifies fd @*/
467 {
468     FDSANE(fd);
469     fd->fd_cpioPos = cpioPos;
470 }
471
472 /** \ingroup rpmio
473  */
474 /*@mayexit@*/ /*@unused@*/ static inline
475 FD_t c2f(/*@null@*/ void * cookie)
476         /*@*/
477 {
478     /*@-castexpose@*/
479     FD_t fd = (FD_t) cookie;
480     /*@=castexpose@*/
481     FDSANE(fd);
482     /*@-refcounttrans -retalias@*/ return fd; /*@=refcounttrans =retalias@*/
483 }
484
485 /** \ingroup rpmio
486  * Attach digest to fd.
487  */
488 /*@unused@*/ static inline
489 void fdInitDigest(FD_t fd, pgpHashAlgo hashalgo, int flags)
490         /*@modifies fd @*/
491 {
492     FDDIGEST_t fddig = fd->digests + fd->ndigests;
493     if (fddig != (fd->digests + FDDIGEST_MAX)) {
494         fd->ndigests++;
495         fddig->hashalgo = hashalgo;
496         fdstat_enter(fd, FDSTAT_DIGEST);
497         fddig->hashctx = rpmDigestInit(hashalgo, flags);
498         fdstat_exit(fd, FDSTAT_DIGEST, 0);
499     }
500 }
501
502 /** \ingroup rpmio
503  * Update digest(s) attached to fd.
504  */
505 /*@unused@*/ static inline
506 void fdUpdateDigests(FD_t fd, const unsigned char * buf, ssize_t buflen)
507         /*@modifies fd @*/
508 {
509     int i;
510
511     if (buf != NULL && buflen > 0)
512     for (i = fd->ndigests - 1; i >= 0; i--) {
513         FDDIGEST_t fddig = fd->digests + i;
514         if (fddig->hashctx == NULL)
515             continue;
516         fdstat_enter(fd, FDSTAT_DIGEST);
517         (void) rpmDigestUpdate(fddig->hashctx, buf, buflen);
518         fdstat_exit(fd, FDSTAT_DIGEST, buflen);
519     }
520 }
521
522 /** \ingroup rpmio
523  */
524 /*@unused@*/ static inline
525 void fdFiniDigest(FD_t fd, pgpHashAlgo hashalgo,
526                 /*@null@*/ /*@out@*/ void ** datap,
527                 /*@null@*/ /*@out@*/ size_t * lenp,
528                 int asAscii)
529         /*@modifies fd, *datap, *lenp @*/
530 {
531     int imax = -1;
532     int i;
533
534     for (i = fd->ndigests - 1; i >= 0; i--) {
535         FDDIGEST_t fddig = fd->digests + i;
536         if (fddig->hashctx == NULL)
537             continue;
538         if (i > imax) imax = i;
539         if (fddig->hashalgo != hashalgo)
540             continue;
541         fdstat_enter(fd, FDSTAT_DIGEST);
542         (void) rpmDigestFinal(fddig->hashctx, datap, lenp, asAscii);
543         fdstat_exit(fd, FDSTAT_DIGEST, 0);
544         fddig->hashctx = NULL;
545         break;
546     }
547 /*@-boundswrite@*/
548     if (i < 0) {
549         if (datap) *datap = NULL;
550         if (lenp) *lenp = 0;
551     }
552 /*@=boundswrite@*/
553
554     fd->ndigests = imax;
555     if (i < imax)
556         fd->ndigests++;         /* convert index to count */
557 }
558
559 /*@-shadow@*/
560 /** \ingroup rpmio
561  */
562 /*@unused@*/ static inline
563 int fdFileno(/*@null@*/ void * cookie)
564         /*@*/
565 {
566     FD_t fd;
567     if (cookie == NULL) return -2;
568     fd = c2f(cookie);
569 /*@-boundsread@*/
570     return fd->fps[0].fdno;
571 /*@=boundsread@*/
572 }
573 /*@=shadow@*/
574
575 /**
576  * Read an entire file into a buffer.
577  * @param fn            file name to read
578  * @retval *bp          (malloc'd) buffer address
579  * @retval *blenp       (malloc'd) buffer length
580  * @return              0 on success
581  */
582 int rpmioSlurp(const char * fn,
583                 /*@out@*/ const unsigned char ** bp, /*@out@*/ ssize_t * blenp)
584         /*@globals fileSystem, internalState @*/
585         /*@modifies *bp, *blenp, fileSystem, internalState @*/;
586
587 #ifdef __cplusplus
588 }
589 #endif
590
591 #endif  /* H_RPMIO_INTERNAL */