#include "mkdir.h"
#include "testsuite.h"
+static inline int is_dir(const char *path)
+{
+ struct stat st;
+
+ if (stat(path, &st) >= 0)
+ return S_ISDIR(st.st_mode);
+
+ return -errno;
+}
+
TS_EXPORT int mkdir_p(const char *path, mode_t mode)
{
char *start = strdupa(path);
int len = strlen(path);
char *end = start + len;
- struct stat st;
/*
* scan backwards, replacing '/' with '\0' while the component doesn't
* exist
*/
for (;;) {
- if (stat(start, &st) >= 0) {
- if (S_ISDIR(st.st_mode))
- break;
- return -ENOTDIR;
- }
+ int r = is_dir(start);
+ if (r > 0) {
+ end += strlen(end);
- /* Find the next component, backwards, discarding extra '/'*/
- for (; end != start && *end != '/'; end--)
- ;
+ if (end == start + len)
+ return 0;
- for (; end != start - 1 && *end == '/'; end--)
- ;
+ /* end != start, since it would be caught on the first
+ * iteration */
+ *end = '/';
+ break;
+ } else if (r == 0)
+ return -ENOTDIR;
- end++;
if (end == start)
break;
*end = '\0';
- }
- if (end == start + len)
- return 0;
+ /* Find the next component, backwards, discarding extra '/'*/
+ while (end > start && *end != '/')
+ end--;
- for (; end < start + len;) {
- *end = '/';
- end += strlen(end);
+ while (end > start && *(end - 1) == '/')
+ end--;
+ }
- if (mkdir(start, mode) < 0)
+ for (; end < start + len;) {
+ if (mkdir(start, mode) < 0 && errno != EEXIST)
return -errno;
+
+ end += strlen(end);
+ *end = '/';
}
return 0;