1 /* Make a file's ancestor directories.
3 Copyright (C) 2006 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software Foundation,
17 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 /* Written by Paul Eggert. */
23 #include "mkancesdirs.h"
29 #include "stat-macros.h"
31 /* Return 0 if FILE is a directory, otherwise -1 (setting errno). */
34 test_dir (char const *file)
37 if (stat (file, &st) == 0)
39 if (S_ISDIR (st.st_mode))
46 /* Ensure that the ancestor directories of FILE exist, using an
47 algorithm that should work even if two processes execute this
48 function in parallel. Temporarily modify FILE by storing '\0'
49 bytes into it, to access the ancestor directories.
51 Create any ancestor directories that don't already exist, by
52 invoking MAKE_DIR (ANCESTOR, MAKE_DIR_ARG). This function should
53 return zero if successful, -1 (setting errno) otherwise.
55 If successful, return 0 with FILE set back to its original value;
56 otherwise, return -1 (setting errno), storing a '\0' into *FILE so
57 that it names the ancestor directory that had problems. */
60 mkancesdirs (char *file,
61 int (*make_dir) (char const *, void *),
64 /* This algorithm is O(N**2) but in typical practice the fancier
65 O(N) algorithms are slower. */
67 /* Address of the previous directory separator that follows an
68 ordinary byte in a file name in the left-to-right scan, or NULL
69 if no such separator precedes the current location P. */
72 char const *prefix_end = file + FILE_SYSTEM_PREFIX_LEN (file);
76 /* Search backward through FILE using mkdir to create the
77 furthest-away ancestor that is needed. This loop isn't needed
78 for correctness, but typically ancestors already exist so this
79 loop speeds things up a bit.
81 This loop runs a bit faster if errno initially contains an error
82 number corresponding to a failed access to FILE. However, things
83 work correctly regardless of errno's initial value. */
85 for (p = last_component (file); prefix_end < p; p--)
86 if (ISSLASH (*p) && ! ISSLASH (p[-1]))
90 if (errno == ENOENT && make_dir (file, make_dir_arg) == 0)
98 if (test_dir (file) == 0)
110 /* Scan forward through FILE, creating directories along the way.
111 Try mkdir before stat, so that the procedure works even when two
112 or more processes are executing it in parallel. */
120 else if (ISSLASH (c) && *p && sep)
123 if (make_dir (file, make_dir_arg) != 0 && test_dir (file) != 0)