xref: /netbsd-src/external/bsd/am-utils/dist/conf/mtab/mtab_svr4.c (revision 8bae5d409deb915cf7c8f0539fae22ff2cb8a313)
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