1 /* 2 * Copyright (c) 2000 Peter Edwards 3 * Copyright (c) 1988, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by Peter Edwards 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * $FreeBSD: src/usr.bin/fstat/msdosfs.c,v 1.1.2.2 2001/11/21 10:49:37 dwmalone Exp $ 33 */ 34 35 #define _KERNEL_STRUCTURES 36 37 #include <sys/param.h> 38 #include <sys/time.h> 39 #include <sys/stat.h> 40 #include <sys/vnode.h> 41 42 #include <sys/mount.h> 43 #include <vfs/msdosfs/bpb.h> 44 #include <vfs/msdosfs/msdosfsmount.h> 45 46 #include <vfs/msdosfs/denode.h> 47 #include <vfs/msdosfs/direntry.h> 48 #include <vfs/msdosfs/fat.h> 49 50 #include <err.h> 51 #include <kvm.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 55 /* 56 * XXX - 57 * VTODE is defined in denode.h only if _KERNEL is defined, but that leads to 58 * header explosion 59 */ 60 #define VTODE(vp) ((struct denode *)(vp)->v_data) 61 62 #include "fstat.h" 63 64 struct dosmount { 65 struct dosmount *next; 66 struct msdosfsmount *kptr; /* Pointer in kernel space */ 67 struct msdosfsmount data; /* User space copy of structure */ 68 }; 69 70 int 71 msdosfs_filestat(struct vnode *vp, struct filestat *fsp) 72 { 73 struct denode denode; 74 static struct dosmount *mounts; 75 struct dosmount *mnt; 76 u_long dirsperblk; 77 int fileid; 78 79 if (!kread(VTODE(vp), &denode, sizeof (denode))) { 80 dprintf(stderr, "can't read denode at %p for pid %d\n", 81 (void *)VTODE(vp), Pid); 82 return 0; 83 } 84 85 /* 86 * Find msdosfsmount structure for the vnode's filesystem. Needed 87 * for some filesystem parameters 88 */ 89 for (mnt = mounts; mnt; mnt = mnt->next) 90 if (mnt->kptr == denode.de_pmp) 91 break; 92 93 if (!mnt) { 94 if ((mnt = malloc(sizeof(struct dosmount))) == NULL) 95 err(1, NULL); 96 mnt->next = mounts; 97 mounts = mnt; 98 mnt->kptr = denode.de_pmp; 99 if (!kread(denode.de_pmp, &mnt->data, sizeof mnt->data)) { 100 dprintf(stderr, 101 "can't read mount info at %p for pid %d\n", 102 (void *)denode.de_pmp, Pid); 103 return 0; 104 } 105 } 106 107 fsp->fsid = fsp->rdev = fstat_dev2udev(denode.de_dev); 108 fsp->mode = 0555; 109 fsp->mode |= denode.de_Attributes & ATTR_READONLY ? 0 : 0222; 110 fsp->mode &= mnt->data.pm_mask; 111 112 /* Distinguish directories and files. No "special" files in FAT. */ 113 fsp->mode |= denode.de_Attributes & ATTR_DIRECTORY ? S_IFDIR : S_IFREG; 114 115 fsp->size = denode.de_FileSize; 116 117 /* 118 * XXX - 119 * Culled from msdosfs_vnops.c. There appears to be a problem 120 * here, in that a directory has the same inode number as the first 121 * file in the directory. stat(2) suffers from this problem also, so 122 * I won't try to fix it here. 123 * 124 * The following computation of the fileid must be the same as that 125 * used in msdosfs_readdir() to compute d_fileno. If not, pwd 126 * doesn't work. 127 */ 128 dirsperblk = mnt->data.pm_BytesPerSec / sizeof(struct direntry); 129 if (denode.de_Attributes & ATTR_DIRECTORY) { 130 fileid = cntobn(&mnt->data, denode.de_StartCluster) 131 * dirsperblk; 132 if (denode.de_StartCluster == MSDOSFSROOT) 133 fileid = 1; 134 } else { 135 fileid = cntobn(&mnt->data, denode.de_dirclust) * dirsperblk; 136 if (denode.de_dirclust == MSDOSFSROOT) 137 fileid = roottobn(&mnt->data, 0) * dirsperblk; 138 fileid += denode.de_diroffset / sizeof(struct direntry); 139 } 140 141 fsp->fileid = fileid; 142 return 1; 143 } 144