X-Git-Url: https://git.librecmc.org/?p=oweals%2Fopkg-lede.git;a=blobdiff_plain;f=libopkg%2Ffile_util.c;h=155d73b52be1ac81d88ebfd851c50c98ede6f012;hp=3ab1cc571660efa3856812f54e767fe9c078e6f5;hb=54cc7e3bd1f79569022aa9fc3d0e748c81e3bcd8;hpb=9e9f4261abe887b1d98dedabd6b52dbc238d82bf diff --git a/libopkg/file_util.c b/libopkg/file_util.c index 3ab1cc5..155d73b 100644 --- a/libopkg/file_util.c +++ b/libopkg/file_util.c @@ -1,7 +1,8 @@ /* file_util.c - convenience routines for common stat operations - Carl D. Worth + Copyright (C) 2009 Ubiq Technologies + Carl D. Worth Copyright (C) 2001 University of Southern California This program is free software; you can redistribute it and/or @@ -15,40 +16,44 @@ General Public License for more details. */ -#include "opkg.h" +#include "config.h" + +#include #include #include +#include +#include +#include #include "sprintf_alloc.h" #include "file_util.h" +#ifdef HAVE_MD5 #include "md5.h" +#endif #include "libbb/libbb.h" -#undef strlen + +#if defined HAVE_SHA256 +#include "sha256.h" +#endif int file_exists(const char *file_name) { - int err; - struct stat stat_buf; + struct stat st; + + if (stat(file_name, &st) == -1) + return 0; - err = stat(file_name, &stat_buf); - if (err == 0) { return 1; - } else { - return 0; - } } int file_is_dir(const char *file_name) { - int err; - struct stat stat_buf; + struct stat st; - err = stat(file_name, &stat_buf); - if (err) { - return 0; - } + if (stat(file_name, &st) == -1) + return 0; - return S_ISDIR(stat_buf.st_mode); + return S_ISDIR(st.st_mode); } /* read a single line from a file, stopping at a newline or EOF. @@ -58,120 +63,303 @@ int file_is_dir(const char *file_name) Return value is NULL if the file is at EOF when called. */ -#define FILE_READ_LINE_BUF_SIZE 1024 -char *file_read_line_alloc(FILE *file) +char *file_read_line_alloc(FILE * fp) { - char buf[FILE_READ_LINE_BUF_SIZE]; - int buf_len; - char *line = NULL; - int line_size = 0; - - memset(buf, 0, FILE_READ_LINE_BUF_SIZE); - while (fgets(buf, FILE_READ_LINE_BUF_SIZE, file)) { - buf_len = strlen(buf); - if (line) { - line_size += buf_len; - line = realloc(line, line_size); - if (line == NULL) { - fprintf(stderr, "%s: out of memory\n", __FUNCTION__); - break; - } - strcat(line, buf); - } else { - line_size = buf_len + 1; - line = strdup(buf); - } - if (buf[buf_len - 1] == '\n') { - break; - } - } - - return line; + char buf[BUFSIZ]; + unsigned int buf_len; + char *line = NULL; + unsigned int line_size = 0; + int got_nl = 0; + + buf[0] = '\0'; + + while (fgets(buf, BUFSIZ, fp)) { + buf_len = strlen(buf); + if (buf[buf_len - 1] == '\n') { + buf_len--; + buf[buf_len] = '\0'; + got_nl = 1; + } + if (line) { + line_size += buf_len; + line = xrealloc(line, line_size + 1); + strncat(line, buf, line_size); + } else { + line_size = buf_len + 1; + line = xstrdup(buf); + } + if (got_nl) + break; + } + + return line; } int file_move(const char *src, const char *dest) { - int err; - - err = rename(src, dest); - - if (err && errno == EXDEV) { - err = file_copy(src, dest); - unlink(src); - } else if (err) { - fprintf(stderr, "%s: ERROR: failed to rename %s to %s: %s\n", - __FUNCTION__, src, dest, strerror(errno)); - } + int err; + + err = rename(src, dest); + if (err == -1) { + if (errno == EXDEV) { + /* src & dest live on different file systems */ + err = file_copy(src, dest); + if (err == 0) + unlink(src); + } else { + opkg_perror(ERROR, "Failed to rename %s to %s", + src, dest); + } + } - return err; + return err; } -/* I put these here to keep libbb dependencies from creeping all over - the opkg code */ int file_copy(const char *src, const char *dest) { - int err; + int err; - err = copy_file(src, dest, FILEUTILS_FORCE | FILEUTILS_PRESERVE_STATUS); - if (err) { - fprintf(stderr, "%s: ERROR: failed to copy %s to %s\n", - __FUNCTION__, src, dest); - } + err = copy_file(src, dest, FILEUTILS_FORCE | FILEUTILS_PRESERVE_STATUS); + if (err) + opkg_msg(ERROR, "Failed to copy file %s to %s.\n", src, dest); - return err; + return err; } int file_mkdir_hier(const char *path, long mode) { - return make_directory(path, mode, FILEUTILS_RECUR); + return make_directory(path, mode, FILEUTILS_RECUR); } +#ifdef HAVE_MD5 char *file_md5sum_alloc(const char *file_name) { - static const int md5sum_bin_len = 16; - static const int md5sum_hex_len = 32; - - static const unsigned char bin2hex[16] = { - '0', '1', '2', '3', - '4', '5', '6', '7', - '8', '9', 'a', 'b', - 'c', 'd', 'e', 'f' - }; - - int i, err; - FILE *file; - char *md5sum_hex; - unsigned char md5sum_bin[md5sum_bin_len]; - - md5sum_hex = malloc(md5sum_hex_len + 1); - if (md5sum_hex == NULL) { - fprintf(stderr, "%s: out of memory\n", __FUNCTION__); - return strdup(""); - } - - file = fopen(file_name, "r"); - if (file == NULL) { - fprintf(stderr, "%s: Failed to open file %s: %s\n", - __FUNCTION__, file_name, strerror(errno)); - return strdup(""); - } - - err = md5_stream(file, md5sum_bin); - if (err) { - fprintf(stderr, "%s: ERROR computing md5sum for %s: %s\n", - __FUNCTION__, file_name, strerror(err)); - return strdup(""); - } - - fclose(file); - - for (i=0; i < md5sum_bin_len; i++) { - md5sum_hex[i*2] = bin2hex[md5sum_bin[i] >> 4]; - md5sum_hex[i*2+1] = bin2hex[md5sum_bin[i] & 0xf]; - } - - md5sum_hex[md5sum_hex_len] = '\0'; - - return md5sum_hex; + static const int md5sum_bin_len = 16; + static const int md5sum_hex_len = 32; + + static const unsigned char bin2hex[16] = { + '0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f' + }; + + int i, err; + FILE *file; + char *md5sum_hex; + unsigned char md5sum_bin[md5sum_bin_len]; + + md5sum_hex = xcalloc(1, md5sum_hex_len + 1); + + file = fopen(file_name, "r"); + if (file == NULL) { + opkg_perror(ERROR, "Failed to open file %s", file_name); + free(md5sum_hex); + return NULL; + } + + err = md5_stream(file, md5sum_bin); + if (err) { + opkg_msg(ERROR, "Could't compute md5sum for %s.\n", file_name); + fclose(file); + free(md5sum_hex); + return NULL; + } + + fclose(file); + + for (i = 0; i < md5sum_bin_len; i++) { + md5sum_hex[i * 2] = bin2hex[md5sum_bin[i] >> 4]; + md5sum_hex[i * 2 + 1] = bin2hex[md5sum_bin[i] & 0xf]; + } + + md5sum_hex[md5sum_hex_len] = '\0'; + + return md5sum_hex; +} +#endif + +#ifdef HAVE_SHA256 +char *file_sha256sum_alloc(const char *file_name) +{ + static const int sha256sum_bin_len = 32; + static const int sha256sum_hex_len = 64; + + static const unsigned char bin2hex[16] = { + '0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f' + }; + + int i, err; + FILE *file; + char *sha256sum_hex; + unsigned char sha256sum_bin[sha256sum_bin_len]; + + sha256sum_hex = xcalloc(1, sha256sum_hex_len + 1); + + file = fopen(file_name, "r"); + if (file == NULL) { + opkg_perror(ERROR, "Failed to open file %s", file_name); + free(sha256sum_hex); + return NULL; + } + + err = sha256_stream(file, sha256sum_bin); + if (err) { + opkg_msg(ERROR, "Could't compute sha256sum for %s.\n", + file_name); + fclose(file); + free(sha256sum_hex); + return NULL; + } + + fclose(file); + + for (i = 0; i < sha256sum_bin_len; i++) { + sha256sum_hex[i * 2] = bin2hex[sha256sum_bin[i] >> 4]; + sha256sum_hex[i * 2 + 1] = bin2hex[sha256sum_bin[i] & 0xf]; + } + + sha256sum_hex[sha256sum_hex_len] = '\0'; + + return sha256sum_hex; } +#endif + +char *checksum_bin2hex(const char *src, size_t len) +{ + unsigned char *p; + static unsigned char buf[65]; + const unsigned char *s = (unsigned char *)src; + static const unsigned char bin2hex[16] = { + '0', '1', '2', '3', + '4', '5', '6', '7', + '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f' + }; + + if (len > 32) + return NULL; + + for (p = buf; len > 0; s++, len--) { + *p++ = bin2hex[*s / 16]; + *p++ = bin2hex[*s % 16]; + } + + *p = 0; + + return (char *)buf; +} + +char *checksum_hex2bin(const char *src, size_t *len) +{ + size_t slen; + unsigned char *p; + const unsigned char *s = (unsigned char *)src; + static unsigned char buf[32]; + + while (isspace(*src)) + src++; + + slen = strlen(src); + + if (slen > 64) { + *len = 0; + return NULL; + } + +#define hex(c) \ + (c >= 'a' ? (c - 'a') : (c >= 'A' ? (c - 'A') : (c - '0'))) + + for (p = buf, *len = 0; + slen > 0 && isxdigit(s[0]) && isxdigit(s[1]); + slen--, s += 2, (*len)++) + *p++ = hex(s[0]) * 16 + hex(s[1]); + + return (char *)buf; +} + +int rm_r(const char *path) +{ + int ret = 0; + DIR *dir; + struct dirent *dent; + + if (path == NULL) { + opkg_perror(ERROR, "Missing directory parameter"); + return -1; + } + + dir = opendir(path); + if (dir == NULL) { + opkg_perror(ERROR, "Failed to open dir %s", path); + return -1; + } + + if (fchdir(dirfd(dir)) == -1) { + opkg_perror(ERROR, "Failed to change to dir %s", path); + closedir(dir); + return -1; + } + + while (1) { + errno = 0; + if ((dent = readdir(dir)) == NULL) { + if (errno) { + opkg_perror(ERROR, "Failed to read dir %s", + path); + ret = -1; + } + break; + } + + if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) + continue; + +#ifdef _BSD_SOURCE + if (dent->d_type == DT_DIR) { + if ((ret = rm_r(dent->d_name)) == -1) + break; + continue; + } else if (dent->d_type == DT_UNKNOWN) +#endif + { + struct stat st; + if ((ret = lstat(dent->d_name, &st)) == -1) { + opkg_perror(ERROR, "Failed to lstat %s", + dent->d_name); + break; + } + if (S_ISDIR(st.st_mode)) { + if ((ret = rm_r(dent->d_name)) == -1) + break; + continue; + } + } + + if ((ret = unlink(dent->d_name)) == -1) { + opkg_perror(ERROR, "Failed to unlink %s", dent->d_name); + break; + } + } + + if (chdir("..") == -1) { + ret = -1; + opkg_perror(ERROR, "Failed to change to dir %s/..", path); + } + + if (rmdir(path) == -1) { + ret = -1; + opkg_perror(ERROR, "Failed to remove dir %s", path); + } + + if (closedir(dir) == -1) { + ret = -1; + opkg_perror(ERROR, "Failed to close dir %s", path); + } + + return ret; +}