Split required functions for public
[platform/core/system/tizen-platform-config.git] / src / sha256sum.c
1 /*
2  * Copyright (C) 2013-2014 Intel Corporation.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Authors:
19  *       José Bollo <jose.bollo@open.eurogiciel.org>
20  *       Stéphane Desneux <stephane.desneux@open.eurogiciel.org>
21  *       Jean-Benoit Martin <jean-benoit.martin@open.eurogiciel.org>
22  *
23  */
24 #define _GNU_SOURCE
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #include <sys/types.h>
34 #include <sys/wait.h>
35 #include <fcntl.h>
36 #include <string.h>
37
38 #include "sha256sum.h"
39
40 static const char *arg[2] = { "/usr/bin/sha256sum", NULL };
41
42 struct sha256sum {
43         enum { RUNNING, FAILED, SUCCESSED } state;
44         pid_t pid;
45         int tofd;
46         int fromfd;
47         char result[32];
48 };
49
50 struct sha256sum *sha256sum_create()
51 {
52         int fds1[2];
53         int fds2[2];
54         pid_t pid;
55         int sts;
56         struct sha256sum *result;
57
58         result = malloc(sizeof * result);
59         if (result == NULL)
60                 return NULL;
61
62         sts = pipe(fds1);
63         if (sts != 0) {
64                 free(result);
65                 return NULL;
66         }
67
68         sts = pipe(fds2);
69         if (sts != 0) {
70                 close(fds1[0]);
71                 close(fds1[1]);
72                 free(result);
73                 return NULL;
74         }
75
76         pid = fork();
77         if (pid == -1) {
78                 close(fds1[0]);
79                 close(fds1[1]);
80                 close(fds2[0]);
81                 close(fds2[1]);
82                 free(result);
83                 return NULL;
84         }
85
86         if (pid == 0) {
87                 dup2(fds1[0], 0);
88                 dup2(fds2[1], 1);
89                 close(fds1[0]);
90                 close(fds1[1]);
91                 close(fds2[0]);
92                 close(fds2[1]);
93                 execve(arg[0], (char**)arg, environ);
94                 exit(1);
95         }
96
97         close(fds1[0]);
98         close(fds2[1]);
99         result->state = RUNNING;
100         result->pid = pid;
101         result->tofd = fds1[1];
102         result->fromfd = fds2[0];
103         return result;
104 }
105
106 void sha256sum_destroy(struct sha256sum *s)
107 {
108         int sts;
109
110         if (s->state == RUNNING) {
111                 close(s->fromfd);
112                 close(s->tofd);
113                 waitpid(s->pid, &sts, 0);
114         }
115         free(s);
116 }
117
118 int sha256sum_add_data(struct sha256sum *s, const void *data, size_t length)
119 {
120         ssize_t sl;
121         int sts;
122
123         if (s->state != RUNNING)
124                 return -1;
125
126         while (length) {
127                 do {
128                         sl = write(s->tofd, data, length);
129                 } while (sl == -1 && (errno == EINTR || errno == EAGAIN));
130                 if (sl == -1) {
131                         s->state = FAILED;
132                         close(s->fromfd);
133                         close(s->tofd);
134                         waitpid(s->pid, &sts, 0);
135                         return -1;
136                 }
137                 length -= (size_t)sl;
138                 data = (const void*)((const char*)data + (size_t)sl);
139         }
140         return 0;
141 }
142
143 int sha256sum_add_file(struct sha256sum *s, const char *filename)
144 {
145         char buffer[16384];
146         int fd;
147         ssize_t rd;
148
149         fd = open(filename, O_RDONLY);
150         if (fd < 0)
151                 return -1;
152
153         for (;;) {
154                 do {
155                         rd = read(fd, buffer, sizeof buffer);
156                 } while (rd == -1 && (errno == EINTR || errno == EAGAIN));
157                 if (rd == -1) {
158                         close(fd);
159                         return -1;
160                 }
161                 if (rd == 0) {
162                         close(fd);
163                         return 0;
164                 }
165                 if (sha256sum_add_data(s, buffer, (size_t)rd)) {
166                         close(fd);
167                         return -1;
168                 }
169         }
170 }
171
172 int sha256sum_get(struct sha256sum *s, char result[32])
173 {
174         int sts;
175         int j;
176         char buffer[65];
177         char c1;
178         char c2;
179
180         if (s->state == RUNNING) {
181                 s->state = FAILED;
182                 close(s->tofd);
183                 waitpid(s->pid, &sts, 0);
184                 if (WIFEXITED(sts) && WEXITSTATUS(sts) == 0) {
185                         sts = read(s->fromfd, buffer, 65);
186                         if (sts == 65 && buffer[64] == ' ') {
187                                 s->state = SUCCESSED;
188                                 for (j = 0 ; j < 32 ; j++) {
189                                         c1 = buffer[j+j];
190                                         if ('0' <= c1 && c1 <= '9')
191                                                 c1 = c1 - '0';
192                                         else if ('a' <= c1 && c1 <= 'f')
193                                                 c1 = c1 - 'a' + '\012';
194                                         else if ('A' <= c1 && c1 <= 'F')
195                                                 c1 = c1 - 'A' + '\012';
196                                         else {
197                                                 s->state = FAILED;
198                                                 break;
199                                         }
200                                         c2 = buffer[j+j+1];
201                                         if ('0' <= c2 && c2 <= '9')
202                                                 c2 = c2 - '0';
203                                         else if ('a' <= c2 && c2 <= 'f')
204                                                 c2 = c2 - 'a' + '\012';
205                                         else if ('A' <= c2 && c2 <= 'F')
206                                                 c2 = c2 - 'A' + '\012';
207                                         else {
208                                                 s->state = FAILED;
209                                                 break;
210                                         }
211                                         s->result[j] = (c1 << 4) | c2;
212                                 }
213                         }
214                 }
215                 close(s->fromfd);
216         }
217
218         if (s->state == FAILED)
219                 return -1;
220
221         memcpy(result, s->result, 32);
222
223         return 0;
224 }
225
226 #ifdef TEST
227 #include <stdio.h>
228 #include <assert.h>
229 int main(int argc, char **argv)
230 {
231         char sum[32];
232         int j, r;
233         struct sha256sum *s;
234
235         while (*++argv) {
236                 s = sha256sum_create();
237                 assert(s != NULL);
238                 r = sha256sum_add_file(s, *argv);
239                 assert(r == 0);
240                 r = sha256sum_get(s, sum);
241                 assert(r == 0);
242                 sha256sum_destroy(s);
243                 for (j = 0 ; j < 32 ; j++)
244                         printf("%02x", (int)(unsigned char)sum[j]);
245                 printf("  %s\n", *argv);
246         }
247         return 0;
248 }
249 #endif
250