diff options
author | Dave Reisner <dreisner@archlinux.org> | 2012-02-15 06:02:40 +0100 |
---|---|---|
committer | Dan McGee <dan@archlinux.org> | 2012-02-20 23:52:48 +0100 |
commit | f8892b9d087f5c60de663d107643085deaba727b (patch) | |
tree | 92e62c11950ae98b2aca21ed9da8efd65fcde7c8 /lib | |
parent | 31d95b867919b02774f4a98b25d2f997c2985600 (diff) | |
download | pacman-f8892b9d087f5c60de663d107643085deaba727b.tar.gz pacman-f8892b9d087f5c60de663d107643085deaba727b.tar.xz |
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 <dreisner@archlinux.org>
Signed-off-by: Dan McGee <dan@archlinux.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libalpm/util.c | 55 |
1 files 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; } |