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