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 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
) {
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
)) {
38 switch (opt
->desc
->optcode
) {
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
));
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
));
55 if (Chmod(filename
, opt
->value
.u_modet
) < 0) {
56 Error3("chmod(\"%s\", "F_mode
"): %s",
57 filename
, opt
->value
.u_modet
, strerror(errno
));
60 case OPT_UNLINK_EARLY
:
63 if (Unlink(filename
) < 0) {
64 if (errno
== ENOENT
) {
65 Warn2("unlink(\"%s\"): %s", filename
, strerror(errno
));
67 Error2("unlink(\"%s\"): %s", filename
, strerror(errno
));
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
));
77 default: Error1("applyopts_named(): option \"%s\" not implemented",
81 opt
->desc
= ODESC_DONE
;
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
,
97 bool *exists
, struct opt
*opts
) {
98 const char *path
= argv
[1];
100 struct stat64 statbuf
;
103 #endif /* !HAVE_STAT64 */
104 bool opt_unlink_early
= false;
107 Error2("%s: wrong number of parameters (%d instead of 1)", argv
[0]?argv
[0]:"<named>", argc
);
110 /* find the appropriate groupbits */
113 Stat64(path
, &statbuf
) < 0
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
;
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
));
140 applyopts_named(path
, opts
, PH_EARLY
);
141 applyopts(-1, opts
, PH_EARLY
);
143 applyopts_named(path
, opts
, PH_PREOPEN
);
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
) {
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
)
170 if (retropt_bool(opts
, OPT_O_NONBLOCK
, &flag
) >= 0 && flag
)
173 if (retropt_bool(opts
, OPT_O_ASYNC
, &flag
) >= 0 && flag
)
176 if (retropt_bool(opts
, OPT_O_TRUNC
, &flag
) >= 0 && flag
)
179 if (retropt_bool(opts
, OPT_O_BINARY
, &flag
) >= 0 && flag
)
183 if (retropt_bool(opts
, OPT_O_TEXT
, &flag
) >= 0 && flag
)
187 if (retropt_bool(opts
, OPT_O_NOINHERIT
, &flag
) >= 0 && flag
)
188 flags
|= O_NOINHERIT
;
191 if (retropt_bool(opts
, OPT_O_NOATIME
, &flag
) >= 0 && flag
)
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
);
205 applyopts_named(path
, opts
, PH_FD
);
206 applyopts(fd
, opts
, PH_FD
);
207 applyopts_cloexec(fd
, opts
);
212 #endif /* _WITH_NAMED */