Contents of /trunk/mkinitrd-magellan/klibc/usr/utils/mkdir.c
Parent Directory | Revision Log
Revision 532 -
(show annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 2845 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 2845 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd
1 | #include <sys/stat.h> |
2 | #include <sys/types.h> |
3 | #include <errno.h> |
4 | #include <fcntl.h> |
5 | #include <signal.h> |
6 | #include <stdio.h> |
7 | #include <stdlib.h> |
8 | #include <string.h> |
9 | #include <unistd.h> |
10 | |
11 | #include "file_mode.h" |
12 | |
13 | static mode_t leaf_mode, subdir_mode; |
14 | static int p_flag; |
15 | |
16 | char *progname; |
17 | |
18 | static __noreturn usage(void) |
19 | { |
20 | fprintf(stderr, "Usage: %s [-p] [-m mode] dir...\n", progname); |
21 | exit(1); |
22 | } |
23 | |
24 | static int make_one_dir(char *dir, mode_t mode) |
25 | { |
26 | struct stat stbuf; |
27 | |
28 | if (mkdir(dir, mode) == -1) { |
29 | int err = errno; |
30 | |
31 | /* |
32 | * Ignore the error if it all of the following |
33 | * are satisfied: |
34 | * - error was EEXIST |
35 | * - -p was specified |
36 | * - stat indicates that its a directory |
37 | */ |
38 | if (p_flag && errno == EEXIST && |
39 | stat(dir, &stbuf) == 0 && S_ISDIR(stbuf.st_mode)) |
40 | return 1; |
41 | errno = err; |
42 | fprintf(stderr, "%s: ", progname); |
43 | perror(dir); |
44 | return -1; |
45 | } |
46 | return 0; |
47 | } |
48 | |
49 | static int make_dir(char *dir) |
50 | { |
51 | int ret; |
52 | |
53 | if (p_flag) { |
54 | char *s, *p; |
55 | |
56 | /* |
57 | * Recurse each directory, trying to make it |
58 | * as we go. Should we check to see if it |
59 | * exists, and if so if it's a directory |
60 | * before calling mkdir? |
61 | */ |
62 | s = dir; |
63 | while ((p = strchr(s, '/')) != NULL) { |
64 | /* |
65 | * Ignore the leading / |
66 | */ |
67 | if (p != dir) { |
68 | *p = '\0'; |
69 | |
70 | /* |
71 | * Make the intermediary directory. POSIX |
72 | * says that these directories are created |
73 | * with umask,u+wx |
74 | */ |
75 | if (make_one_dir(dir, subdir_mode) == -1) |
76 | return -1; |
77 | |
78 | *p = '/'; |
79 | } |
80 | s = p + 1; |
81 | } |
82 | } |
83 | |
84 | /* |
85 | * Make the final target. Only complain if the |
86 | * target already exists if -p was not specified. |
87 | * This is created with the asked for mode & ~umask |
88 | */ |
89 | ret = make_one_dir(dir, leaf_mode); |
90 | if (ret == -1) |
91 | return -1; |
92 | |
93 | /* |
94 | * We might not set all the permission bits. Do that |
95 | * here (but only if we did create it.) |
96 | */ |
97 | if (ret == 0 && chmod(dir, leaf_mode) == -1) { |
98 | int err_save = errno; |
99 | |
100 | /* |
101 | * We failed, remove the directory we created |
102 | */ |
103 | rmdir(dir); |
104 | errno = err_save; |
105 | fprintf(stderr, "%s: ", progname); |
106 | perror(dir); |
107 | return -1; |
108 | } |
109 | return 0; |
110 | } |
111 | |
112 | int main(int argc, char *argv[]) |
113 | { |
114 | int c, ret = 0; |
115 | mode_t saved_umask; |
116 | |
117 | progname = argv[0]; |
118 | |
119 | saved_umask = umask(0); |
120 | leaf_mode = (S_IRWXU | S_IRWXG | S_IRWXO) & ~saved_umask; |
121 | subdir_mode = (saved_umask ^ (S_IRWXU | S_IRWXG | S_IRWXO)) |
122 | | S_IWUSR | S_IXUSR; |
123 | |
124 | do { |
125 | c = getopt(argc, argv, "pm:"); |
126 | if (c == EOF) |
127 | break; |
128 | switch (c) { |
129 | case 'm': |
130 | leaf_mode = |
131 | parse_file_mode(optarg, leaf_mode, saved_umask); |
132 | break; |
133 | case 'p': |
134 | p_flag = 1; |
135 | break; |
136 | |
137 | case '?': |
138 | fprintf(stderr, "%s: invalid option -%c\n", |
139 | progname, optopt); |
140 | usage(); |
141 | } |
142 | } while (1); |
143 | |
144 | if (optind == argc) |
145 | usage(); |
146 | |
147 | while (optind < argc) { |
148 | if (make_dir(argv[optind])) |
149 | ret = 255; /* seems to be what gnu mkdir does */ |
150 | optind++; |
151 | } |
152 | |
153 | return ret; |
154 | } |