diff --git a/src/vio/csync_vio.c b/src/vio/csync_vio.c index 552f4c7df5..f9b2b7d4ff 100644 --- a/src/vio/csync_vio.c +++ b/src/vio/csync_vio.c @@ -339,6 +339,63 @@ int csync_vio_mkdir(CSYNC *ctx, const char *uri, mode_t mode) { return rc; } +int csync_vio_mkdirs(CSYNC *ctx, const char *uri, mode_t mode) { + int tmp; + csync_vio_file_stat_t *st; + + if (uri == NULL) { + errno = EINVAL; + return -1; + } + + st = csync_vio_file_stat_new(); + if (st == NULL) { + return -1; + } + + if (csync_vio_stat(ctx, uri, st) == 0) { + if (! S_ISDIR(st->mode)) { + errno = ENOTDIR; + return -1; + } + } + csync_vio_file_stat_destroy(st); + + tmp = strlen(uri); + while(tmp > 0 && uri[tmp - 1] == '/') --tmp; + while(tmp > 0 && uri[tmp - 1] != '/') --tmp; + while(tmp > 0 && uri[tmp - 1] == '/') --tmp; + + if (tmp > 0) { + char suburi[tmp + 1]; + memcpy(suburi, uri, tmp); + suburi[tmp] = '\0'; + + st = csync_vio_file_stat_new(); + if (csync_vio_stat(ctx, suburi, st) == 0) { + if (! S_ISDIR(st->mode)) { + csync_vio_file_stat_destroy(st); + errno = ENOTDIR; + return -1; + } + } else if (errno != ENOENT) { + csync_vio_file_stat_destroy(st); + return -1; + } else if (csync_vio_mkdirs(ctx, suburi, mode) < 0) { + csync_vio_file_stat_destroy(st); + return -1; + } + csync_vio_file_stat_destroy(st); + } + + tmp = csync_vio_mkdir(ctx, uri, mode); + if (errno == EEXIST) { + return 0; + } + + return tmp; +} + int csync_vio_rmdir(CSYNC *ctx, const char *uri) { int rc = -1; diff --git a/src/vio/csync_vio.h b/src/vio/csync_vio.h index 7fe5cc8870..e5705a6a27 100644 --- a/src/vio/csync_vio.h +++ b/src/vio/csync_vio.h @@ -45,6 +45,7 @@ int csync_vio_closedir(CSYNC *ctx, csync_vio_handle_t *dhandle); csync_vio_file_stat_t *csync_vio_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle); int csync_vio_mkdir(CSYNC *ctx, const char *uri, mode_t mode); +int csync_vio_mkdirs(CSYNC *ctx, const char *uri, mode_t mode); int csync_vio_rmdir(CSYNC *ctx, const char *uri); int csync_vio_stat(CSYNC *ctx, const char *uri, csync_vio_file_stat_t *buf);