1 /* $NetBSD: mtab_svr4.c,v 1.1.1.3 2015/01/17 16:34:16 christos Exp $ */
2
3 /*
4 * Copyright (c) 1997-2014 Erez Zadok
5 * Copyright (c) 1990 Jan-Simon Pendry
6 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
7 * Copyright (c) 1990 The Regents of the University of California.
8 * All rights reserved.
9 *
10 * This code is derived from software contributed to Berkeley by
11 * Jan-Simon Pendry at Imperial College, London.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 *
38 * File: am-utils/conf/mtab/mtab_svr4.c
39 *
40 * How to manage the mount table file. Based on other SVR3 ports.
41 * -Erez Zadok <ezk@cs.columbia.edu>
42 */
43
44 #ifdef HAVE_CONFIG_H
45 # include <config.h>
46 #endif /* HAVE_CONFIG_H */
47 #include <am_defs.h>
48 #include <amu.h>
49
50 /*
51 * file descriptor for lock file
52 * values: -1 no file-descriptor was set yet (or mnttab unlocked, or error
53 * in locking).
54 * >=0 legal file-descriptor value (file lock succeeded)
55 */
56 static int mntent_lock_fd = -1;
57
58
59 #ifdef MOUNT_TABLE_ON_FILE
60 static char mtlckname[] = "/etc/.mnttab.lock";
61 #endif /* MOUNT_TABLE_ON_FILE */
62
63
64 /****************************************************************************/
65 /*** Private functions */
66 /****************************************************************************/
67
68 static void
unlockmnttab(void)69 unlockmnttab(void)
70 {
71 #ifdef MOUNT_TABLE_ON_FILE
72 if (mntent_lock_fd >= 0) {
73 close(mntent_lock_fd);
74 mntent_lock_fd = -1;
75 }
76 #endif /* MOUNT_TABLE_ON_FILE */
77 }
78
79
80 #ifdef MOUNT_TABLE_ON_FILE
81 static int
lockfile(int fd,int type)82 lockfile(int fd, int type)
83 {
84 struct flock lk;
85 int ret;
86
87 lk.l_type = type;
88 lk.l_whence = 0;
89 lk.l_start = 0;
90 lk.l_len = 0;
91
92 /*
93 * F_SETLKW means to block until the read or write block is free to be
94 * locked.
95 */
96 ret = fcntl(fd, F_SETLKW, &lk);
97 return ret;
98 }
99 #endif /* MOUNT_TABLE_ON_FILE */
100
101
102 /* return 0 if locking succeeded, -1 if failed */
103 static int
lockmnttab(void)104 lockmnttab(void)
105 {
106 #ifdef MOUNT_TABLE_ON_FILE
107 /* if mnttab file is locked, all is well */
108 if (mntent_lock_fd >= 0)
109 return 0;
110
111 /* need to lock mnttab file. first, open the file */
112 mntent_lock_fd = open(mtlckname, O_RDWR | O_CREAT, 0600);
113 if (mntent_lock_fd < 0) {
114 plog(XLOG_ERROR, "Unable to open/creat %s: %m", mtlckname);
115 return -1;
116 }
117
118 /* if succeeded in opening the file, try to lock it */
119 if (lockfile(mntent_lock_fd, F_WRLCK) < 0) {
120 close(mntent_lock_fd);
121 mntent_lock_fd = -1;
122 #ifdef DEBUG
123 dlog("lock %s failed: %m", mtlckname);
124 #endif /* DEBUG */
125 return -1;
126 }
127 #else /* not MOUNT_TABLE_ON_FILE */
128 /* fake lock for in-kernel mount table */
129 #endif /* not MOUNT_TABLE_ON_FILE */
130
131 /* finally, succeeded in also locking the file */
132 return 0;
133 }
134
135
136 /*
137 * Convert from solaris mnttab to Amd mntent. Since am-utils uses
138 * native "struct mnttab" if available, this really copies fields of
139 * the same structure.
140 */
141 static mntent_t *
mnt_dup(const mntent_t * mtp)142 mnt_dup(const mntent_t *mtp)
143 {
144 mntent_t *mep = ALLOC(mntent_t);
145
146 mep->mnt_fsname = xstrdup(mtp->mnt_fsname);
147 mep->mnt_dir = xstrdup(mtp->mnt_dir);
148 mep->mnt_type = xstrdup(mtp->mnt_type);
149 mep->mnt_opts = xstrdup(mtp->mnt_opts);
150 mep->mnt_time = xstrdup(mtp->mnt_time);
151
152 return mep;
153 }
154
155
156 /*
157 * Adjust arguments in mntent_t.
158 */
159 #ifdef MOUNT_TABLE_ON_FILE
160 static mntent_t *
update_mnttab_fields(const mntent_t * mnt)161 update_mnttab_fields(const mntent_t *mnt)
162 {
163 static mntent_t mt;
164 static char timestr[16];
165 struct timeval tv;
166
167 /* most fields don't change, only update mnt_time below */
168 mt.mnt_fsname = mnt->mnt_fsname;
169 mt.mnt_dir = mnt->mnt_dir;
170 mt.mnt_type = mnt->mnt_type;
171 mt.mnt_opts = mnt->mnt_opts;
172
173 /*
174 * Solaris 2.5 and newer take a second argument to gettimeofday(). If you
175 * find a useful svr4-like OS that uses the old style, and this code here
176 * fails, then create a new autoconf test that will determine the number
177 * of arguments gettimeofday() takes. -Erez.
178 */
179 if (gettimeofday(&tv, NULL) < 0)
180 timestr[0] = '\0';
181 else
182 xsnprintf(timestr, sizeof(timestr), "%ld", tv.tv_sec);
183
184 mt.mnt_time = timestr;
185
186 return &mt;
187 }
188 #endif /* MOUNT_TABLE_ON_FILE */
189
190
191 static void
write_mntent_to_mtab(FILE * fp,const mntent_t * mnt)192 write_mntent_to_mtab(FILE *fp, const mntent_t *mnt)
193 {
194 #ifdef MOUNT_TABLE_ON_FILE
195 putmntent(fp, update_mnttab_fields(mnt));
196 #endif /* MOUNT_TABLE_ON_FILE */
197 }
198
199
200 /****************************************************************************/
201 /*** Public functions */
202 /****************************************************************************/
203
204
205 void
unlock_mntlist(void)206 unlock_mntlist(void)
207 {
208 unlockmnttab();
209 }
210
211
212 /*
213 * Read a mount table into memory
214 */
215 mntlist *
read_mtab(char * fs,const char * mnttabname)216 read_mtab(char *fs, const char *mnttabname)
217 {
218 mntlist **mpp, *mhp;
219 FILE *fp;
220 mntent_t mountbuf;
221 int ret;
222
223 if (lockmnttab() < 0) /* failed locking */
224 return NULL;
225
226 fp = fopen(mnttabname, "r");
227 if (fp == NULL) {
228 plog(XLOG_ERROR, "Can't open %s: %m", mnttabname);
229 return NULL;
230 }
231 mpp = &mhp;
232
233 while ((ret = getmntent(fp, &mountbuf)) == 0) {
234 /*
235 * Allocate a new slot
236 */
237 *mpp = ALLOC(struct mntlist);
238
239 /*
240 * Copy the data returned by getmntent
241 */
242 (*mpp)->mnt = mnt_dup(&mountbuf);
243
244 /*
245 * Move to next pointer
246 */
247 mpp = &(*mpp)->mnext;
248 }
249
250 if (ret > 0) {
251 plog(XLOG_ERROR, "read error on %s: %m", mnttabname);
252 unlockmnttab();
253 mhp = NULL;
254 }
255 *mpp = NULL;
256
257 fclose(fp);
258 return mhp;
259 }
260
261
262 void
rewrite_mtab(mntlist * mp,const char * mnttabname)263 rewrite_mtab(mntlist *mp, const char *mnttabname)
264 {
265 FILE *fp;
266
267 assert(mntent_lock_fd >= 0); /* ensure lock fd is valid */
268
269 fp = fopen(mnttabname, "r+");
270 if (fp == NULL) {
271 plog(XLOG_ERROR, "Can't open %s: %m", mnttabname);
272 unlockmnttab();
273 return;
274 }
275 while (mp) {
276 if (mp->mnt)
277 write_mntent_to_mtab(fp, mp->mnt);
278 mp = mp->mnext;
279 }
280
281 ftruncate(fileno(fp), ftell(fp));
282 fclose(fp);
283 unlockmnttab();
284 }
285
286
287 void
write_mntent(mntent_t * mtp,const char * mnttabname)288 write_mntent(mntent_t *mtp, const char *mnttabname)
289 {
290 FILE *fp;
291
292 if (lockmnttab() < 0)
293 return;
294
295 fp = fopen(mnttabname, "a");
296 if (fp == NULL) {
297 plog(XLOG_ERROR, "Unable to append %s: %m", mnttabname);
298 return;
299 }
300 write_mntent_to_mtab(fp, mtp);
301
302 fclose(fp);
303 unlockmnttab();
304 }
305