- umask(orig_umask);
- p = fname;
- while ((p = strchr(p,'/')) != NULL) {
- *p = '\0';
- if (do_mkdir(fname, ACCESSPERMS) < 0 && errno != EEXIST)
- ret = -1;
- *p++ = '/';
+ if (flags & MKP_DROP_NAME) {
+ end = strrchr(fname, '/');
+ if (!end)
+ return 0;
+ *end = '\0';
+ } else
+ end = fname + strlen(fname);
+
+ umask(orig_umask); /* NOTE: don't return before setting this back to 0! */
+
+ /* Try to find an existing dir, starting from the deepest dir. */
+ for (p = end; ; ) {
+ if (do_mkdir(fname, ACCESSPERMS) == 0) {
+ ret++;
+ break;
+ }
+ if (errno != ENOENT) {
+ if (errno != EEXIST)
+ ret = -ret - 1;
+ break;
+ }
+ while (1) {
+ if (p == fname) {
+ ret = -ret - 1;
+ goto double_break;
+ }
+ if (*--p == '/') {
+ if (p == fname) {
+ ret = -ret - 1; /* impossible... */
+ goto double_break;
+ }
+ *p = '\0';
+ break;
+ }
+ }
+ }
+ double_break:
+
+ /* Make all the dirs that we didn't find on the way here. */
+ while (p != end) {
+ *p = '/';
+ p += strlen(p);
+ if (ret < 0) /* Skip mkdir on error, but keep restoring the path. */
+ continue;
+ if (do_mkdir(fname, ACCESSPERMS) < 0)
+ ret = -ret - 1;
+ else
+ ret++;