Whamcloud - gitweb
Fix clang warnings on architectures with a 64-bit long
[tools/e2fsprogs.git] / lib / ext2fs / digest_encode.c
1 /*
2  * lib/ext2fs/digest_encode.c
3  *
4  * A function to encode a digest using 64 characters that are valid in a
5  * filename per ext2fs rules.
6  *
7  * Written by Uday Savagaonkar, 2014.
8  *
9  * Copyright 2014 Google Inc.  All Rights Reserved.
10  *
11  * %Begin-Header%
12  * This file may be redistributed under the terms of the GNU Library
13  * General Public License, version 2.
14  * %End-Header%
15  */
16
17 #include "config.h"
18 #if HAVE_SYS_TYPES_H
19 #include <sys/types.h>
20 #endif
21 #include "ext2fs.h"
22
23 static const char *lookup_table =
24         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,";
25
26 /**
27  * ext2fs_digest_encode() -
28  *
29  * Encodes the input digest using characters from the set [a-zA-Z0-9_+].
30  * The encoded string is roughly 4/3 times the size of the input string.
31  */
32 int ext2fs_digest_encode(const char *src, int len, char *dst)
33 {
34         int i = 0, bits = 0, ac = 0;
35         char *cp = dst;
36
37         while (i < len) {
38                 ac += (((unsigned char) src[i]) << bits);
39                 bits += 8;
40                 do {
41                         *cp++ = lookup_table[ac & 0x3f];
42                         ac >>= 6;
43                         bits -= 6;
44                 } while (bits >= 6);
45                 i++;
46         }
47         if (bits)
48                 *cp++ = lookup_table[ac & 0x3f];
49         return cp - dst;
50 }
51
52 int ext2fs_digest_decode(const char *src, int len, char *dst)
53 {
54         int i = 0, bits = 0, ac = 0;
55         const char *p;
56         char *cp = dst;
57
58         while (i < len) {
59                 p = strchr(lookup_table, src[i]);
60                 if (p == NULL || src[i] == 0)
61                         return -1;
62                 ac += (p - lookup_table) << bits;
63                 bits += 6;
64                 if (bits >= 8) {
65                         *cp++ = ac & 0xff;
66                         ac >>= 8;
67                         bits -= 8;
68                 }
69                 i++;
70         }
71         if (ac)
72                 return -1;
73         return cp - dst;
74 }
75
76
77 #ifdef UNITTEST
78 static const struct {
79         unsigned char d[32];
80         unsigned int len;
81         const char *ed;
82 } tests[] = {
83         { { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
84             0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
85             0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
86             0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 }, 32,
87         "jDLxChJ,cQhm7TPyZ+WukcirBROZbOJTkWZmbgnU4WF"
88         },
89         { { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
90             0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
91             0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
92             0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }, 32,
93         "6inF,+YAPreQBBk3d5qIjA7AhNqlXoHn0Cx,hJPAV0K"
94         },
95         { { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8,
96             0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39,
97             0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67,
98             0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }, 32,
99         "k0oahJtB4gb5AbykM4DY5MKPknFZ,HyZ2ze7Unx2GEM"
100         },
101         { { 0x00, }, 1,
102         "AA"
103         },
104         { { 0x01, }, 1,
105         "BA"
106         },
107         { { 0x01, 0x02 }, 2,
108         "BIA"
109         },
110         { { 0x01, 0x02, 0x03 }, 3,
111         "BIwA"
112         },
113         { { 0x01, 0x02, 0x03, 0x04 }, 4,
114         "BIwAEA"
115         },
116         { { 0x01, 0x02, 0x03, 0x04, 0xff }, 5,
117         "BIwAE8P"
118         },
119         { { 0x01, 0x02, 0x03, 0x04, 0xff, 0xfe }, 6,
120         "BIwAE8v,"
121         },
122         { { 0x01, 0x02, 0x03, 0x04, 0xff, 0xfe, 0xfd }, 7,
123         "BIwAE8v,9D"
124         },
125 };
126
127 int main(int argc, char **argv)
128 {
129         int i, ret, len;
130         int errors = 0;
131         char tmp[1024], tmp2[1024];
132
133         if (argc == 3 && !strcmp(argv[1], "encode")) {
134                 memset(tmp, 0, sizeof(tmp));
135                 ext2fs_digest_encode(argv[2], strlen(argv[2]), tmp);
136                 puts(tmp);
137                 exit(0);
138         }
139         if (argc == 3 && !strcmp(argv[1], "decode")) {
140                 memset(tmp, 0, sizeof(tmp));
141                 ret = ext2fs_digest_decode(argv[2], strlen(argv[2]), tmp);
142                 puts(tmp);
143                 fprintf(stderr, "returned %d\n", ret);
144                 exit(0);
145         }
146         for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
147                 memset(tmp, 0, sizeof(tmp));
148                 ret = ext2fs_digest_encode((const char *) tests[i].d,
149                                            tests[i].len, tmp);
150                 len = strlen(tmp);
151                 printf("Test Digest %d (returned %d): ", i, ret);
152                 if (ret != len) {
153                         printf("FAILED returned %d, string length was %d\n",
154                                ret, len);
155                         errors++;
156                         continue;
157                 } else if (strcmp(tmp, tests[i].ed) != 0) {
158                         printf("FAILED: got %s, expected %s\n", tmp,
159                                tests[i].ed);
160                         errors++;
161                         continue;
162                 }
163                 ret = ext2fs_digest_decode(tmp, len, tmp2);
164                 if (ret != tests[i].len) {
165                         printf("FAILED decode returned %d, expected %d\n",
166                                ret, tests[i].len);
167                         errors++;
168                         continue;
169                 }
170                 if (memcmp(tmp2, tests[i].d, ret) != 0) {
171                         puts("FAILED: decode mismatched");
172                         errors++;
173                         continue;
174                 }
175                 printf("OK\n");
176         }
177         for (i = 1; i < argc; i++) {
178                 memset(tmp, 0, sizeof(tmp));
179                 ret = ext2fs_digest_encode(argv[i], strlen(argv[i]), tmp);
180                 len = strlen(tmp);
181                 printf("Digest of '%s' is '%s' (returned %d, length %d)\n",
182                        argv[i], tmp, ret, len);
183         }
184         return errors;
185 }
186
187 #endif /* UNITTEST */