1/*	$NetBSD: mtab_isc3.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_isc3.c
39 *
40 */
41
42#ifdef HAVE_CONFIG_H
43# include <config.h>
44#endif /* HAVE_CONFIG_H */
45#include <am_defs.h>
46#include <amu.h>
47
48/* fd for /etc/.mnt.lock (also act as flag for: is_locked) */
49static int mtlckf = 0;
50static char mtlckname[] = "/etc/.mnt.lock";
51static char mnttabname[] = "/etc/mnttab";
52
53
54static void
55unlockmnttab(void)
56{
57  if (mtlckf) {
58    close(mtlckf);
59    mtlckf = 0;
60  }
61}
62
63
64static
65lockfile(int fd, int type)
66{
67  struct flock lk;
68
69  lk.l_type = type;
70  lk.l_whence = 0;
71  lk.l_start = 0;
72  lk.l_len = 0;
73
74  return fcntl(fd, F_SETLKW, &lk);
75}
76
77
78static
79lockmnttab(void)
80{
81  if (mtlckf == 0) {		/* need lock on /etc/.mnt.lock */
82    mtlckf = open(mtlckname, O_RDWR);
83    if (mtlckf >= 0) {
84      if (lockfile(mtlckf, F_WRLCK) < 0) {
85	close(mtlckf);
86	mtlckf = 0;
87#ifdef DEBUG
88	dlog("lock failed %m");
89#endif /* DEBUG */
90      } else {
91	return 0;
92      }
93    }
94  }
95  plog(XLOG_ERROR, "Unable to lock %s: %m", mtlckname);
96  return -1;
97}
98
99
100void
101unlock_mntlist(void)
102{
103  dlog("unlock_mntlist: releasing");
104  unlockmnttab();
105}
106
107
108/* convert from ix386 mnttab to amd mntent */
109static mntent_t *
110mnt_dup(mntent_t *mp)
111{
112  /* note: may not be null terminated */
113  mntent_t *new_mp = ALLOC(mntent_t);
114  char nullcpy[128];
115
116  xstrlcpy(nullcpy, mp->mt_dev, 32);
117  new_mp->mnt_fsname = xstrdup(nullcpy);
118
119  xstrlcpy(nullcpy, mp->mt_filsys, 32);
120  new_mp->mnt_dir = xstrdup(nullcpy);
121
122  xstrlcpy(nullcpy, mp->mt_fstyp, 16);
123  new_mp->mnt_type = xstrdup(nullcpy);
124
125  xstrlcpy(nullcpy, mp->mt_mntopts, 64);
126  new_mp->mnt_opts = xstrdup(nullcpy);
127
128  new_mp->mnt_freq = 0;
129  new_mp->mnt_passno = 0;
130
131  new_mp->mnt_time = mp->mt_time;
132  new_mp->mnt_ro = mp->mt_ro_flg;
133
134  return new_mp;
135}
136
137
138/* convert back (static alloc) */
139static mntent_t *
140mtab_of(mntent_t *mnt)
141{
142  static mntent_t mt;
143
144  xstrlcpy(mt.mt_dev, mnt->mnt_fsname, 32);
145  xstrlcpy(mt.mt_filsys, mnt->mnt_dir, 32);
146
147  mt.mt_ro_flg = mnt->mnt_ro;
148  mt.mt_time = mnt->mnt_time;
149
150  xstrlcpy(mt.mt_fstyp, mnt->mnt_type, 16);
151  xstrlcpy(mt.mt_mntopts, mnt->mnt_opts, 64);
152
153  return &mt;
154}
155
156
157/*
158 * Read a mount table into memory
159 */
160mntlist *
161read_mtab(char *fs, const char *mnttabname)
162{
163  mntlist **mpp, *mhp;
164  /* From: Piete Brooks <pb@cl.cam.ac.uk> */
165  int fd;
166  mntent_t mountbuffer[NMOUNT], *fs_data;
167  int ret;
168  int nmts;
169
170  if (lockmnttab() != 0)
171    return (mntlist *) NULL;
172
173  fd = open(mnttabname, O_RDONLY);
174  if (fd < 0) {
175    plog(XLOG_ERROR, "Can't open %s: %m", mnttabname);
176    return (mntlist *) NULL;
177  }
178  mpp = &mhp;
179  while ((ret = read(fd, (char *) mountbuffer, NMOUNT * sizeof(mntent_t))) > 0) {
180    nmts = ret / sizeof(mntent_t);
181    for (fs_data = mountbuffer; fs_data < &mountbuffer[nmts]; fs_data++) {
182      /*
183       * Allocate a new slot
184       */
185      *mpp = ALLOC(struct mntlist);
186
187      /*
188       * Copy the data returned by getmntent
189       */
190      (*mpp)->mnt = mnt_dup(fs_data);
191
192      /*
193       * Move to next pointer
194       */
195      mpp = &(*mpp)->mnext;
196    }
197  }
198  if (ret < 0) {
199    plog(XLOG_ERROR, "read error on %s: %m", mnttabname);
200    unlockmnttab();
201    mhp = (mntlist *) NULL;
202  }
203  *mpp = NULL;
204
205  close(fd);
206  return mhp;
207}
208
209
210static
211write_mntent_to_mtab(int fd, mntent_t *mnt)
212{
213  int wr;
214
215eagain:
216  wr = write(fd, (char *) mtab_of(mnt), sizeof(mntent_t));
217  if (wr < 0) {
218    switch (wr) {
219    case EAGAIN:
220      goto eagain;
221    default:
222      return -1;
223    }
224  }
225  if (wr != sizeof(mntent_t))
226      plog(XLOG_ERROR, "Can't write entry to %s: %m", mnttabname);
227  return 0;
228}
229
230
231void
232rewrite_mtab(mntlist *mp, const char *mnttabname)
233{
234  int fd;
235
236  assert(mtlckf != 0);
237
238  fd = open(mnttabname, O_RDWR | O_TRUNC);
239  if (fd < 0) {
240    plog(XLOG_ERROR, "Can't open %s: %m", mnttabname);
241    unlockmnttab();
242  }
243  while (mp) {
244    if (mp->mnt)
245      write_mntent_to_mtab(fd, mp->mnt);
246    mp = mp->mnext;
247  }
248
249  close(fd);
250  unlockmnttab();
251}
252
253
254void
255write_mntent(mntent_t *mp, const char *mnttabname)
256{
257  int fd;
258
259  if (lockmnttab() == -1)
260    return;
261
262  fd = open(mnttabname, O_RDWR | O_APPEND);
263  if (fd < 0) {
264    plog(XLOG_ERROR, "Unable to append %s: %m", mnttabname);
265    return;
266  }
267  write_mntent_to_mtab(fd, mp);
268
269  close(fd);
270  unlockmnttab();
271}
272