Magellan Linux

Annotation of /trunk/mkinitrd-magellan/klibc/usr/utils/mkdir.c

Parent Directory Parent Directory | Revision Log 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)
-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     }