ops_udf.c revision 310490
1/*
2 * Copyright (c) 1997-2014 Erez Zadok
3 * Copyright (c) 1990 Jan-Simon Pendry
4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1990 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 *
36 * File: am-utils/amd/ops_udf.c
37 *
38 */
39
40/*
41 * UDF file system
42 */
43
44#ifdef HAVE_CONFIG_H
45# include <config.h>
46#endif /* HAVE_CONFIG_H */
47#include <am_defs.h>
48#include <amd.h>
49
50/* forward definitions */
51static char *udf_match(am_opts *fo);
52static int udf_mount(am_node *am, mntfs *mf);
53static int udf_umount(am_node *am, mntfs *mf);
54
55/*
56 * Ops structure
57 */
58am_ops udf_ops =
59{
60	"udf",
61	udf_match,
62	0,				/* udf_init */
63	udf_mount,
64	udf_umount,
65	amfs_error_lookup_child,
66	amfs_error_mount_child,
67	amfs_error_readdir,
68	0,				/* udf_readlink */
69	0,				/* udf_mounted */
70	0,				/* udf_umounted */
71	amfs_generic_find_srvr,
72	0,				/* udf_get_wchan */
73	FS_MKMNT | FS_UBACKGROUND | FS_AMQINFO,	/* nfs_fs_flags */
74#ifdef HAVE_FS_AUTOFS
75	AUTOFS_UDF_FS_FLAGS,
76#endif /* HAVE_FS_AUTOFS */
77};
78
79#if defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_NOBODY_UID)
80static int
81a_num(const char *s, const char *id_type)
82{
83	int id;
84	char *ep;
85
86	id = strtol(s, &ep, 0);
87	if (*ep || s == ep || id < 0) {
88		plog(XLOG_ERROR, "mount_udf: unknown %s: %s", id_type, s);
89		return 0;
90	}
91	return id;
92}
93#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_NOBODY_UID) */
94
95#if defined(HAVE_UDF_ARGS_T_NOBODY_GID)
96static gid_t
97a_gid(const char *s, const char *id_type)
98{
99	struct group *gr;
100
101	if ((gr = getgrnam(s)) != NULL)
102		return gr->gr_gid;
103	return a_num(s, id_type);
104}
105#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) */
106
107#if defined(HAVE_UDF_ARGS_T_NOBODY_UID)
108static uid_t
109a_uid(const char *s, const char *id_type)
110{
111	struct passwd *pw;
112
113	if ((pw = getpwnam(s)) != NULL)
114		return pw->pw_uid;
115	return a_num(s, id_type);
116}
117#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) */
118
119/*
120 * UDF needs remote filesystem.
121 */
122static char *
123udf_match(am_opts *fo)
124{
125
126	if (!fo->opt_dev) {
127		plog(XLOG_USER, "udf: no source device specified");
128		return 0;
129	}
130	dlog("UDF: mounting device \"%s\" on \"%s\"", fo->opt_dev, fo->opt_fs);
131
132	/*
133	 * Determine magic cookie to put in mtab
134	 */
135	return xstrdup(fo->opt_dev);
136}
137
138static int
139mount_udf(char *mntdir, char *fs_name, char *opts, int on_autofs)
140{
141	udf_args_t udf_args;
142	mntent_t mnt;
143	int flags;
144	char *str;
145#if defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID)
146	uid_t uid_nobody;
147	gid_t gid_nobody;
148#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) */
149	/*
150	 * Figure out the name of the file system type.
151	 */
152	MTYPE_TYPE type = MOUNT_TYPE_UDF;
153
154#if defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID)
155	uid_nobody = a_uid("nobody", "user");
156	if (uid_nobody == 0) {
157		plog(XLOG_ERROR, "mount_udf: invalid uid for nobody");
158		return EPERM;
159	}
160#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_UID) || defined(HAVE_UDF_ARGS_T_ANON_UID) */
161
162#if defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_ANON_GID)
163	gid_nobody = a_gid("nobody", "group");
164	if (gid_nobody == 0) {
165		plog(XLOG_ERROR, "mount_udf: invalid gid for nobody");
166		return EPERM;
167	}
168#endif /* defined(HAVE_UDF_ARGS_T_NOBODY_GID) || defined(HAVE_UDF_ARGS_T_ANON_GID) */
169
170	str = NULL;
171	memset((voidp) &udf_args, 0, sizeof(udf_args)); /* Paranoid */
172
173	/*
174	 * Fill in the mount structure
175	 */
176	memset((voidp)&mnt, 0, sizeof(mnt));
177	mnt.mnt_dir = mntdir;
178	mnt.mnt_fsname = fs_name;
179	mnt.mnt_type = MNTTAB_TYPE_UDF;
180	mnt.mnt_opts = opts;
181
182	flags = compute_mount_flags(&mnt);
183
184#ifdef HAVE_UDF_ARGS_T_UDFMFLAGS
185# if defined(MNT2_UDF_OPT_CLOSESESSION) && defined(MNTTAB_OPT_CLOSESESSION)
186	if (amu_hasmntopt(&mnt, MNTTAB_OPT_CLOSESESSION))
187		udf_args.udfmflags |= MNT2_UDF_OPT_CLOSESESSION;
188# endif /* defined(MNT2_UDF_OPT_CLOSESESSION) && defined(MNTTAB_OPT_CLOSESESSION) */
189#endif /* HAVE_UDF_ARGS_T_UDFMFLAGS */
190
191#ifdef HAVE_UDF_ARGS_T_NOBODY_UID
192	udf_args.nobody_uid = uid_nobody;
193#endif /* HAVE_UDF_ARGS_T_NOBODY_UID */
194
195#ifdef HAVE_UDF_ARGS_T_NOBODY_GID
196	udf_args.nobody_gid = gid_nobody;
197#endif /* HAVE_UDF_ARGS_T_NOBODY_GID */
198
199#ifdef HAVE_UDF_ARGS_T_ANON_UID
200	udf_args.anon_uid = uid_nobody;	/* default to nobody */
201	if ((str = hasmntstr(&mnt, MNTTAB_OPT_USER)) != NULL) {
202		udf_args.anon_uid = a_uid(str, MNTTAB_OPT_USER);
203		XFREE(str);
204	}
205#endif /* HAVE_UDF_ARGS_T_ANON_UID */
206
207#ifdef HAVE_UDF_ARGS_T_ANON_GID
208	udf_args.anon_gid = gid_nobody;	/* default to nobody */
209	if ((str = hasmntstr(&mnt, MNTTAB_OPT_GROUP)) != NULL) {
210		udf_args.anon_gid = a_gid(str, MNTTAB_OPT_GROUP);
211		XFREE(str);
212	}
213#endif /* HAVE_UDF_ARGS_T_ANON_GID */
214
215#ifdef HAVE_UDF_ARGS_T_GMTOFF
216	udf_args.gmtoff = 0;
217	if ((str = hasmntstr(&mnt, MNTTAB_OPT_GMTOFF)) != NULL) {
218		udf_args.gmtoff = a_num(str, MNTTAB_OPT_GMTOFF);
219		XFREE(str);
220	}
221#endif /* HAVE_UDF_ARGS_T_GMTOFF */
222
223#ifdef HAVE_UDF_ARGS_T_SESSIONNR
224	udf_args.sessionnr = 0;
225	if ((str = hasmntstr(&mnt, MNTTAB_OPT_SESSIONNR)) != NULL) {
226		udf_args.sessionnr = a_num(str, MNTTAB_OPT_SESSIONNR);
227		XFREE(str);
228	}
229#endif /* HAVE_UDF_ARGS_T_SESSIONNR */
230
231#ifdef HAVE_UDF_ARGS_T_VERSION
232# ifdef UDFMNT_VERSION
233	udf_args.version = UDFMNT_VERSION;
234# endif /* UDFMNT_VERSION */
235#endif /* HAVE_UDF_ARGS_T_VERSION */
236
237#ifdef HAVE_UDF_ARGS_T_FSPEC
238	udf_args.fspec = fs_name;
239#endif /* HAVE_UFS_ARGS_T_FSPEC */
240
241	/*
242	 * Call generic mount routine
243	 */
244	return mount_fs(&mnt, flags, (caddr_t)&udf_args, 0, type, 0, NULL,
245	    mnttab_file_name, on_autofs);
246}
247
248static int
249udf_mount(am_node *am, mntfs *mf)
250{
251	int on_autofs;
252	int error;
253
254	on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
255	error = mount_udf(mf->mf_mount, mf->mf_info, mf->mf_mopts, on_autofs);
256	if (error) {
257		errno = error;
258		plog(XLOG_ERROR, "mount_udf: %m");
259		return error;
260	}
261	return 0;
262}
263
264
265static int
266udf_umount(am_node *am, mntfs *mf)
267{
268	int unmount_flags;
269
270	unmount_flags = (mf->mf_flags & MFF_ON_AUTOFS) ? AMU_UMOUNT_AUTOFS : 0;
271	return UMOUNT_FS(mf->mf_mount, mnttab_file_name, unmount_flags);
272}
273