2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "@(#)pc_vfsops.c 1.104 07/10/25 SMI"
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/kmem.h>
31 #include <sys/user.h>
32 #include <sys/proc.h>
33 #include <sys/cred.h>
34 #include <sys/disp.h>
35 #include <sys/buf.h>
36 #include <sys/vfs.h>
37 #include <sys/vfs_opreg.h>
38 #include <sys/vnode.h>
39 #include <sys/fdio.h>
40 #include <sys/file.h>
41 #include <sys/uio.h>
42 #include <sys/conf.h>
43 #include <sys/statvfs.h>
44 #include <sys/mount.h>
45 #include <sys/pathname.h>
46 #include <sys/cmn_err.h>
276
277 extern struct pcfs_args pc_tz;
278
279 /*
280 * Define some special logical drives we use internal to this file.
281 */
282 #define BOOT_PARTITION_DRIVE 99
283 #define PRIMARY_DOS_DRIVE 1
284 #define UNPARTITIONED_DRIVE 0
285
286 static int
287 pcfs_device_identify(
288 struct vfs *vfsp,
289 struct mounta *uap,
290 struct cred *cr,
291 int *dos_ldrive,
292 dev_t *xdev)
293 {
294 struct pathname special;
295 char *c;
296 struct vnode *bvp;
297 int oflag, aflag;
298 int error;
299
300 /*
301 * Resolve path name of special file being mounted.
302 */
303 if (error = pn_get(uap->spec, UIO_USERSPACE, &special)) {
304 return (error);
305 }
306
307 *dos_ldrive = -1;
308
309 if (error =
310 lookupname(special.pn_path, UIO_SYSSPACE, FOLLOW, NULLVPP, &bvp)) {
311 /*
312 * If there's no device node, the name specified most likely
313 * maps to a PCFS-style "partition specifier" to select a
314 * harddisk primary/logical partition. Disable floppy-specific
315 * checks in such cases unless an explicit :A or :B is
316 * requested.
317 */
318
319 /*
320 * Split the pathname string at the last ':' separator.
321 * If there's no ':' in the device name, or the ':' is the
322 * last character in the string, the name is invalid and
323 * the error from the previous lookup will be returned.
324 */
325 c = strrchr(special.pn_path, ':');
326 if (c == NULL || strlen(c) == 0)
327 goto devlookup_done;
328
329 *c++ = '\0';
330
367 * PCMCIA pseudofloppy (sram card).
368 */
369 *c = tolower(*c);
370 if (*c == 'a' || *c == 'b') {
371 *dos_ldrive = UNPARTITIONED_DRIVE;
372 } else if (*c < 'c' || *c > 'z') {
373 error = ENXIO;
374 goto devlookup_done;
375 } else {
376 *dos_ldrive = 1 + *c - 'c';
377 }
378 } else {
379 /*
380 * Can't parse this - pass through previous error.
381 */
382 goto devlookup_done;
383 }
384
385
386 error = lookupname(special.pn_path, UIO_SYSSPACE, FOLLOW,
387 NULLVPP, &bvp);
388 } else {
389 *dos_ldrive = UNPARTITIONED_DRIVE;
390 }
391 devlookup_done:
392 pn_free(&special);
393 if (error)
394 return (error);
395
396 ASSERT(*dos_ldrive >= UNPARTITIONED_DRIVE);
397
398 *xdev = bvp->v_rdev;
399
400 /*
401 * Verify caller's permission to open the device special file.
402 */
403 if ((vfsp->vfs_flag & VFS_RDONLY) != 0 ||
404 ((uap->flags & MS_RDONLY) != 0)) {
405 oflag = FREAD;
406 aflag = VREAD;
407 } else {
408 oflag = FREAD | FWRITE;
409 aflag = VREAD | VWRITE;
410 }
411
412 if (bvp->v_type != VBLK)
413 error = ENOTBLK;
414 else if (getmajor(*xdev) >= devcnt)
415 error = ENXIO;
416
417 if ((error != 0) ||
418 (error = VOP_ACCESS(bvp, aflag, 0, cr, NULL)) != 0 ||
419 (error = secpolicy_spec_open(cr, bvp, oflag)) != 0) {
420 VN_RELE(bvp);
421 return (error);
422 }
423
424 VN_RELE(bvp);
425 return (0);
426 }
427
428 static int
429 pcfs_device_ismounted(
430 struct vfs *vfsp,
431 int dos_ldrive,
432 dev_t xdev,
433 int *remounting,
434 dev_t *pseudodev)
435 {
436 struct pcfs *fsp;
437 int remount = *remounting;
438
439 /*
440 * Ensure that this logical drive isn't already mounted, unless
441 * this is a REMOUNT request.
442 * Note: The framework will perform this check if the "...:c"
443 * PCFS-style "logical drive" syntax has not been used and an
444 * actually existing physical device is backing this filesystem.
445 * Once all block device drivers support PC-style partitioning,
|
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "@(#)pc_vfsops.c 1.105 08/05/07 SMI"
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/kmem.h>
31 #include <sys/user.h>
32 #include <sys/proc.h>
33 #include <sys/cred.h>
34 #include <sys/disp.h>
35 #include <sys/buf.h>
36 #include <sys/vfs.h>
37 #include <sys/vfs_opreg.h>
38 #include <sys/vnode.h>
39 #include <sys/fdio.h>
40 #include <sys/file.h>
41 #include <sys/uio.h>
42 #include <sys/conf.h>
43 #include <sys/statvfs.h>
44 #include <sys/mount.h>
45 #include <sys/pathname.h>
46 #include <sys/cmn_err.h>
276
277 extern struct pcfs_args pc_tz;
278
279 /*
280 * Define some special logical drives we use internal to this file.
281 */
282 #define BOOT_PARTITION_DRIVE 99
283 #define PRIMARY_DOS_DRIVE 1
284 #define UNPARTITIONED_DRIVE 0
285
286 static int
287 pcfs_device_identify(
288 struct vfs *vfsp,
289 struct mounta *uap,
290 struct cred *cr,
291 int *dos_ldrive,
292 dev_t *xdev)
293 {
294 struct pathname special;
295 char *c;
296 struct vnode *svp = NULL;
297 struct vnode *lvp = NULL;
298 int oflag, aflag;
299 int error;
300
301 /*
302 * Resolve path name of special file being mounted.
303 */
304 if (error = pn_get(uap->spec, UIO_USERSPACE, &special)) {
305 return (error);
306 }
307
308 *dos_ldrive = -1;
309
310 if (error =
311 lookupname(special.pn_path, UIO_SYSSPACE, FOLLOW, NULLVPP, &svp)) {
312 /*
313 * If there's no device node, the name specified most likely
314 * maps to a PCFS-style "partition specifier" to select a
315 * harddisk primary/logical partition. Disable floppy-specific
316 * checks in such cases unless an explicit :A or :B is
317 * requested.
318 */
319
320 /*
321 * Split the pathname string at the last ':' separator.
322 * If there's no ':' in the device name, or the ':' is the
323 * last character in the string, the name is invalid and
324 * the error from the previous lookup will be returned.
325 */
326 c = strrchr(special.pn_path, ':');
327 if (c == NULL || strlen(c) == 0)
328 goto devlookup_done;
329
330 *c++ = '\0';
331
368 * PCMCIA pseudofloppy (sram card).
369 */
370 *c = tolower(*c);
371 if (*c == 'a' || *c == 'b') {
372 *dos_ldrive = UNPARTITIONED_DRIVE;
373 } else if (*c < 'c' || *c > 'z') {
374 error = ENXIO;
375 goto devlookup_done;
376 } else {
377 *dos_ldrive = 1 + *c - 'c';
378 }
379 } else {
380 /*
381 * Can't parse this - pass through previous error.
382 */
383 goto devlookup_done;
384 }
385
386
387 error = lookupname(special.pn_path, UIO_SYSSPACE, FOLLOW,
388 NULLVPP, &svp);
389 } else {
390 *dos_ldrive = UNPARTITIONED_DRIVE;
391 }
392 devlookup_done:
393 pn_free(&special);
394 if (error)
395 return (error);
396
397 ASSERT(*dos_ldrive >= UNPARTITIONED_DRIVE);
398
399 /*
400 * Verify caller's permission to open the device special file.
401 */
402 if ((vfsp->vfs_flag & VFS_RDONLY) != 0 ||
403 ((uap->flags & MS_RDONLY) != 0)) {
404 oflag = FREAD;
405 aflag = VREAD;
406 } else {
407 oflag = FREAD | FWRITE;
408 aflag = VREAD | VWRITE;
409 }
410
411 error = vfs_get_lofi(vfsp, &lvp);
412
413 if (error > 0) {
414 if (error == ENOENT)
415 error = ENODEV;
416 goto out;
417 } else if (error == 0) {
418 *xdev = lvp->v_rdev;
419 } else {
420 *xdev = svp->v_rdev;
421
422 if (svp->v_type != VBLK)
423 error = ENOTBLK;
424
425 if ((error = secpolicy_spec_open(cr, svp, oflag)) != 0)
426 goto out;
427 }
428
429 if (getmajor(*xdev) >= devcnt) {
430 error = ENXIO;
431 goto out;
432 }
433
434 if ((error = VOP_ACCESS(svp, aflag, 0, cr, NULL)) != 0)
435 goto out;
436
437 out:
438 if (svp != NULL)
439 VN_RELE(svp);
440 if (lvp != NULL)
441 VN_RELE(lvp);
442 return (error);
443 }
444
445 static int
446 pcfs_device_ismounted(
447 struct vfs *vfsp,
448 int dos_ldrive,
449 dev_t xdev,
450 int *remounting,
451 dev_t *pseudodev)
452 {
453 struct pcfs *fsp;
454 int remount = *remounting;
455
456 /*
457 * Ensure that this logical drive isn't already mounted, unless
458 * this is a REMOUNT request.
459 * Note: The framework will perform this check if the "...:c"
460 * PCFS-style "logical drive" syntax has not been used and an
461 * actually existing physical device is backing this filesystem.
462 * Once all block device drivers support PC-style partitioning,
|