From 9a5f37d91fd4c9f37608d9151b96e156c5a07efa Mon Sep 17 00:00:00 2001 From: Fufu Fang Date: Fri, 26 Apr 2019 07:39:45 +0100 Subject: [PATCH] replaced strndupcat with path_append, added LinkTable_disk_*() functions --- src/cache.c | 44 ++++++---------- src/link.c | 142 ++++++++++++++++++++++++++++++++++++++------------ src/link.h | 19 ++++--- src/main.c | 4 +- src/network.c | 2 +- src/util.c | 36 ++++++------- src/util.h | 21 +++++--- 7 files changed, 171 insertions(+), 97 deletions(-) diff --git a/src/cache.c b/src/cache.c index afc4254..e6d87bf 100644 --- a/src/cache.c +++ b/src/cache.c @@ -27,12 +27,6 @@ */ #define MAX_SEGBC 1073741824 -/** - * \brief the maximum length of a path - * \details This corresponds the maximum path length under Ext4. - */ -#define MAX_PATH_LEN 4096 - /** * \brief error associated with metadata */ @@ -77,11 +71,11 @@ void CacheSystem_init(const char *path) /* Handle the case of missing '/' */ if (path[strnlen(path, MAX_PATH_LEN) - 1] == '/') { - META_DIR = strndupcat(path, "meta/", MAX_PATH_LEN); - DATA_DIR = strndupcat(path, "data/", MAX_PATH_LEN); + META_DIR = path_append(path, "meta/"); + DATA_DIR = path_append(path, "data/"); } else { - META_DIR = strndupcat(path, "/meta/", MAX_PATH_LEN); - DATA_DIR = strndupcat(path, "/data/", MAX_PATH_LEN); + META_DIR = path_append(path, "/meta/"); + DATA_DIR = path_append(path, "/data/"); } /* Check if directories exist, if not, create them */ @@ -235,7 +229,7 @@ static int Data_create(Cache *cf) int mode; mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - char *datafn = strndupcat(DATA_DIR, cf->path, MAX_PATH_LEN); + char *datafn = path_append(DATA_DIR, cf->path); fd = open(datafn, O_WRONLY | O_CREAT, mode); free(datafn); if (fd == -1) { @@ -256,7 +250,7 @@ static int Data_create(Cache *cf) */ static long Data_size(const char *fn) { - char *datafn = strndupcat(DATA_DIR, fn, MAX_PATH_LEN); + char *datafn = path_append(DATA_DIR, fn); struct stat st; int s = stat(datafn, &st); free(datafn); @@ -341,11 +335,6 @@ static long Data_write(Cache *cf, const uint8_t *buf, off_t len, fprintf(stderr, "Data_write(): fwrite(): requested %ld, returned %ld!\n", len, byte_written); - if (feof(cf->dfp)) { - /* reached EOF */ - fprintf(stderr, - "Data_write(): fwrite(): reached the end of the file!\n"); - } if (ferror(cf->dfp)) { /* filesystem error */ fprintf(stderr, @@ -358,8 +347,8 @@ static long Data_write(Cache *cf, const uint8_t *buf, off_t len, int CacheDir_create(const char *dirn) { - char *metadirn = strndupcat(META_DIR, dirn, MAX_PATH_LEN); - char *datadirn = strndupcat(DATA_DIR, dirn, MAX_PATH_LEN); + char *metadirn = path_append(META_DIR, dirn); + char *datadirn = path_append(DATA_DIR, dirn); int i; i = -mkdir(metadirn, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); @@ -461,8 +450,8 @@ static int Cache_exist(const char *fn) { int meta_exists = 1; int data_exists = 1; - char *metafn = strndupcat(META_DIR, fn, MAX_PATH_LEN); - char *datafn = strndupcat(DATA_DIR, fn, MAX_PATH_LEN); + char *metafn = path_append(META_DIR, fn); + char *datafn = path_append(DATA_DIR, fn); if (access(metafn, F_OK)) { // fprintf(stderr, "Cache_exist(): access(): %s\n", strerror(errno)); @@ -501,8 +490,8 @@ static int Cache_exist(const char *fn) void Cache_delete(const char *fn) { // fprintf(stderr, "Cache_delete(): deleting %s\n", fn); - char *metafn = strndupcat(META_DIR, fn, MAX_PATH_LEN); - char *datafn = strndupcat(DATA_DIR, fn, MAX_PATH_LEN); + char *metafn = path_append(META_DIR, fn); + char *datafn = path_append(DATA_DIR, fn); if (!access(metafn, F_OK)) { if(unlink(metafn)) { fprintf(stderr, "Cache_delete(): unlink(): %s\n", @@ -528,12 +517,13 @@ void Cache_delete(const char *fn) */ static int Data_open(Cache *cf) { - char *datafn = strndupcat(DATA_DIR, cf->path, MAX_PATH_LEN); + char *datafn = path_append(DATA_DIR, cf->path); cf->dfp = fopen(datafn, "r+"); free(datafn); if (!cf->dfp) { /* Failed to open the data file */ - fprintf(stderr, "Data_open(): fopen(): %s\n", strerror(errno)); + fprintf(stderr, "Data_open(): fopen(%s): %s\n", datafn, + strerror(errno)); return -1; } return 0; @@ -547,7 +537,7 @@ static int Data_open(Cache *cf) */ static int Meta_open(Cache *cf) { - char *metafn = strndupcat(META_DIR, cf->path, MAX_PATH_LEN); + char *metafn = path_append(META_DIR, cf->path); cf->mfp = fopen(metafn, "r+"); if (!cf->mfp) { /* Failed to open the data file */ @@ -568,7 +558,7 @@ static int Meta_open(Cache *cf) */ static int Meta_create(Cache *cf) { - char *metafn = strndupcat(META_DIR, cf->path, MAX_PATH_LEN); + char *metafn = path_append(META_DIR, cf->path); cf->mfp = fopen(metafn, "w"); if (!cf->mfp) { /* Failed to open the data file */ diff --git a/src/link.c b/src/link.c index d8b1853..86f8d5c 100644 --- a/src/link.c +++ b/src/link.c @@ -37,11 +37,11 @@ static Link *Link_new(const char *linkname, LinkType type) fprintf(stderr, "Link_new(): calloc failure!\n"); exit(EXIT_FAILURE); } - strncpy(link->linkname, linkname, LINKNAME_LEN_MAX); + strncpy(link->linkname, linkname, MAX_FILENAME_LEN); link->type = type; /* remove the '/' from linkname if it exists */ - char *c = &(link->linkname[strnlen(link->linkname, LINKNAME_LEN_MAX) - 1]); + char *c = &(link->linkname[strnlen(link->linkname, MAX_FILENAME_LEN) - 1]); if ( *c == '/') { *c = '\0'; } @@ -61,7 +61,7 @@ static LinkType linkname_type(const char *linkname) return LINK_INVALID; } - if ( linkname[strnlen(linkname, LINKNAME_LEN_MAX) - 1] == '/' ) { + if ( linkname[strnlen(linkname, MAX_FILENAME_LEN) - 1] == '/' ) { return LINK_DIR; } @@ -185,29 +185,6 @@ void Link_set_stat(Link* this_link, CURL *curl) } } -static char *url_append(const char *url, const char *sublink) -{ - int needs_separator = 0; - if (url[strnlen(url, URL_LEN_MAX)-1] != '/') { - needs_separator = 1; - } - - char *str; - size_t ul = strnlen(url, URL_LEN_MAX); - size_t sl = strnlen(sublink, LINKNAME_LEN_MAX); - str = calloc(ul + sl + needs_separator + 1, sizeof(char)); - if (!str) { - fprintf(stderr, "url_append(): calloc failure!\n"); - exit(EXIT_FAILURE); - } - strncpy(str, url, ul); - if (needs_separator) { - str[ul] = '/'; - } - strncat(str, sublink, sl); - return str; -} - static void LinkTable_fill(LinkTable *linktbl) { Link *head_link = linktbl->links[0]; @@ -215,14 +192,14 @@ static void LinkTable_fill(LinkTable *linktbl) Link *this_link = linktbl->links[i]; if (this_link->type) { char *url; - url = url_append(head_link->f_url, this_link->linkname); - strncpy(this_link->f_url, url, URL_LEN_MAX); + url = path_append(head_link->f_url, this_link->linkname); + strncpy(this_link->f_url, url, MAX_PATH_LEN); free(url); char *unescaped_linkname; unescaped_linkname = curl_easy_unescape(NULL, this_link->linkname, 0, NULL); - strncpy(this_link->linkname, unescaped_linkname, LINKNAME_LEN_MAX); + strncpy(this_link->linkname, unescaped_linkname, MAX_FILENAME_LEN); curl_free(unescaped_linkname); if (this_link->type == LINK_FILE && !(this_link->content_length)) { @@ -281,7 +258,7 @@ LinkTable *LinkTable_new(const char *url) LinkTable_add(linktbl, Link_new("/", LINK_HEAD)); Link *head_link = linktbl->links[0]; head_link->type = LINK_HEAD; - strncpy(head_link->f_url, url, URL_LEN_MAX); + strncpy(head_link->f_url, url, MAX_PATH_LEN); /* start downloading the base URL */ CURL *curl = Link_to_curl(head_link); @@ -327,6 +304,103 @@ URL: %s, HTTP %ld\n", url, http_resp); return linktbl; } +static void LinkTable_disk_delete(const char *dirn) +{ + char *path = path_append(dirn, ".LinkTable"); + if(unlink(path)) { + fprintf(stderr, "LinkTable_delete(): unlink(): %s\n", + strerror(errno)); + } + free(path); +} + +int LinkTable_disk_save(LinkTable *linktbl, const char *dirn) +{ + char *path = path_append(dirn, ".LinkTable"); + FILE *fp = fopen(path, "w"); + free(path); + + if (!fp) { + fprintf(stderr, "LinkTable_save(): fopen(): %s\n", strerror(errno)); + return -1; + } + + fwrite(&linktbl->num, sizeof(int), 1, fp); + for (int i = 0; i < linktbl->num; i++) { + fwrite(linktbl->links[i]->linkname, sizeof(char), MAX_FILENAME_LEN, fp); + fwrite(linktbl->links[i]->f_url, sizeof(char), MAX_PATH_LEN, fp); + fwrite(&linktbl->links[i]->type, sizeof(LinkType), 1, fp); + fwrite(&linktbl->links[i]->content_length, sizeof(size_t), 1, fp); + fwrite(&linktbl->links[i]->time, sizeof(long), 1, fp); + } + + int res = 0; + + if (ferror(fp)) { + fprintf(stderr, "LinkTable_save(): encountered ferror!\n"); + res = -1; + } + + if (fclose(fp)) { + fprintf(stderr, "LinkTable_save(): cannot close the file pointer, %s\n", + strerror(errno)); + res = -1; + } + + return res; +} + +LinkTable *LinkTable_disk_open(const char *dirn) +{ + char *path = path_append(dirn, ".LinkTable"); + FILE *fp = fopen(path, "r"); + free(path); + + if (!fp) { + fprintf(stderr, "LinkTable_save(): fopen(): %s\n", strerror(errno)); + return NULL; + } + + LinkTable *linktbl = calloc(1, sizeof(LinkTable)); + if (!linktbl) { + fprintf(stderr, "LinkTable_open(): calloc linktbl failed!\n"); + return NULL; + } + + fread(&linktbl->num, sizeof(int), 1, fp); + linktbl->links = calloc(linktbl->num, sizeof(Link *)); + for (int i = 0; i < linktbl->num; i++) { + linktbl->links[i] = calloc(1, sizeof(Link)); + if (linktbl->links[i]) { + fprintf(stderr, "LinkTable_open(): calloc links[i] failed!\n"); + } + fread(linktbl->links[i]->f_url, sizeof(char), MAX_PATH_LEN, fp); + fread(&linktbl->links[i]->type, sizeof(LinkType), 1, fp); + fread(&linktbl->links[i]->content_length, sizeof(size_t), 1, fp); + fread(&linktbl->links[i]->time, sizeof(long), 1, fp); + if (feof(fp)) { + /* reached EOF */ + fprintf(stderr, + "LinkTable_open(): reached EOF!\n"); + LinkTable_free(linktbl); + LinkTable_disk_delete(dirn); + return NULL; + } + if (ferror(fp)) { + fprintf(stderr, "LinkTable_open(): encountered ferror!\n"); + LinkTable_free(linktbl); + LinkTable_disk_delete(dirn); + return NULL; + } + } + if (fclose(fp)) { + fprintf(stderr, "LinkTable_save(): cannot close the file pointer, %s\n", + strerror(errno)); + } + return linktbl; +} + + LinkTable *path_to_Link_LinkTable_new(const char *path) { Link *link = path_to_Link(path); @@ -344,7 +418,7 @@ static Link *path_to_Link_recursive(char *path, LinkTable *linktbl) } /* remove the last '/' if it exists */ - char *slash = &(path[strnlen(path, URL_LEN_MAX) - 1]); + char *slash = &(path[strnlen(path, MAX_PATH_LEN) - 1]); if (*slash == '/') { *slash = '\0'; } @@ -353,7 +427,7 @@ static Link *path_to_Link_recursive(char *path, LinkTable *linktbl) if ( slash == NULL ) { /* We cannot find another '/', we have reached the last level */ for (int i = 1; i < linktbl->num; i++) { - if (!strncmp(path, linktbl->links[i]->linkname, LINKNAME_LEN_MAX)) { + if (!strncmp(path, linktbl->links[i]->linkname, MAX_FILENAME_LEN)) { /* We found our link */ return linktbl->links[i]; } @@ -372,7 +446,7 @@ static Link *path_to_Link_recursive(char *path, LinkTable *linktbl) /* move the pointer past the '/' */ char *next_path = slash + 1; for (int i = 1; i < linktbl->num; i++) { - if (!strncmp(path, linktbl->links[i]->linkname, LINKNAME_LEN_MAX)) { + if (!strncmp(path, linktbl->links[i]->linkname, MAX_FILENAME_LEN)) { /* The next sub-directory exists */ if (!linktbl->links[i]->next_table) { linktbl->links[i]->next_table = LinkTable_new( @@ -388,7 +462,7 @@ static Link *path_to_Link_recursive(char *path, LinkTable *linktbl) Link *path_to_Link(const char *path) { - char *new_path = strndup(path, URL_LEN_MAX); + char *new_path = strndup(path, MAX_PATH_LEN); if (!new_path) { fprintf(stderr, "path_to_Link(): cannot allocate memory\n"); exit(EXIT_FAILURE); diff --git a/src/link.h b/src/link.h index 8029063..8a7b3fa 100644 --- a/src/link.h +++ b/src/link.h @@ -1,12 +1,9 @@ #ifndef LINK_H #define LINK_H -#include +#include "util.h" -/** \brief the maximum length of the URL */ -#define URL_LEN_MAX 2048 -/** \brief the maximum length of a partial URL (a link) */ -#define LINKNAME_LEN_MAX 255 +#include /** \brief the link type */ typedef enum { @@ -29,9 +26,9 @@ typedef struct Link Link; * \brief Link data structure */ struct Link { - char linkname[LINKNAME_LEN_MAX]; /**< The link name in the last level of + char linkname[MAX_FILENAME_LEN]; /**< The link name in the last level of the URL */ - char f_url[URL_LEN_MAX]; /**< The full URL of the file */ + char f_url[MAX_PATH_LEN]; /**< The full URL of the file */ LinkType type; /**< The type of the link */ size_t content_length; /**< CURLINFO_CONTENT_LENGTH_DOWNLOAD of the file */ LinkTable *next_table; /**< The next LinkTable level, if it is a LINK_DIR */ @@ -80,5 +77,13 @@ Link *path_to_Link(const char *path); */ LinkTable *path_to_Link_LinkTable_new(const char *path); +/** + * \brief dump a link table to the disk. + */ +int LinkTable_disk_save(LinkTable *linktbl, const char *dirn); +/** + * \brief load a link table from the disk. + */ +LinkTable *LinkTable_disk_open(const char *dirn); #endif diff --git a/src/main.c b/src/main.c index 137804f..5af3b47 100644 --- a/src/main.c +++ b/src/main.c @@ -98,7 +98,7 @@ void parse_config_file(char ***argv, int *argc) strncat(full_path, main_config_name, strlen(main_config_name)); /* The buffer has to be able to fit a URL */ - int buf_len = URL_LEN_MAX; + int buf_len = MAX_PATH_LEN; char buf[buf_len]; FILE *config = fopen(full_path, "r"); if (config) { @@ -178,7 +178,7 @@ parse_arg_list(int argc, char **argv, char ***fuse_argv, int *fuse_argc) NETWORK_CONFIG.password = strndup(optarg, ARG_LEN_MAX); break; case 'P': - NETWORK_CONFIG.proxy = strndup(optarg, URL_LEN_MAX); + NETWORK_CONFIG.proxy = strndup(optarg, MAX_PATH_LEN); break; case 'L': /* Long options */ diff --git a/src/network.c b/src/network.c index 4dcddec..cf47a60 100644 --- a/src/network.c +++ b/src/network.c @@ -263,7 +263,7 @@ LinkTable *network_init(const char *url) /* --------- Set the length of the root link ----------- */ /* This is where the '/' should be */ - ROOT_LINK_OFFSET = strnlen(url, URL_LEN_MAX) - 1; + ROOT_LINK_OFFSET = strnlen(url, MAX_PATH_LEN) - 1; if (url[ROOT_LINK_OFFSET] != '/') { /* * If '/' is not there, it is automatically added, so we need to skip 2 diff --git a/src/util.c b/src/util.c index 2622c87..cab72ef 100644 --- a/src/util.c +++ b/src/util.c @@ -4,29 +4,27 @@ #include #include -char *strndupcat(const char *a, const char *b, int n) +char *path_append(const char *path, const char *filename) { - int na = strnlen(a, n); - int nb = strnlen(b, n); - int nc = na + nb + 1; - if (nc > n) { - fprintf(stderr, - "strndupcat(): resulting string length exceeds maximum limit!\n"); - /* - * It is better to crash the program here, then corrupting the cache - * folder - */ + int needs_separator = 0; + if (path[strnlen(path, MAX_PATH_LEN)-1] != '/') { + needs_separator = 1; + } + + char *str; + size_t ul = strnlen(path, MAX_PATH_LEN); + size_t sl = strnlen(filename, MAX_FILENAME_LEN); + str = calloc(ul + sl + needs_separator + 1, sizeof(char)); + if (!str) { + fprintf(stderr, "path_append(): calloc failure!\n"); exit(EXIT_FAILURE); } - char *c = calloc(nc, sizeof(char)); - if (!c) { - fprintf(stderr, "strndupcat(): calloc failure!\n"); - exit(EXIT_FAILURE); + strncpy(str, path, ul); + if (needs_separator) { + str[ul] = '/'; } - strncpy(c, a, na); - strncat(c, b, nb); - c[nc-1] = '\0'; - return c; + strncat(str, filename, sl); + return str; } int64_t round_div(int64_t a, int64_t b) diff --git a/src/util.h b/src/util.h index 677b6fb..fec5b7a 100644 --- a/src/util.h +++ b/src/util.h @@ -9,18 +9,25 @@ */ /** - * \brief strndup with concatenation - * \details This function concatenate string a and string b together, and put - * the result in a new string. - * \param[in] a the first string - * \param[in] b the second string - * \param[in] n the maximum length of the output string + * \brief the maximum length of a path and a URL. + * \details This corresponds the maximum path length under Ext4. */ -char *strndupcat(const char *a, const char *b, int n); +#define MAX_PATH_LEN 4096 + +/** \brief the maximum length of a filename. */ +#define MAX_FILENAME_LEN 255 + +/** + * \brief append a path + * \details This function appends a path with the next level, while taking the + * trailing slash of the upper level into account. + */ +char *path_append(const char *path, const char *filename); /** * \brief division, but rounded to the nearest integer rather than truncating */ int64_t round_div(int64_t a, int64_t b); + #endif