xref: /titanic_52/usr/src/lib/libbc/libc/gen/common/exportent.c (revision 5d54f3d8999eac1762fe0a8c7177d20f1f201fae)
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 *
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
79 endexportent(FILE *f)
80 {
81 	(void) fclose(f);
82 }
83 
84 
85 struct exportent *
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
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
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 *
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 *
244 skipwhite(char *str)
245 {
246 	while (*str && iswhite(*str)) {
247 		str++;
248 	}
249 	return (str);
250 }
251 
252 static char *
253 skipnonwhite(char *str)
254 {
255 	while (*str && ! iswhite(*str)) {
256 		str++;
257 	}
258 	return (str);
259 }
260