• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/opkg-lede/libopkg/file_util.c

  1 /* file_util.c - convenience routines for common stat operations
  2 
  3    Copyright (C) 2009 Ubiq Technologies <graham.gower@gmail.com>
  4 
  5    Carl D. Worth
  6    Copyright (C) 2001 University of Southern California
  7 
  8    This program is free software; you can redistribute it and/or
  9    modify it under the terms of the GNU General Public License as
 10    published by the Free Software Foundation; either version 2, or (at
 11    your option) any later version.
 12 
 13    This program is distributed in the hope that it will be useful, but
 14    WITHOUT ANY WARRANTY; without even the implied warranty of
 15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16    General Public License for more details.
 17 */
 18 
 19 #include <stdio.h>
 20 #include <sys/types.h>
 21 #include <sys/stat.h>
 22 #include <dirent.h>
 23 #include <unistd.h>
 24 #include <ctype.h>
 25 
 26 #include "sprintf_alloc.h"
 27 #include "file_util.h"
 28 #include <libubox/md5.h>
 29 #include "libbb/libbb.h"
 30 
 31 #include "sha256.h"
 32 
 33 int file_exists(const char *file_name)
 34 {
 35         struct stat st;
 36 
 37         if (stat(file_name, &st) == -1)
 38                 return 0;
 39 
 40         return 1;
 41 }
 42 
 43 int file_is_dir(const char *file_name)
 44 {
 45         struct stat st;
 46 
 47         if (stat(file_name, &st) == -1)
 48                 return 0;
 49 
 50         return S_ISDIR(st.st_mode);
 51 }
 52 
 53 /* read a single line from a file, stopping at a newline or EOF.
 54    If a newline is read, it will appear in the resulting string.
 55    Return value is a malloc'ed char * which should be freed at
 56    some point by the caller.
 57 
 58    Return value is NULL if the file is at EOF when called.
 59 */
 60 char *file_read_line_alloc(FILE * fp)
 61 {
 62         size_t buf_len, line_size;
 63         char buf[BUFSIZ];
 64         char *line = NULL;
 65         int got_nl = 0;
 66 
 67         while (fgets(buf, BUFSIZ, fp)) {
 68                 buf_len = strlen(buf);
 69                 if (buf_len > 0 && buf[buf_len - 1] == '\n') {
 70                         buf_len--;
 71                         buf[buf_len] = '\0';
 72                         got_nl = 1;
 73                 }
 74                 if (line) {
 75                         line_size += buf_len;
 76                         line = xrealloc(line, line_size + 1);
 77                         strncat(line, buf, line_size);
 78                 } else {
 79                         line_size = buf_len + 1;
 80                         line = xstrdup(buf);
 81                 }
 82                 if (got_nl)
 83                         break;
 84         }
 85 
 86         return line;
 87 }
 88 
 89 int file_move(const char *src, const char *dest)
 90 {
 91         int err;
 92 
 93         err = rename(src, dest);
 94         if (err == -1) {
 95                 if (errno == EXDEV) {
 96                         /* src & dest live on different file systems */
 97                         err = file_copy(src, dest);
 98                         if (err == 0)
 99                                 unlink(src);
100                 } else {
101                         opkg_perror(ERROR, "Failed to rename %s to %s",
102                                     src, dest);
103                 }
104         }
105 
106         return err;
107 }
108 
109 int file_copy(const char *src, const char *dest)
110 {
111         int err;
112 
113         err = copy_file(src, dest, FILEUTILS_FORCE | FILEUTILS_PRESERVE_STATUS);
114         if (err)
115                 opkg_msg(ERROR, "Failed to copy file %s to %s.\n", src, dest);
116 
117         return err;
118 }
119 
120 int file_mkdir_hier(const char *path, long mode)
121 {
122         return make_directory(path, mode, FILEUTILS_RECUR);
123 }
124 
125 
126 static int hex2bin(unsigned char x)
127 {
128         if (x >= 'a' && x <= 'f')
129                 return x - 'a' + 10;
130         else if (x >= 'A' && x <= 'F')
131                 return x - 'A' + 10;
132         else if (x >= '' && x <= '9')
133                 return x - '';
134         else
135                 return 0;
136 }
137 
138 static const unsigned char bin2hex[16] = {
139         '', '1', '2', '3',
140         '4', '5', '6', '7',
141         '8', '9', 'a', 'b',
142         'c', 'd', 'e', 'f'
143 };
144 
145 char *file_md5sum_alloc(const char *file_name)
146 {
147         static const int md5sum_bin_len = 16;
148         static const int md5sum_hex_len = 32;
149 
150         int i, len;
151         char *md5sum_hex;
152         unsigned char md5sum_bin[md5sum_bin_len];
153 
154         len = md5sum(file_name, md5sum_bin);
155 
156         if (len) {
157                 opkg_msg(ERROR, "Could't compute md5sum for %s.\n", file_name);
158                 return NULL;
159         }
160 
161         md5sum_hex = xcalloc(1, md5sum_hex_len + 1);
162 
163         for (i = 0; i < md5sum_bin_len; i++) {
164                 md5sum_hex[i * 2] = bin2hex[md5sum_bin[i] >> 4];
165                 md5sum_hex[i * 2 + 1] = bin2hex[md5sum_bin[i] & 0xf];
166         }
167 
168         md5sum_hex[md5sum_hex_len] = '\0';
169 
170         return md5sum_hex;
171 }
172 
173 char *file_sha256sum_alloc(const char *file_name)
174 {
175         static const int sha256sum_bin_len = 32;
176         static const int sha256sum_hex_len = 64;
177 
178         int i, err;
179         FILE *file;
180         char *sha256sum_hex;
181         unsigned char sha256sum_bin[sha256sum_bin_len];
182 
183         sha256sum_hex = xcalloc(1, sha256sum_hex_len + 1);
184 
185         file = fopen(file_name, "r");
186         if (file == NULL) {
187                 opkg_perror(ERROR, "Failed to open file %s", file_name);
188                 free(sha256sum_hex);
189                 return NULL;
190         }
191 
192         err = sha256_stream(file, sha256sum_bin);
193         if (err) {
194                 opkg_msg(ERROR, "Could't compute sha256sum for %s.\n",
195                          file_name);
196                 fclose(file);
197                 free(sha256sum_hex);
198                 return NULL;
199         }
200 
201         fclose(file);
202 
203         for (i = 0; i < sha256sum_bin_len; i++) {
204                 sha256sum_hex[i * 2] = bin2hex[sha256sum_bin[i] >> 4];
205                 sha256sum_hex[i * 2 + 1] = bin2hex[sha256sum_bin[i] & 0xf];
206         }
207 
208         sha256sum_hex[sha256sum_hex_len] = '\0';
209 
210         return sha256sum_hex;
211 }
212 
213 char *checksum_bin2hex(const char *src, size_t len)
214 {
215         unsigned char *p;
216         static unsigned char buf[65];
217         const unsigned char *s = (unsigned char *)src;
218         if (!s || len > 32)
219                 return NULL;
220 
221         for (p = buf; len > 0; s++, len--) {
222                 *p++ = bin2hex[*s / 16];
223                 *p++ = bin2hex[*s % 16];
224         }
225 
226         *p = 0;
227 
228         return (char *)buf;
229 }
230 
231 char *checksum_hex2bin(const char *src, size_t *len)
232 {
233         static unsigned char buf[32];
234         size_t n = 0;
235 
236         *len = 0;
237 
238         if (!src)
239                 return NULL;
240 
241         while (isspace(*src))
242                 src++;
243 
244         if (strlen(src) > sizeof(buf) * 2)
245                 return NULL;
246 
247         while (*src) {
248                 if (n >= sizeof(buf) || !isxdigit(src[0]) || !isxdigit(src[1]))
249                         return NULL;
250 
251                 buf[n++] = hex2bin(src[0]) * 16 + hex2bin(src[1]);
252                 src += 2;
253         }
254 
255         *len = n;
256         return n ? (char *)buf : NULL;
257 }
258 
259 int rm_r(const char *path)
260 {
261         int ret = 0;
262         DIR *dir;
263         struct dirent *dent;
264 
265         if (path == NULL) {
266                 opkg_perror(ERROR, "Missing directory parameter");
267                 return -1;
268         }
269 
270         dir = opendir(path);
271         if (dir == NULL) {
272                 opkg_perror(ERROR, "Failed to open dir %s", path);
273                 return -1;
274         }
275 
276         if (fchdir(dirfd(dir)) == -1) {
277                 opkg_perror(ERROR, "Failed to change to dir %s", path);
278                 closedir(dir);
279                 return -1;
280         }
281 
282         while (1) {
283                 errno = 0;
284                 if ((dent = readdir(dir)) == NULL) {
285                         if (errno) {
286                                 opkg_perror(ERROR, "Failed to read dir %s",
287                                             path);
288                                 ret = -1;
289                         }
290                         break;
291                 }
292 
293                 if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
294                         continue;
295 
296 #ifdef _BSD_SOURCE
297                 if (dent->d_type == DT_DIR) {
298                         if ((ret = rm_r(dent->d_name)) == -1)
299                                 break;
300                         continue;
301                 } else if (dent->d_type == DT_UNKNOWN)
302 #endif
303                 {
304                         struct stat st;
305                         if ((ret = lstat(dent->d_name, &st)) == -1) {
306                                 opkg_perror(ERROR, "Failed to lstat %s",
307                                             dent->d_name);
308                                 break;
309                         }
310                         if (S_ISDIR(st.st_mode)) {
311                                 if ((ret = rm_r(dent->d_name)) == -1)
312                                         break;
313                                 continue;
314                         }
315                 }
316 
317                 if ((ret = unlink(dent->d_name)) == -1) {
318                         opkg_perror(ERROR, "Failed to unlink %s", dent->d_name);
319                         break;
320                 }
321         }
322 
323         if (chdir("..") == -1) {
324                 ret = -1;
325                 opkg_perror(ERROR, "Failed to change to dir %s/..", path);
326         }
327 
328         if (rmdir(path) == -1) {
329                 ret = -1;
330                 opkg_perror(ERROR, "Failed to remove dir %s", path);
331         }
332 
333         if (closedir(dir) == -1) {
334                 ret = -1;
335                 opkg_perror(ERROR, "Failed to close dir %s", path);
336         }
337 
338         return ret;
339 }
340 
341 static int urlencode_is_specialchar(char c)
342 {
343         switch (c) {
344         case ':':
345         case '?':
346         case '#':
347         case '[':
348         case ']':
349         case '@':
350         case '!':
351         case '$':
352         case '&':
353         case '\'':
354         case '(':
355         case ')':
356         case '*':
357         case '+':
358         case ',':
359         case ';':
360         case '=':
361         case '%':
362                 return 1;
363 
364         default:
365                 return 0;
366         }
367 }
368 
369 char *urlencode_path(const char *filename)
370 {
371         size_t len = 0;
372         const unsigned char *in;
373         unsigned char *copy, *out;
374 
375         for (in = (unsigned char *)filename; *in != 0; in++)
376                 len += urlencode_is_specialchar(*in) ? 3 : 1;
377 
378         copy = xcalloc(1, len + 1);
379 
380         for (in = (unsigned char *)filename, out = copy; *in != 0; in++) {
381                 if (urlencode_is_specialchar(*in)) {
382                         *out++ = '%';
383                         *out++ = bin2hex[*in / 16];
384                         *out++ = bin2hex[*in % 16];
385                 }
386                 else {
387                         *out++ = *in;
388                 }
389         }
390 
391         return (char *)copy;
392 }
393 
394 char *urldecode_path(const char *filename)
395 {
396         unsigned char *copy = (unsigned char *)xstrdup(filename);
397         unsigned char *in, *out;
398 
399         for (in = copy, out = copy; *in != 0; in++) {
400                 if (*in == '%' && isxdigit(in[1]) && isxdigit(in[2])) {
401                         *out++ = hex2bin(in[1]) * 16 + hex2bin(in[2]);
402                         in += 2;
403                 }
404                 else {
405                         *out++ = *in;
406                 }
407         }
408 
409         *out = 0;
410 
411         return (char *)copy;
412 }
413 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt