From 377ccdb9f2e2c13c371c78f4c1ca261908a656de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Fri, 15 Feb 2019 23:03:10 +0100 Subject: Fix pending fixes in calendar.c. --- calendar.c | 177 ++++++++++++++++++++++++++++--------------------------------- calendar.h | 33 ++++++++++++ 2 files changed, 114 insertions(+), 96 deletions(-) diff --git a/calendar.c b/calendar.c index de06276a..d0476583 100644 --- a/calendar.c +++ b/calendar.c @@ -1,136 +1,121 @@ #include "calendar.h" -/* - * These three are only for some FD hacks. - */ -#include #include -#include #include #include #include #include -#include -#include "macro.h" #include "parse.h" #include "err.h" -/* - * Returns 0 if file has no extersion - * - * TODO this looks from the first point, it should look from the last - * point. - */ -int get_extension(const char* filename, char* ext, ssize_t max_len) { - int ext_idx = -1; - ext[0] = '\0'; - for (char* c = (char*) filename; *c != '\0'; c++) { - if (*c == '.') { - ext_idx = 0; - continue; - } - if (ext_idx >= 0) { - ext[ext_idx++] = *c; - if (ext_idx == max_len) break; - } +int read_vcalendar(vcomponent* cal, char* path) { + + struct stat statbuf; + if (stat (path, &statbuf) != 0) { + fprintf(stderr, + "Error stating file or directory, errno = %i\npath = [%s]\n", + errno, path); + } + + int type = statbuf.st_mode & 0777000; + int chmod = statbuf.st_mode & 0777; + INFO_F("file has mode 0%o, with chmod = 0%o", type, chmod); + + switch (type) { + case S_IFREG: handle_file(cal, path); break; + case S_IFDIR: handle_dir (cal, path); break; + case S_IFLNK: + ERR("Found symlink, can't be bothered to check it further."); + break; + + default: ; } - ext[ext_idx] = '\0'; - return (ext_idx == -1) - ? 0 - : ext_idx; + + return 0; } -/* - * TODO merge the code for files and dirs. - */ +int handle_file(vcomponent* cal, char* path) { + INFO("Parsing a single file"); -int parse_dir(vcomponent* cal, char* path) { - DIR* dir = opendir(path); - struct dirent* d; - while ((d = readdir(dir)) != NULL) { + char* resolved_path = realpath(path, NULL); + open_ics (resolved_path, cal); + free (resolved_path); - /* Check that it's a regular file */ - if (d->d_type != DT_REG) continue; + return 0; +} - /* Check that we have an ICS file */ - char* fname = d->d_name; - char ext[10]; - int has_ext = get_extension(fname, ext, 9); - if (! has_ext || strcmp(ext, "ics") != 0) continue; +int handle_dir(vcomponent* cal, char* path) { + INFO("Parsing a directory"); + DIR* dir = opendir(path); - /* We now assume that it's a good file, and start parsing it */ + /* Buffer for holding search path and filename */ + char buf[PATH_MAX]; + strcpy(buf, path); + int path_len = strlen(path) + 1; - int fd = openat(dirfd(dir), fname, O_RDONLY); + /* Slash to guarantee we have at least one */ + buf[path_len - 1] = '/'; - FILE* f = fdopen(fd, "r"); - if (f == NULL) { - fprintf(stderr, "Error opening file [%s], errno = %i\n", - fname, errno); - exit (1); - } + struct dirent* d; + while ((d = readdir(dir)) != NULL) { + /* Check that it's a regular file */ + if (d->d_type != DT_REG) continue; - // TODO complete path - parse_file(fname, f, cal); + /* Append filename with currentt searchpath */ + strcat(buf, d->d_name); + char* resolved_path = realpath(buf, NULL); + /* Remove file part from combined path */ + buf[path_len] = '\0'; - fclose(f); + open_ics (resolved_path, cal); + + free (resolved_path); } closedir(dir); - return 0; } -int read_vcalendar(vcomponent* cal, char* path) { +int get_extension(const char* filename, char* ext, ssize_t max_len) { + int ext_idx = -1; + ext[0] = '\0'; + for (int i = 0; filename[i] != '\0'; i++) { + if (filename[i] == '.') ext_idx = i + 1; + if (filename[i] == '/') ext_idx = -1; + } - struct stat statbuf; - if (stat (path, &statbuf) != 0) { - fprintf(stderr, - "Error opening file or directory, errno = %i\npath = [%s]\n", - errno, path); + if (ext_idx == -1) return 0; + + int ext_len = 0; + for (int i = 0; i < max_len; i++, ext_len++) { + char c = filename[i + ext_idx]; + if (c == '\0') break; + ext[i] = c; } + ext[ext_len] = '\0'; + return ext_len; +} - int type = statbuf.st_mode & 0777000; - int chmod = statbuf.st_mode & 0777; - INFO_F("file has mode 0%o, with chmod = 0%o", type, chmod); +int check_ext (const char* path, const char* ext) { + char buf[10]; + int has_ext = get_extension(path, buf, 9); - switch (type) { - case S_IFREG: - INFO("Parsing a single file"); - - char ext[10]; - int has_ext = get_extension(path, ext, 9); - if (! has_ext || strcmp(ext, "ics") != 0) { - fprintf(stderr, "File doesn't have .ics extension. [%s]\n", ext); - exit(1); - } - - FILE* f = fopen(path, "r"); - if (f == NULL) { - fprintf(stderr, "Error opening file [%s], errno = %i\n", - path, errno); - exit (1); - } - - // TODO absolute path - parse_file(path, f, cal); - fclose(f); - break; + return has_ext && strcmp(buf, ext) == 0; +} - case S_IFDIR: - INFO("Parsing a directory"); - parse_dir (cal, path); - break; +int open_ics (char* resolved_path, vcomponent* cal) { + puts(resolved_path); + if (! check_ext(resolved_path, "ics") ) return 2; - case S_IFLNK: - ERR("Found symlink, can't be bothered to check it further."); - break; + FILE* f = fopen(resolved_path, "r"); - default: - ; - } + if (f == NULL) return 1; + parse_file(resolved_path, f, cal); + fclose(f); return 0; } + diff --git a/calendar.h b/calendar.h index c7484d05..20b78a9f 100644 --- a/calendar.h +++ b/calendar.h @@ -3,6 +3,39 @@ #include "vcal.h" +/* + * Reads all ics flies in path into the given vcomponent. The + * component is assumed to be a abstract ROOT element, whose first + * component will most likely become a VCALENDAR. + * + * path should either be a single .ics file (vcalendar), or a + * directory directly containing .ics files (vdir). + */ int read_vcalendar(vcomponent* cal, char* path); +/* + * Gets extension from filename. Writes output to ext. + * Assumes that the extension is the text between the last dot and + * the end of the string, and that no slashes can occur between the + * dot and the end. + * + * Returns the length of the extension, 0 if no extension. + */ +int get_extension(const char* filename, char* ext, ssize_t max_len); + +/* Returns 1 if path has extension ext, 0 otherwise */ +int check_ext (const char* path, const char* ext); + +/* Handle a lone ics file */ +int handle_file(vcomponent* cal, char* path); + +/* Handle a directory of ics files */ +int handle_dir(vcomponent* cal, char* path); + +/* + * Helper for opening a single ICS file. Handles file internally, and + * writes output to cal. + */ +int open_ics (char* resolved_path, vcomponent* cal); + #endif /* CALENDAR_H */ -- cgit v1.2.3