diff options
author | fitz <fitz@13f79535-47bb-0310-9956-ffa450edef68> | 2002-05-31 22:28:40 +0000 |
---|---|---|
committer | fitz <fitz@13f79535-47bb-0310-9956-ffa450edef68> | 2002-05-31 22:28:40 +0000 |
commit | 0c13352488752674358fef333bc8751090f73039 (patch) | |
tree | 64f5112203ec102ae360b7a3690332596f72b257 /file_io | |
parent | eaddd65e35ace20184097e1988ecf4962e363793 (diff) | |
download | libapr-0c13352488752674358fef333bc8751090f73039.tar.gz |
Needed a function in Subversion to behave like 'mkdir -p', and this
seems like the logical place for it.
* file_io/unix/dir.c: apr_dir_make_recursive: New function.
(The following 2 are support for the above
function. Perhaps one day they'll live in a path
utilities file of their own?)
path_canonicalize: New static function.
path_remove_last_component: New static function.
* include/apr_file_io.h: apr_dir_make_recursive: New declaration.
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@63457 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'file_io')
-rw-r--r-- | file_io/unix/dir.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/file_io/unix/dir.c b/file_io/unix/dir.c index fe8003ed6..5f6779dab 100644 --- a/file_io/unix/dir.c +++ b/file_io/unix/dir.c @@ -73,6 +73,39 @@ static apr_status_t dir_cleanup(void *thedir) } } +#define PATH_SEPARATOR '/' + +/* Remove trailing separators that don't affect the meaning of PATH. */ +static const char *path_canonicalize (const char *path, apr_pool_t *pool) +{ + /* At some point this could eliminate redundant components. For + * now, it just makes sure there is no trailing slash. */ + apr_size_t len = strlen (path); + apr_size_t orig_len = len; + + while ((len > 0) && (path[len - 1] == PATH_SEPARATOR)) + len--; + + if (len != orig_len) + return apr_pstrndup (pool, path, len); + else + return path; +} + +/* Remove one component off the end of PATH. */ +static char *path_remove_last_component (const char *path, apr_pool_t *pool) +{ + const char *newpath = path_canonicalize (path, pool); + int i; + + for (i = (strlen(newpath) - 1); i >= 0; i--) { + if (path[i] == PATH_SEPARATOR) + break; + } + + return apr_pstrndup (pool, path, (i < 0) ? 0 : i); +} + apr_status_t apr_dir_open(apr_dir_t **new, const char *dirname, apr_pool_t *pool) { /* On some platforms (e.g., Linux+GNU libc), d_name[] in struct @@ -204,6 +237,29 @@ apr_status_t apr_dir_make(const char *path, apr_fileperms_t perm, apr_pool_t *po } } +apr_status_t apr_dir_make_recursive(const char *path, apr_fileperms_t perm, + apr_pool_t *pool) +{ + apr_status_t apr_err = 0; + + apr_err = apr_dir_make (path, perm, pool); /* Try to make PATH right out */ + + if (apr_err == EEXIST) /* It's OK if PATH exists */ + return APR_SUCCESS; + + if (apr_err == ENOENT) { /* Missing an intermediate dir */ + char *dir; + + dir = path_remove_last_component(path, pool); + apr_err = apr_dir_make_recursive(dir, perm, pool); + + if (!apr_err) + apr_err = apr_dir_make (path, perm, pool); + } + + return apr_err; +} + apr_status_t apr_dir_remove(const char *path, apr_pool_t *pool) { if (rmdir(path) == 0) { |