3 * Handling of file attributes
5 * (c) 1999 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the `fw' port forwarder.
12 * `fw' is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * `fw' is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with `fw'; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 /*----- Header files ------------------------------------------------------*/
37 #include <sys/types.h>
48 /*----- Global variables --------------------------------------------------*/
52 /*----- Main code ---------------------------------------------------------*/
54 /* --- @fattr_init@ --- *
56 * Arguments: @fattr *f@ = pointer to file attributes
60 * Use: Initializes a set of file attributes to default values.
63 void fattr_init(fattr *f)
65 unsigned um = umask(0);
72 /* --- @fattr_option@ --- *
74 * Arguments: @scanner *sc@ = pointer to scanner to read
75 * @fattr *f@ = pointer to file attributes to set
77 * Returns: Whether the option was claimed.
79 * Use: Reads file attributes from a scanner.
82 int fattr_option(scanner *sc, fattr *f)
84 CONF_BEGIN(sc, "fattr", "file attribute")
86 /* --- Read a file mode specification --- */
88 if (strcmp(sc->d.buf, "mode") == 0) {
91 /* --- Gobble an optional `=' sign --- */
93 conf_undelim(sc, 0, ",=+-");
98 if (sc->t != CTOK_WORD)
99 error(sc, "parse error, expected file mode");
100 conf_undelim(sc, 0, 0);
102 /* --- If it looks digitlike, read as octal --- */
104 if (isdigit((unsigned char)*sc->d.buf))
105 mode = strtoul(sc->d.buf, 0, 8) & 07777;
107 /* --- Otherise read as chmod-like characters --- */
111 unsigned mask = 04700;
115 /* --- Set the default from the umask --- */
118 unsigned um = umask(0);
123 /* --- Parse the characters --- *
125 * This is a particularly lenient implementation of the usual chmod-
126 * style mode language.
129 for (p = sc->d.buf; *p; p++) {
133 case 'a': mask = (mask & state) | 07777; state = 07777; break;
134 case 'u': mask = (mask & state) | 04700; state = 07777; break;
135 case 'g': mask = (mask & state) | 02070; state = 07777; break;
136 case 'o': mask = (mask & state) | 01007; state = 07777; break;
138 case '=': mode &= ~mask; /* Drop through */
139 case '+': state = 0; or = 1; break;
140 case '-': state = 0; or = 0; break;
142 #define APPLY(m) if (or) mode |= ((m) & mask); else mode &= ~((m) & mask);
143 case 'r': state = 0; APPLY(00444); break;
144 case 'w': state = 0; APPLY(00222); break;
145 case 'x': state = 0; APPLY(00111); break;
146 case 's': state = 0; APPLY(06000); break;
147 case 't': state = 0; APPLY(01000); break;
150 default: error(sc, "unknown mode character `%c'", *p);
160 /* --- Read a file uid specification --- */
162 if (strcmp(sc->d.buf, "uid") == 0 ||
163 strcmp(sc->d.buf, "user") == 0 ||
164 strcmp(sc->d.buf, "owner") == 0) {
168 if (sc->t != CTOK_WORD)
169 error(sc, "parse error, expected user name or uid");
170 if (isdigit((unsigned char)*sc->d.buf))
171 f->uid = atoi(sc->d.buf);
173 struct passwd *pw = getpwnam(sc->d.buf);
175 error(sc, "unknown user name `%s'", sc->d.buf);
182 /* --- Read a file gid specification --- */
184 if (strcmp(sc->d.buf, "gid") == 0 ||
185 strcmp(sc->d.buf, "group") == 0) {
189 if (sc->t != CTOK_WORD)
190 error(sc, "parse error, expected group name or gid");
191 if (isdigit((unsigned char)*sc->d.buf))
192 f->gid = atoi(sc->d.buf);
194 struct group *gr = getgrnam(sc->d.buf);
196 error(sc, "unknown user name `%s'", sc->d.buf);
203 /* --- Nothing here for me --- */
208 /* --- @fattr_apply@ --- *
210 * Arguments: @const char *file@ = pointer to filename
211 * @fattr *f@ = pointer to attribute set
213 * Returns: @-1@ if it failed.
215 * Use: Applies file attributes to a file. For best results, try to
216 * create the file with the right permissions and so on. This
217 * call will fix everything up, but there are potential races
218 * which might catch you out if you're not careful.
221 int fattr_apply(const char *file, fattr *f)
223 if (chown(file, f->uid, f->gid) == -1 ||
224 chmod(file, f->mode) == -1)
229 /*----- That's all, folks -------------------------------------------------*/