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"
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 fd 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];
99 unsigned int iogroups
= 0;
101 struct stat64 statbuf
;
104 #endif /* !HAVE_STAT64 */
105 bool opt_unlink_early
= false;
108 Error2("%s: wrong number of parameters (%d instead of 1)", argv
[0]?argv
[0]:"<named>", argc
);
111 /* find the appropriate groupbits */
114 Stat64(path
, &statbuf
) < 0
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
;
126 iogroups
= _groupbits(statbuf
.st_mode
);
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
));
144 applyopts(-1, opts
, PH_EARLY
);
145 applyopts_named(path
, opts
, PH_EARLY
);
147 applyopts_named(path
, opts
, PH_PREOPEN
);
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
) {
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
)
174 if (retropt_bool(opts
, OPT_O_NONBLOCK
, &flag
) >= 0 && flag
)
177 if (retropt_bool(opts
, OPT_O_ASYNC
, &flag
) >= 0 && flag
)
180 if (retropt_bool(opts
, OPT_O_TRUNC
, &flag
) >= 0 && flag
)
183 if (retropt_bool(opts
, OPT_O_BINARY
, &flag
) >= 0 && flag
)
187 if (retropt_bool(opts
, OPT_O_TEXT
, &flag
) >= 0 && flag
)
191 if (retropt_bool(opts
, OPT_O_NOINHERIT
, &flag
) >= 0 && flag
)
192 flags
|= O_NOINHERIT
;
195 if (retropt_bool(opts
, OPT_O_NOATIME
, &flag
) >= 0 && flag
)
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
);
209 applyopts_named(path
, opts
, PH_FD
);
210 applyopts(fd
, opts
, PH_FD
);
211 applyopts_cloexec(fd
, opts
);
216 #endif /* _WITH_NAMED */