Annotation of /trunk/mkinitrd-magellan/klibc/usr/utils/mkdir.c
Parent Directory | Revision Log
Revision 532 -
(hide annotations)
(download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 months ago) by niro
File MIME type: text/plain
File size: 2845 byte(s)
Sat Sep 1 22:45:15 2007 UTC (16 years, 9 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 | niro | 532 | #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 | } |