replaced strndupcat with path_append, added LinkTable_disk_*() functions

This commit is contained in:
Fufu Fang 2019-04-26 07:39:45 +01:00
parent 825bd4d3fb
commit 9a5f37d91f
7 changed files with 171 additions and 97 deletions

View File

@ -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 */

View File

@ -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);

View File

@ -1,12 +1,9 @@
#ifndef LINK_H
#define LINK_H
#include <curl/curl.h>
#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 <curl/curl.h>
/** \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

View File

@ -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 */

View File

@ -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

View File

@ -4,29 +4,27 @@
#include <stdlib.h>
#include <string.h>
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)

View File

@ -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