1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23 /*
24 * Copyright 1995 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 #pragma ident "%Z%%M% %I% %E% SMI"
29
30 /*
31 * Exported file system table manager. Reads/writes "/etc/xtab".
32 */
33
34 #include <stdio.h>
35 #include <exportent.h>
36 #include <sys/file.h>
37 #include <ctype.h>
38
39 extern char *strtok();
40 extern char *strcpy();
41
42 #define LINESIZE 4096
43
44 static char *TMPFILE = "/tmp/xtabXXXXXX";
45
46 static char *skipwhite(char *);
47 static char *skipnonwhite(char *);
48
49 FILE *
setexportent(void)50 setexportent(void)
51 {
52 FILE *f;
53 int fd;
54
55 /*
56 * Create the tab file if it does not exist already
57 */
58 if (access(TABFILE, F_OK) < 0) {
59 fd = open(TABFILE, O_CREAT, 0644);
60 close(fd);
61 }
62 if (access(TABFILE, W_OK) == 0) {
63 f = fopen(TABFILE, "r+");
64 } else {
65 f = fopen(TABFILE, "r");
66 }
67 if (f == NULL) {
68 return (NULL);
69 }
70 if (flock(fileno(f), LOCK_EX) < 0) {
71 (void)fclose(f);
72 return (NULL);
73 }
74 return (f);
75 }
76
77
78 void
endexportent(FILE * f)79 endexportent(FILE *f)
80 {
81 (void) fclose(f);
82 }
83
84
85 struct exportent *
getexportent(FILE * f)86 getexportent(FILE *f)
87 {
88 static char *line = NULL;
89 static struct exportent xent;
90 int len;
91 char *p;
92
93 if (line == NULL) {
94 line = (char *)malloc(LINESIZE + 1);
95 }
96 if (fgets(line, LINESIZE, f) == NULL) {
97 return (NULL);
98 }
99 len = strlen(line);
100 if (line[len-1] == '\n') {
101 line[len-1] = 0;
102 }
103 xent.xent_dirname = line;
104 xent.xent_options = NULL;
105 p = skipnonwhite(line);
106 if (*p == 0) {
107 return (&xent);
108 }
109 *p++ = 0;
110 p = skipwhite(p);
111 if (*p == 0) {
112 return (&xent);
113 }
114 if (*p == '-') {
115 p++;
116 }
117 xent.xent_options = p;
118 return (&xent);
119 }
120
121 int
remexportent(FILE * f,char * dirname)122 remexportent(FILE *f, char *dirname)
123 {
124 char buf[LINESIZE];
125 FILE *f2;
126 int len;
127 char *fname;
128 int fd;
129 long pos;
130 long rempos;
131 int remlen;
132 int res;
133
134 fname = (char *) malloc(strlen(TMPFILE) + 1);
135 pos = ftell(f);
136 rempos = 0;
137 remlen = 0;
138 (void)strcpy(fname, TMPFILE);
139 fd = mkstemp(fname);
140 if (fd < 0) {
141 return (-1);
142 }
143 if (unlink(fname) < 0) {
144 (void)close(fd);
145 return (-1);
146 }
147 f2 = fdopen(fd, "r+");
148 if (f2 == NULL) {
149 (void)close(fd);
150 return (-1);
151 }
152 len = strlen(dirname);
153 rewind(f);
154 while (fgets(buf, sizeof(buf), f)) {
155 if (strncmp(buf, dirname,
156 len) != 0 || ! isspace((unsigned char)buf[len])) {
157 if (fputs(buf, f2) <= 0) {
158 (void)fclose(f2);
159 return (-1);
160 }
161 } else {
162 remlen = strlen(buf);
163 rempos = ftell(f) - remlen;
164 }
165 }
166 rewind(f);
167 if (ftruncate(fileno(f), 0L) < 0) {
168 (void)fclose(f2);
169 return (-1);
170 }
171 rewind(f2);
172 while (fgets(buf, sizeof(buf), f2)) {
173 if (fputs(buf, f) <= 0) {
174 (void)fclose(f2);
175 return (-1);
176 }
177 }
178 (void)fclose(f2);
179 if (remlen == 0) {
180 /* nothing removed */
181 (void) fseek(f, pos, L_SET);
182 res = -1;
183 } else if (pos <= rempos) {
184 res = fseek(f, pos, L_SET);
185 } else if (pos > rempos + remlen) {
186 res = fseek(f, pos - remlen, L_SET);
187 } else {
188 res = fseek(f, rempos, L_SET);
189 }
190 return (res < 0 ? -1 : 0);
191 }
192
193 int
addexportent(FILE * f,char * dirname,char * options)194 addexportent(FILE *f, char *dirname, char *options)
195 {
196 long pos;
197
198 pos = ftell(f);
199 if (fseek(f, 0L, L_XTND) >= 0 &&
200 fprintf(f, "%s", dirname) > 0 &&
201 (options == NULL || fprintf(f, " -%s", options) > 0) &&
202 fprintf(f, "\n") > 0 &&
203 fseek(f, pos, L_SET) >= 0) {
204 return (0);
205 }
206 return (-1);
207 }
208
209
210 char *
getexportopt(struct exportent * xent,char * opt)211 getexportopt(struct exportent *xent, char *opt)
212 {
213 static char *tokenbuf = NULL;
214 char *lp;
215 char *tok;
216 int len;
217
218 if (tokenbuf == NULL) {
219 tokenbuf = (char *)malloc(LINESIZE);
220 }
221 if (xent->xent_options == NULL) {
222 return (NULL);
223 }
224 (void)strcpy(tokenbuf, xent->xent_options);
225 lp = tokenbuf;
226 len = strlen(opt);
227 while ((tok = strtok(lp, ",")) != NULL) {
228 lp = NULL;
229 if (strncmp(opt, tok, len) == 0) {
230 if (tok[len] == '=') {
231 return (&tok[len + 1]);
232 } else if (tok[len] == 0) {
233 return ("");
234 }
235 }
236 }
237 return (NULL);
238 }
239
240
241 #define iswhite(c) ((c) == ' ' || c == '\t')
242
243 static char *
skipwhite(char * str)244 skipwhite(char *str)
245 {
246 while (*str && iswhite(*str)) {
247 str++;
248 }
249 return (str);
250 }
251
252 static char *
skipnonwhite(char * str)253 skipnonwhite(char *str)
254 {
255 while (*str && ! iswhite(*str)) {
256 str++;
257 }
258 return (str);
259 }
260