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 */ |
51 |
static char *udf_match(am_opts *fo); |
52 |
static int udf_mount(am_node *am, mntfs *mf); |
53 |
static int udf_umount(am_node *am, mntfs *mf); |
54 |
|
55 |
/* |
56 |
* Ops structure |
57 |
*/ |
58 |
am_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) |
80 |
static int |
81 |
a_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) |
96 |
static gid_t |
97 |
a_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) |
108 |
static uid_t |
109 |
a_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 |
*/ |
122 |
static char * |
123 |
udf_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 |
|
138 |
static int |
139 |
mount_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 |
|
248 |
static int |
249 |
udf_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 |
|
265 |
static int |
266 |
udf_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 |
} |