Lucas De Marchi
2013-07-15 05:12:54 UTC
From: Lucas De Marchi <lucas.demarchi-***@public.gmane.org>
- Fix infinite loop when path is relative
- Fix not considering EEXIST as a success
- General refactor to mkdir_p so it never calls mkdir for an existing
dir (given no creates it from outside)
---
testsuite/mkdir.c | 54 +++++++++++++++++++++++++++++++++++-------------------
1 file changed, 35 insertions(+), 19 deletions(-)
diff --git a/testsuite/mkdir.c b/testsuite/mkdir.c
index 0a7de69..be2e37b 100644
--- a/testsuite/mkdir.c
+++ b/testsuite/mkdir.c
@@ -23,47 +23,63 @@
#include "mkdir.h"
#include "testsuite.h"
+static inline int is_dir(const char *path)
+{
+ struct stat st;
+
+ if (stat(path, &st) >= 0) {
+ if (S_ISDIR(st.st_mode))
+ return 1;
+ return 0;
+ }
+
+ 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;
- Fix infinite loop when path is relative
- Fix not considering EEXIST as a success
- General refactor to mkdir_p so it never calls mkdir for an existing
dir (given no creates it from outside)
---
testsuite/mkdir.c | 54 +++++++++++++++++++++++++++++++++++-------------------
1 file changed, 35 insertions(+), 19 deletions(-)
diff --git a/testsuite/mkdir.c b/testsuite/mkdir.c
index 0a7de69..be2e37b 100644
--- a/testsuite/mkdir.c
+++ b/testsuite/mkdir.c
@@ -23,47 +23,63 @@
#include "mkdir.h"
#include "testsuite.h"
+static inline int is_dir(const char *path)
+{
+ struct stat st;
+
+ if (stat(path, &st) >= 0) {
+ if (S_ISDIR(st.st_mode))
+ return 1;
+ return 0;
+ }
+
+ 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;
--
1.8.3.2
1.8.3.2