version 1.7.3.0
[socat.git] / xio-named.c
blobfbb9f685edd5dd67479381f7ad20dfc76f2805d4
1 /* source: xio-named.c */
2 /* Copyright Gerhard Rieger */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the source for filesystem entry functions */
7 #include "xiosysincludes.h"
9 #if _WITH_NAMED
11 #include "xioopen.h"
12 #include "xio-named.h"
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 */
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;
31 if (!opts) return 0;
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));
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));
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));
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));
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));
76 break;
77 default: Error1("applyopts_named(): option \"%s\" not implemented",
78 opt->desc->defname);
79 break;
81 opt->desc = ODESC_DONE;
82 ++opt;
84 return 0;
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...
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;
106 if (argc != 2) {
107 Error2("%s: wrong number of parameters (%d instead of 1)", argv[0]?argv[0]:"<named>", argc);
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 */
118 if (errno != ENOENT) {
119 Error2("stat(\"%s\"): %s", path, strerror(errno));
120 return STAT_RETRYLATER;
122 *exists = false;
123 } else {
124 *exists = true;
127 if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
128 applyopts(-1, opts, PH_INIT);
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;
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);
148 return statbuf.st_mode;
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
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;
162 applyopts_named(path, opts, PH_PREOPEN);
164 /* this only applies pure OPEN flags, not mixed OPEN/FCNTL options */
165 applyopts_flags(opts, GROUP_OPEN, &flags);
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
195 retropt_modet(opts, OPT_PERM, &mode);
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;
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;
212 #endif /* _WITH_NAMED */