Revert "init: Assign set value to avoid ambiguity"
[platform/core/system/tizen-platform-wrapper.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