dir_make_recurse.c 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "fspr_file_io.h"
  17. #include "fspr_lib.h"
  18. #include "fspr_strings.h"
  19. #include <string.h>
  20. #define IS_SEP(c) (c == '/' || c == '\\')
  21. /* Remove trailing separators that don't affect the meaning of PATH. */
  22. static const char *path_canonicalize(const char *path, fspr_pool_t *pool)
  23. {
  24. /* At some point this could eliminate redundant components. For
  25. * now, it just makes sure there is no trailing slash. */
  26. fspr_size_t len = strlen(path);
  27. fspr_size_t orig_len = len;
  28. while ((len > 0) && IS_SEP(path[len - 1])) {
  29. len--;
  30. }
  31. if (len != orig_len) {
  32. return fspr_pstrndup(pool, path, len);
  33. }
  34. else {
  35. return path;
  36. }
  37. }
  38. /* Remove one component off the end of PATH. */
  39. static char *path_remove_last_component(const char *path, fspr_pool_t *pool)
  40. {
  41. const char *newpath = path_canonicalize(path, pool);
  42. int i;
  43. for (i = strlen(newpath) - 1; i >= 0; i--) {
  44. if (IS_SEP(path[i])) {
  45. break;
  46. }
  47. }
  48. return fspr_pstrndup(pool, path, (i < 0) ? 0 : i);
  49. }
  50. fspr_status_t fspr_dir_make_recursive(const char *path, fspr_fileperms_t perm,
  51. fspr_pool_t *pool)
  52. {
  53. fspr_status_t fspr_err = APR_SUCCESS;
  54. fspr_err = fspr_dir_make(path, perm, pool); /* Try to make PATH right out */
  55. if (APR_STATUS_IS_EEXIST(fspr_err)) { /* It's OK if PATH exists */
  56. return APR_SUCCESS;
  57. }
  58. if (APR_STATUS_IS_ENOENT(fspr_err)) { /* Missing an intermediate dir */
  59. char *dir;
  60. dir = path_remove_last_component(path, pool);
  61. fspr_err = fspr_dir_make_recursive(dir, perm, pool);
  62. if (!fspr_err) {
  63. fspr_err = fspr_dir_make(path, perm, pool);
  64. }
  65. }
  66. return fspr_err;
  67. }