1 /* source: xio-named.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
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"
12 #include "xio-named.h"
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 #endif /* WITH_NAMED */
26 /* applies to filesystem entry all options belonging to phase */
27 int applyopts_named(const char *filename
, struct opt
*opts
, unsigned int phase
) {
32 opt
= opts
; while (opt
->desc
!= ODESC_END
) {
33 if (opt
->desc
== ODESC_DONE
||
34 opt
->desc
->phase
!= phase
&& phase
!= PH_ALL
||
35 !(opt
->desc
->group
& GROUP_NAMED
)) {
37 switch (opt
->desc
->optcode
) {
40 if (Chown(filename
, -1, opt
->value
.u_gidt
) < 0) {
41 Error3("chown(\"%s\", -1, "F_gid
"): %s", filename
,
42 opt
->value
.u_gidt
, strerror(errno
));
47 if (Chown(filename
, opt
->value
.u_uidt
, -1) < 0) {
48 Error3("chown(\"%s\", "F_uid
", -1): %s", filename
,
49 opt
->value
.u_uidt
, strerror(errno
));
54 if (Chmod(filename
, opt
->value
.u_modet
) < 0) {
55 Error3("chmod(\"%s\", "F_mode
"): %s",
56 filename
, opt
->value
.u_modet
, strerror(errno
));
59 case OPT_UNLINK_EARLY
:
61 xio_unlink(filename
, E_ERROR
);
64 if (Unlink(filename
) < 0) {
65 if (errno
== ENOENT
) {
66 /* We have just created/opened it, that's - surprising! */
67 Warn2("unlink(\"%s\"): %s", filename
, strerror(errno
));
69 Error2("unlink(\"%s\"): %s", filename
, strerror(errno
));
73 default: Error1("applyopts_named(): option \"%s\" not implemented",
77 opt
->desc
= ODESC_DONE
;
84 /* perform actions that are common to all NAMED group addresses: checking if
85 the entry exists, parsing options, ev.removing old filesystem entry or
86 setting early owners and permissions.
87 It applies options of PH_EARLY and PH_PREOPEN.
88 If the path exists, its st_mode field is returned.
89 After this sub you may proceed with open() or whatever...
91 int _xioopen_named_early(
100 const char *path
= argv
[1];
101 struct single
*sfd
= &xfd
->stream
;
103 struct stat64 statbuf
;
106 #endif /* !HAVE_STAT64 */
107 bool opt_unlink_early
= false;
110 xio_syntax(argv
[0], 1, argc
-1, syntax
);
114 /* find the appropriate groupbits */
117 Stat64(path
, &statbuf
) < 0
119 Stat(path
, &statbuf
) < 0
120 #endif /* !HAVE_STAT64 */
122 if (errno
!= ENOENT
) {
123 Error2("stat(\"%s\"): %s", path
, strerror(errno
));
124 return STAT_RETRYLATER
;
131 if (applyopts_single(sfd
, opts
, PH_INIT
) < 0)
133 applyopts(sfd
, -1, opts
, PH_INIT
);
135 retropt_bool(opts
, OPT_UNLINK_EARLY
, &opt_unlink_early
);
136 if (*exists
&& opt_unlink_early
) {
137 Info1("\"%s\" already exists; removing it", path
);
138 if (Unlink(path
) < 0) {
139 Error2("unlink(\"%s\"): %s", path
, strerror(errno
));
145 applyopts_named(path
, opts
, PH_EARLY
);
146 applyopts(sfd
, -1, opts
, PH_EARLY
);
148 applyopts_named(path
, opts
, PH_PREOPEN
);
150 dropopts(opts
, PH_PREOPEN
);
153 return statbuf
.st_mode
;
157 /* retrieve the OPEN group options and perform the open() call.
158 returns the file descriptor or a negative value.
159 Applies options of phases PREOPEN, OPEN, PASTOPEN, and FD
161 int _xioopen_open(const char *path
, int rw
, struct opt
*opts
) {
167 applyopts_named(path
, opts
, PH_PREOPEN
);
169 /* this only applies pure OPEN flags, not mixed OPEN/FCNTL options */
170 applyopts_flags(opts
, GROUP_OPEN
, &flags
);
172 /* we have to handle mixed OPEN/FCNTL flags specially */
173 if (retropt_bool(opts
, OPT_O_APPEND
, &flag
) >= 0 && flag
)
175 if (retropt_bool(opts
, OPT_O_NONBLOCK
, &flag
) >= 0 && flag
)
178 if (retropt_bool(opts
, OPT_O_ASYNC
, &flag
) >= 0 && flag
)
181 if (retropt_bool(opts
, OPT_O_TRUNC
, &flag
) >= 0 && flag
)
184 if (retropt_bool(opts
, OPT_O_BINARY
, &flag
) >= 0 && flag
)
188 if (retropt_bool(opts
, OPT_O_TEXT
, &flag
) >= 0 && flag
)
192 if (retropt_bool(opts
, OPT_O_NOINHERIT
, &flag
) >= 0 && flag
)
193 flags
|= O_NOINHERIT
;
196 if (retropt_bool(opts
, OPT_O_NOATIME
, &flag
) >= 0 && flag
)
200 retropt_modet(opts
, OPT_PERM
, &mode
);
203 fd
= Open(path
, flags
, mode
);
204 } while (fd
< 0 && errno
== EINTR
);
206 Error4("open(\"%s\", 0%lo, 0%03o): %s",
207 path
, flags
, mode
, strerror(errno
));
208 return STAT_RETRYLATER
;
210 /*0 Info4("open(\"%s\", 0%o, 0%03o) -> %d", path, flags, mode, fd);*/
211 applyopts_named(path
, opts
, PH_PASTOPEN
);
213 applyopts_named(path
, opts
, PH_FD
);
214 applyopts(fd
, opts
, PH_FD
);
215 applyopts_cloexec(fd
, opts
);
220 /* Wrapper around Unlink() that handles the case of non existing file (ENOENT)
221 just as E_INFO. All other errors are handled with level. */
223 const char *filename
, /* the file to be removed */
224 int level
) /* the severity level for other errors, e.g.E_ERROR */
228 if (Unlink(filename
) < 0) {
230 if (errno
== ENOENT
) {
231 Info2("unlink(\"%s\"): %s", filename
, strerror(errno
));
233 Msg2(level
, "unlink(\"%s\"): %s", filename
, strerror(errno
));
241 #endif /* _WITH_NAMED */