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 < 0) { 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