nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* source: xio-named.c */ |
2 | /* Copyright Gerhard Rieger */ |
||
3 | /* Published under the GNU General Public License V.2, see file COPYING */ |
||
4 | |||
5 | /* this file contains the source for filesystem entry functions */ |
||
6 | |||
7 | #include "xiosysincludes.h" |
||
8 | |||
9 | #if _WITH_NAMED |
||
10 | |||
11 | #include "xioopen.h" |
||
12 | #include "xio-named.h" |
||
13 | |||
14 | |||
15 | #if WITH_NAMED |
||
16 | const struct optdesc opt_group_early = { "group-early", NULL, OPT_GROUP_EARLY, GROUP_NAMED, PH_PREOPEN, TYPE_GIDT, OFUNC_SPEC }; |
||
17 | const struct optdesc opt_perm_early = { "perm-early", NULL, OPT_PERM_EARLY, GROUP_NAMED, PH_PREOPEN, TYPE_MODET,OFUNC_SPEC }; |
||
18 | const struct optdesc opt_user_early = { "user-early", NULL, OPT_USER_EARLY, GROUP_NAMED, PH_PREOPEN, TYPE_UIDT, OFUNC_SPEC }; |
||
19 | /*0 const struct optdesc opt_force = { "force", NULL, OPT_FORCE, GROUP_NAMED, PH_???, TYPE_BOOL, OFUNC_SPEC };*/ |
||
20 | const struct optdesc opt_unlink = { "unlink", NULL, OPT_UNLINK, GROUP_NAMED, PH_PREOPEN, TYPE_BOOL, OFUNC_SPEC }; |
||
21 | const struct optdesc opt_unlink_early= { "unlink-early",NULL, OPT_UNLINK_EARLY,GROUP_NAMED, PH_EARLY, TYPE_BOOL, OFUNC_SPEC }; |
||
22 | const struct optdesc opt_unlink_late = { "unlink-late", NULL, OPT_UNLINK_LATE, GROUP_NAMED, PH_PASTOPEN, TYPE_BOOL, OFUNC_SPEC }; |
||
23 | const struct optdesc opt_unlink_close = { "unlink-close", NULL, OPT_UNLINK_CLOSE, GROUP_NAMED, PH_LATE, TYPE_BOOL, OFUNC_SPEC }; |
||
24 | const struct optdesc opt_umask = { "umask", NULL, OPT_UMASK, GROUP_NAMED, PH_EARLY, TYPE_MODET, OFUNC_SPEC }; |
||
25 | #endif /* WITH_NAMED */ |
||
26 | |||
27 | /* applies to filesystem entry all options belonging to phase */ |
||
28 | int applyopts_named(const char *filename, struct opt *opts, unsigned int phase) { |
||
29 | struct opt *opt; |
||
30 | |||
31 | if (!opts) return 0; |
||
32 | |||
33 | opt = opts; while (opt->desc != ODESC_END) { |
||
34 | if (opt->desc == ODESC_DONE || |
||
35 | opt->desc->phase != phase && phase != PH_ALL || |
||
36 | !(opt->desc->group & GROUP_NAMED)) { |
||
37 | ++opt; continue; } |
||
38 | switch (opt->desc->optcode) { |
||
39 | case OPT_GROUP_EARLY: |
||
40 | case OPT_GROUP: |
||
41 | if (Chown(filename, -1, opt->value.u_gidt) < 0) { |
||
42 | Error3("chown(\"%s\", -1, "F_gid"): %s", filename, |
||
43 | opt->value.u_gidt, strerror(errno)); |
||
44 | } |
||
45 | break; |
||
46 | case OPT_USER_EARLY: |
||
47 | case OPT_USER: |
||
48 | if (Chown(filename, opt->value.u_uidt, -1) < 0) { |
||
49 | Error3("chown(\"%s\", "F_uid", -1): %s", filename, |
||
50 | opt->value.u_uidt, strerror(errno)); |
||
51 | } |
||
52 | break; |
||
53 | case OPT_PERM_EARLY: |
||
54 | case OPT_PERM: |
||
55 | if (Chmod(filename, opt->value.u_modet) < 0) { |
||
56 | Error3("chmod(\"%s\", "F_mode"): %s", |
||
57 | filename, opt->value.u_modet, strerror(errno)); |
||
58 | } |
||
59 | break; |
||
60 | case OPT_UNLINK_EARLY: |
||
61 | case OPT_UNLINK: |
||
62 | case OPT_UNLINK_LATE: |
||
63 | if (Unlink(filename) < 0) { |
||
64 | if (errno == ENOENT) { |
||
65 | Warn2("unlink(\"%s\"): %s", filename, strerror(errno)); |
||
66 | } else { |
||
67 | Error2("unlink(\"%s\"): %s", filename, strerror(errno)); |
||
68 | } |
||
69 | } |
||
70 | break; |
||
71 | case OPT_UMASK: |
||
72 | if (Umask(opt->value.u_modet) < 0) { |
||
73 | /* linux docu says it always succeeds, but who believes it? */ |
||
74 | Error2("umask("F_mode"): %s", opt->value.u_modet, strerror(errno)); |
||
75 | } |
||
76 | break; |
||
77 | default: Error1("applyopts_named(): option \"%s\" not implemented", |
||
78 | opt->desc->defname); |
||
79 | break; |
||
80 | } |
||
81 | opt->desc = ODESC_DONE; |
||
82 | ++opt; |
||
83 | } |
||
84 | return 0; |
||
85 | } |
||
86 | |||
87 | |||
88 | /* perform actions that are common to all NAMED group addresses: checking if |
||
89 | the entry exists, parsing options, ev.removing old filesystem entry or |
||
90 | setting early owners and permissions. |
||
91 | It applies options of PH_EARLY and PH_PREOPEN. |
||
92 | If the path exists, its st_mode field is returned. |
||
93 | After this sub you may proceed with open() or whatever... |
||
94 | */ |
||
95 | int _xioopen_named_early(int argc, const char *argv[], xiofile_t *xfd, |
||
96 | int groups, |
||
97 | bool *exists, struct opt *opts) { |
||
98 | const char *path = argv[1]; |
||
99 | #if HAVE_STAT64 |
||
100 | struct stat64 statbuf; |
||
101 | #else |
||
102 | struct stat statbuf; |
||
103 | #endif /* !HAVE_STAT64 */ |
||
104 | bool opt_unlink_early = false; |
||
105 | |||
106 | if (argc != 2) { |
||
107 | Error2("%s: wrong number of parameters (%d instead of 1)", argv[0]?argv[0]:"<named>", argc); |
||
108 | } |
||
109 | statbuf.st_mode = 0; |
||
110 | /* find the appropriate groupbits */ |
||
111 | if ( |
||
112 | #if HAVE_STAT64 |
||
113 | Stat64(path, &statbuf) < 0 |
||
114 | #else |
||
115 | Stat(path, &statbuf) < 0 |
||
116 | #endif /* !HAVE_STAT64 */ |
||
117 | ) { |
||
118 | if (errno != ENOENT) { |
||
119 | Error2("stat(\"%s\"): %s", path, strerror(errno)); |
||
120 | return STAT_RETRYLATER; |
||
121 | } |
||
122 | *exists = false; |
||
123 | } else { |
||
124 | *exists = true; |
||
125 | } |
||
126 | |||
127 | if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1; |
||
128 | applyopts(-1, opts, PH_INIT); |
||
129 | |||
130 | retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early); |
||
131 | if (*exists && opt_unlink_early) { |
||
132 | Info1("\"%s\" already exists; removing it", path); |
||
133 | if (Unlink(path) < 0) { |
||
134 | Error2("unlink(\"%s\"): %s", path, strerror(errno)); |
||
135 | } else { |
||
136 | *exists = false; |
||
137 | } |
||
138 | } |
||
139 | |||
140 | applyopts_named(path, opts, PH_EARLY); |
||
141 | applyopts(-1, opts, PH_EARLY); |
||
142 | if (*exists) { |
||
143 | applyopts_named(path, opts, PH_PREOPEN); |
||
144 | } else { |
||
145 | dropopts(opts, PH_PREOPEN); |
||
146 | } |
||
147 | |||
148 | return statbuf.st_mode; |
||
149 | } |
||
150 | |||
151 | |||
152 | /* retrieve the OPEN group options and perform the open() call. |
||
153 | returns the file descriptor or a negative value. |
||
154 | Applies options of phases PREOPEN, OPEN, PASTOPEN, and FD |
||
155 | */ |
||
156 | int _xioopen_open(const char *path, int rw, struct opt *opts) { |
||
157 | mode_t mode = 0666; |
||
158 | flags_t flags = rw; |
||
159 | bool flag; |
||
160 | int fd; |
||
161 | |||
162 | applyopts_named(path, opts, PH_PREOPEN); |
||
163 | |||
164 | /* this only applies pure OPEN flags, not mixed OPEN/FCNTL options */ |
||
165 | applyopts_flags(opts, GROUP_OPEN, &flags); |
||
166 | |||
167 | /* we have to handle mixed OPEN/FCNTL flags specially */ |
||
168 | if (retropt_bool(opts, OPT_O_APPEND, &flag) >= 0 && flag) |
||
169 | flags |= O_APPEND; |
||
170 | if (retropt_bool(opts, OPT_O_NONBLOCK, &flag) >= 0 && flag) |
||
171 | flags |= O_NONBLOCK; |
||
172 | #ifdef O_ASYNC |
||
173 | if (retropt_bool(opts, OPT_O_ASYNC, &flag) >= 0 && flag) |
||
174 | flags |= O_ASYNC; |
||
175 | #endif |
||
176 | if (retropt_bool(opts, OPT_O_TRUNC, &flag) >= 0 && flag) |
||
177 | flags |= O_TRUNC; |
||
178 | #ifdef O_BINARY |
||
179 | if (retropt_bool(opts, OPT_O_BINARY, &flag) >= 0 && flag) |
||
180 | flags |= O_BINARY; |
||
181 | #endif |
||
182 | #ifdef O_TEXT |
||
183 | if (retropt_bool(opts, OPT_O_TEXT, &flag) >= 0 && flag) |
||
184 | flags |= O_TEXT; |
||
185 | #endif |
||
186 | #ifdef O_NOINHERIT |
||
187 | if (retropt_bool(opts, OPT_O_NOINHERIT, &flag) >= 0 && flag) |
||
188 | flags |= O_NOINHERIT; |
||
189 | #endif |
||
190 | #ifdef O_NOATIME |
||
191 | if (retropt_bool(opts, OPT_O_NOATIME, &flag) >= 0 && flag) |
||
192 | flags |= O_NOATIME; |
||
193 | #endif |
||
194 | |||
195 | retropt_modet(opts, OPT_PERM, &mode); |
||
196 | |||
197 | if ((fd = Open(path, flags, mode)) < 0) { |
||
198 | Error4("open(\"%s\", 0%lo, 0%03o): %s", |
||
199 | path, flags, mode, strerror(errno)); |
||
200 | return STAT_RETRYLATER; |
||
201 | } |
||
202 | /*0 Info4("open(\"%s\", 0%o, 0%03o) -> %d", path, flags, mode, fd);*/ |
||
203 | applyopts_named(path, opts, PH_PASTOPEN); |
||
204 | #if 0 |
||
205 | applyopts_named(path, opts, PH_FD); |
||
206 | applyopts(fd, opts, PH_FD); |
||
207 | applyopts_cloexec(fd, opts); |
||
208 | #endif |
||
209 | return fd; |
||
210 | } |
||
211 | |||
212 | #endif /* _WITH_NAMED */ |