From f8892b9d087f5c60de663d107643085deaba727b Mon Sep 17 00:00:00 2001 From: Dave Reisner Date: Wed, 15 Feb 2012 00:02:40 -0500 Subject: util: reduce pointer hell in _alpm_makepath_mode Simplify the implementation: - allocate and manipulate a copy of the passed in path rather than building out a path as the while loop progresses - use simple pointer arithmetic to skip uninteresting cases - use mkdir(3)'s return value and errno to detect failure Signed-off-by: Dave Reisner Signed-off-by: Dan McGee --- lib/libalpm/util.c | 55 +++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c index 59861242..34f817e1 100644 --- a/lib/libalpm/util.c +++ b/lib/libalpm/util.c @@ -101,36 +101,41 @@ int _alpm_makepath(const char *path) */ int _alpm_makepath_mode(const char *path, mode_t mode) { - /* A bit of pointer hell here. Descriptions: - * orig - a copy of path so we can safely butcher it with strsep - * str - the current position in the path string (after the delimiter) - * ptr - the original position of str after calling strsep - * incr - incrementally generated path for use in stat/mkdir call - */ - char *orig, *str, *ptr, *incr; - mode_t oldmask = umask(0000); + char *ptr, *str; + mode_t oldmask; int ret = 0; - orig = strdup(path); - incr = calloc(strlen(orig) + 1, sizeof(char)); - str = orig; - while((ptr = strsep(&str, "/"))) { - if(strlen(ptr)) { - /* we have another path component- append the newest component to - * existing string and create one more level of dir structure */ - strcat(incr, "/"); - strcat(incr, ptr); - if(access(incr, F_OK)) { - if(mkdir(incr, mode)) { - ret = 1; - break; - } - } + STRDUP(str, path, return 1); + + oldmask = umask(0000); + + for(ptr = str; *ptr; ptr++) { + /* detect mid-path condition and zero length paths */ + if(*ptr != '/' || ptr == str || ptr[-1] == '/') { + continue; } + + /* temporarily mask the end of the path */ + *ptr = '\0'; + + if(mkdir(str, 0755) < 0 && errno != EEXIST) { + ret = 1; + goto done; + } + + /* restore path separator */ + *ptr = '/'; } - free(orig); - free(incr); + + /* end of the string. add the full path. It will already exist when the path + * passed in has a trailing slash. */ + if(mkdir(str, 0755) < 0 && errno != EEXIST) { + ret = 1; + } + +done: umask(oldmask); + free(str); return ret; } -- cgit v1.2.3-24-g4f1b