add listen-timeout to function as an accept timeout
[socat/sam.git] / xio-named.c
blob892cc963063ce7d8ee5f67fa1c499956209306c2
1 /* source: xio-named.c */
2 /* Copyright Gerhard Rieger 2001-2008 */
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 fd 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 unsigned int iogroups = 0;
100 #if HAVE_STAT64
101 struct stat64 statbuf;
102 #else
103 struct stat statbuf;
104 #endif /* !HAVE_STAT64 */
105 bool opt_unlink_early = false;
107 if (argc != 2) {
108 Error2("%s: wrong number of parameters (%d instead of 1)", argv[0]?argv[0]:"<named>", argc);
110 statbuf.st_mode = 0;
111 /* find the appropriate groupbits */
112 if (
113 #if HAVE_STAT64
114 Stat64(path, &statbuf) < 0
115 #else
116 Stat(path, &statbuf) < 0
117 #endif /* !HAVE_STAT64 */
119 if (errno != ENOENT) {
120 Error2("stat(\"%s\"): %s", path, strerror(errno));
121 return STAT_RETRYLATER;
123 iogroups = GROUP_REG;
124 *exists = false;
125 } else {
126 iogroups = _groupbits(statbuf.st_mode);
127 *exists = true;
130 if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
131 applyopts(-1, opts, PH_INIT);
133 retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
134 if (*exists && opt_unlink_early) {
135 Info1("\"%s\" already exists; removing it", path);
136 if (Unlink(path) < 0) {
137 Error2("unlink(\"%s\"): %s", path, strerror(errno));
138 *exists = true;
139 } else {
140 *exists = false;
144 applyopts(-1, opts, PH_EARLY);
145 applyopts_named(path, opts, PH_EARLY);
146 if (*exists) {
147 applyopts_named(path, opts, PH_PREOPEN);
148 } else {
149 dropopts(opts, PH_PREOPEN);
152 return statbuf.st_mode;
156 /* retrieve the OPEN group options and perform the open() call.
157 returns the file descriptor or a negative value.
158 Applies options of phases PREOPEN, OPEN, PASTOPEN, and FD
160 int _xioopen_open(const char *path, int rw, struct opt *opts) {
161 mode_t mode = 0666;
162 flags_t flags = rw;
163 bool flag;
164 int fd;
166 applyopts_named(path, opts, PH_PREOPEN);
168 /* this only applies pure OPEN flags, not mixed OPEN/FCNTL options */
169 applyopts_flags(opts, GROUP_OPEN, &flags);
171 /* we have to handle mixed OPEN/FCNTL flags specially */
172 if (retropt_bool(opts, OPT_O_APPEND, &flag) >= 0 && flag)
173 flags |= O_APPEND;
174 if (retropt_bool(opts, OPT_O_NONBLOCK, &flag) >= 0 && flag)
175 flags |= O_NONBLOCK;
176 #ifdef O_ASYNC
177 if (retropt_bool(opts, OPT_O_ASYNC, &flag) >= 0 && flag)
178 flags |= O_ASYNC;
179 #endif
180 if (retropt_bool(opts, OPT_O_TRUNC, &flag) >= 0 && flag)
181 flags |= O_TRUNC;
182 #ifdef O_BINARY
183 if (retropt_bool(opts, OPT_O_BINARY, &flag) >= 0 && flag)
184 flags |= O_BINARY;
185 #endif
186 #ifdef O_TEXT
187 if (retropt_bool(opts, OPT_O_TEXT, &flag) >= 0 && flag)
188 flags |= O_TEXT;
189 #endif
190 #ifdef O_NOINHERIT
191 if (retropt_bool(opts, OPT_O_NOINHERIT, &flag) >= 0 && flag)
192 flags |= O_NOINHERIT;
193 #endif
194 #ifdef O_NOATIME
195 if (retropt_bool(opts, OPT_O_NOATIME, &flag) >= 0 && flag)
196 flags |= O_NOATIME;
197 #endif
199 retropt_modet(opts, OPT_PERM, &mode);
201 if ((fd = Open(path, flags, mode)) < 0) {
202 Error4("open(\"%s\", 0%lo, 0%03o): %s",
203 path, flags, mode, strerror(errno));
204 return STAT_RETRYLATER;
206 /*0 Info4("open(\"%s\", 0%o, 0%03o) -> %d", path, flags, mode, fd);*/
207 applyopts_named(path, opts, PH_PASTOPEN);
208 #if 0
209 applyopts_named(path, opts, PH_FD);
210 applyopts(fd, opts, PH_FD);
211 applyopts_cloexec(fd, opts);
212 #endif
213 return fd;
216 #endif /* _WITH_NAMED */