summaryrefslogtreecommitdiffstats
path: root/lib/libalpm/util.c
diff options
context:
space:
mode:
authorDave Reisner <dreisner@archlinux.org>2012-02-15 06:02:40 +0100
committerDan McGee <dan@archlinux.org>2012-02-20 23:52:48 +0100
commitf8892b9d087f5c60de663d107643085deaba727b (patch)
tree92e62c11950ae98b2aca21ed9da8efd65fcde7c8 /lib/libalpm/util.c
parent31d95b867919b02774f4a98b25d2f997c2985600 (diff)
downloadpacman-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/libalpm/util.c')
-rw-r--r--lib/libalpm/util.c55
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;
}