static bool create_path(char const* path_in, int permissions, tr_error** error)
{
- char* p;
- char* pp;
- bool done;
- int tmperr;
- int rv;
- struct stat sb;
- char* path;
-
/* make a temporary copy of path */
- path = tr_strdup(path_in);
+ char* path = tr_strdup(path_in);
/* walk past the root */
- p = path;
+ char* p = path;
while (*p == TR_PATH_DELIMITER)
{
++p;
}
- pp = p;
- done = false;
+ char* path_end = p + strlen(p);
+
+ while (path_end > path && *path_end == TR_PATH_DELIMITER)
+ {
+ --path_end;
+ }
+
+ char* pp;
+ bool up_walk_ok = false;
- while ((p = strchr(pp, TR_PATH_DELIMITER)) || (p = strchr(pp, '\0')))
+ /* Go one level up on each iteration and attempt to create */
+ for (pp = path_end; pp != NULL; pp = strrchr(p, TR_PATH_DELIMITER))
{
- if (!*p)
+ *pp = '\0';
+
+ if (mkdir(path, permissions) != -1)
{
- done = true;
+ up_walk_ok = true;
+ break;
}
- else
+
+ if (errno == EEXIST)
{
- *p = '\0';
+ break;
}
- tmperr = errno;
- rv = stat(path, &sb);
- errno = tmperr;
-
- if (rv)
+ if (errno != ENOENT)
{
- tr_error* my_error = NULL;
-
- /* Folder doesn't exist yet */
- if (!tr_sys_dir_create(path, 0, permissions, &my_error))
- {
- tr_logAddError(_("Couldn't create \"%1$s\": %2$s"), path, my_error->message);
- tr_free(path);
- tr_error_propagate(error, &my_error);
- return false;
- }
+ goto unable_to_create;
}
- else if ((sb.st_mode & S_IFMT) != S_IFDIR)
+ }
+
+ if (up_walk_ok && pp == path_end)
+ {
+ goto success;
+ }
+
+ /* Go one level down on each iteration and attempt to create */
+ for (; pp < path_end; pp += strlen(pp))
+ {
+ *pp = TR_PATH_DELIMITER;
+
+ if (mkdir(path, permissions) != -1)
{
- /* Node exists but isn't a folder */
- char* const buf = tr_strdup_printf(_("File \"%s\" is in the way"), path);
- tr_logAddError(_("Couldn't create \"%1$s\": %2$s"), path_in, buf);
- tr_free(buf);
- tr_free(path);
- set_system_error(error, ENOTDIR);
- return false;
+ continue;
}
- if (done)
+ if (errno != EEXIST)
{
- break;
+ goto unable_to_create;
}
+ }
+
+ struct stat sb;
+
+ if (stat(path, &sb) == -1)
+ {
+ goto unable_to_create;
+ }
- *p = TR_PATH_DELIMITER;
- p++;
- pp = p;
+ if ((sb.st_mode & S_IFMT) != S_IFDIR)
+ {
+ goto not_a_directory;
}
+success:
+
tr_free(path);
return true;
+
+not_a_directory:
+
+ {
+ char* const buf = tr_strdup_printf(_("File \"%s\" is in the way"), path);
+
+ tr_logAddError(_("Couldn't create \"%1$s\": %2$s"), path_in, buf);
+ set_system_error(error, ENOTDIR);
+
+ tr_free(buf);
+ goto fail;
+ }
+
+unable_to_create:
+
+ {
+ tr_error* my_error = NULL;
+ set_system_error(&my_error, errno);
+
+ tr_logAddError(_("Couldn't create \"%1$s\": %2$s"), path, my_error->message);
+ tr_error_propagate(error, &my_error);
+
+ goto fail;
+ }
+
+fail:
+
+ tr_free(path);
+ return false;
}
#endif