dedup

deduplicating backup program
git clone git://git.2f30.org/dedup
Log | Files | Refs | README | LICENSE

unpack.c (2424B)


      1 /*
      2  * ISC License
      3  *
      4  * (c) 2019 Roberto E. Vargas Caballero <k0ga@shike2.com>
      5  *
      6  * Permission to use, copy, modify, and/or distribute this software for any
      7  * purpose with or without fee is hereby granted, provided that the above
      8  * copyright notice and this permission notice appear in all copies.
      9  *
     10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  */
     18 
     19 #include <ctype.h>
     20 #include <stdarg.h>
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 
     24 static int
     25 lunpack(unsigned char *src, char *fmt, va_list va)
     26 {
     27 	unsigned char *bp, *cp;
     28 	unsigned short *sp;
     29 	unsigned s;
     30 	unsigned long *lp, l;
     31 	unsigned long long *qp, q;
     32 	int n;
     33 
     34 	bp = src;
     35 	while (*fmt) {
     36 		switch (*fmt++) {
     37 		case '\'':
     38 			n = atoi(fmt);
     39 			while (isdigit(*fmt))
     40 				fmt++;
     41 			cp = va_arg(va, unsigned char *);
     42 			while (n--)
     43 				*cp++ = *bp++;
     44 			break;
     45 		case 'c':
     46 			cp = va_arg(va, unsigned char *);
     47 			*cp = *bp++;
     48 			break;
     49 		case 's':
     50 			sp = va_arg(va, unsigned short *);
     51 			s =  (unsigned) *bp++;
     52 			s |= (unsigned) *bp++ << 8;
     53 			*sp = s;
     54 			break;
     55 		case 'l':
     56 			lp = va_arg(va, unsigned long *);
     57 			l = (unsigned long) *bp++;
     58 			l |= (unsigned long) *bp++ << 8;
     59 			l |= (unsigned long) *bp++ << 16;
     60 			l |= (unsigned long) *bp++ << 24;
     61 			*lp = l;
     62 			break;
     63 		case 'q':
     64 			qp = va_arg(va, unsigned long long *);
     65 			q = (unsigned long long) *bp++;
     66 			q |= (unsigned long long) *bp++ << 8;
     67 			q |= (unsigned long long) *bp++ << 16;
     68 			q |= (unsigned long long) *bp++ << 24;
     69 			q |= (unsigned long long) *bp++ << 32;
     70 			q |= (unsigned long long) *bp++ << 40;
     71 			q |= (unsigned long long) *bp++ << 48;
     72 			q |= (unsigned long long) *bp++ << 56;
     73 			*qp = q;
     74 			break;
     75 		default:
     76 			va_end(va);
     77 			return -1;
     78 		}
     79 	}
     80 
     81 	return bp - src;
     82 }
     83 
     84 int
     85 unpack(unsigned char *src, char *fmt, ...)
     86 {
     87 	int r;
     88         int (*fn)(unsigned char *dst, char *fmt, va_list va);
     89         va_list va;
     90 
     91         va_start(va, fmt);
     92         fn = lunpack;
     93         r = (*fn)(src, fmt, va);
     94         va_end(va);
     95 
     96         return r;
     97 }