1221807Sstas/* 2221807Sstas * Copyright (c) 2000 Peter Edwards 3221807Sstas * Copyright (c) 1988, 1993 4221807Sstas * The Regents of the University of California. All rights reserved. 5221807Sstas * 6221807Sstas * This code is derived from software contributed to Berkeley by Peter Edwards 7221807Sstas * 8221807Sstas * Redistribution and use in source and binary forms, with or without 9221807Sstas * modification, are permitted provided that the following conditions 10221807Sstas * are met: 11221807Sstas * 1. Redistributions of source code must retain the above copyright 12221807Sstas * notice, this list of conditions and the following disclaimer. 13221807Sstas * 2. Redistributions in binary form must reproduce the above copyright 14221807Sstas * notice, this list of conditions and the following disclaimer in the 15221807Sstas * documentation and/or other materials provided with the distribution. 16221807Sstas * 3. All advertising materials mentioning features or use of this software 17221807Sstas * must display the following acknowledgement: 18221807Sstas * This product includes software developed by the University of 19221807Sstas * California, Berkeley and its contributors. 20221807Sstas * 4. Neither the name of the University nor the names of its contributors 21221807Sstas * may be used to endorse or promote products derived from this software 22221807Sstas * without specific prior written permission. 23221807Sstas * 24221807Sstas * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25221807Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26221807Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27221807Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28221807Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29221807Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30221807Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31221807Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32221807Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33221807Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34221807Sstas * SUCH DAMAGE. 35221807Sstas */ 36221807Sstas 37221807Sstas#include <sys/cdefs.h> 38221807Sstas__FBSDID("$FreeBSD$"); 39221807Sstas 40221807Sstas#include <sys/param.h> 41221807Sstas#include <sys/time.h> 42221807Sstas#include <sys/stat.h> 43221807Sstas#include <sys/vnode.h> 44221807Sstas 45221807Sstas#include <netinet/in.h> 46221807Sstas 47221807Sstas#define _KERNEL 48221807Sstas#include <sys/mount.h> 49221807Sstas#include <fs/msdosfs/bpb.h> 50221807Sstas#include <fs/msdosfs/msdosfsmount.h> 51221807Sstas#undef _KERNEL 52221807Sstas 53221807Sstas#include <fs/msdosfs/denode.h> 54221807Sstas#include <fs/msdosfs/direntry.h> 55221807Sstas#include <fs/msdosfs/fat.h> 56221807Sstas 57221807Sstas#include <err.h> 58221807Sstas#include <kvm.h> 59221807Sstas#include <stdio.h> 60221807Sstas#include <stdlib.h> 61221807Sstas 62221807Sstas/* 63221807Sstas * XXX - 64221807Sstas * VTODE is defined in denode.h only if _KERNEL is defined, but that leads to 65221807Sstas * header explosion 66221807Sstas */ 67221807Sstas#define VTODE(vp) ((struct denode *)getvnodedata(vp)) 68221807Sstas 69221807Sstas#include "libprocstat.h" 70221807Sstas#include "common_kvm.h" 71221807Sstas 72221807Sstasstruct dosmount { 73221807Sstas struct dosmount *next; 74221807Sstas struct msdosfsmount *kptr; /* Pointer in kernel space */ 75221807Sstas struct msdosfsmount data; /* User space copy of structure */ 76221807Sstas}; 77221807Sstas 78221807Sstasint 79221807Sstasmsdosfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn) 80221807Sstas{ 81221807Sstas struct denode denode; 82221807Sstas static struct dosmount *mounts; 83221807Sstas struct dosmount *mnt; 84221807Sstas u_long dirsperblk; 85221807Sstas int fileid; 86221807Sstas 87221807Sstas if (!kvm_read_all(kd, (unsigned long)VTODE(vp), &denode, 88221807Sstas sizeof(denode))) { 89221807Sstas warnx("can't read denode at %p", (void *)VTODE(vp)); 90221807Sstas return (1); 91221807Sstas } 92221807Sstas 93221807Sstas /* 94221807Sstas * Find msdosfsmount structure for the vnode's filesystem. Needed 95221807Sstas * for some filesystem parameters 96221807Sstas */ 97221807Sstas for (mnt = mounts; mnt; mnt = mnt->next) 98221807Sstas if (mnt->kptr == denode.de_pmp) 99221807Sstas break; 100221807Sstas 101221807Sstas if (!mnt) { 102221807Sstas if ((mnt = malloc(sizeof(struct dosmount))) == NULL) { 103221807Sstas warn("malloc()"); 104221807Sstas return (1); 105221807Sstas } 106221807Sstas if (!kvm_read_all(kd, (unsigned long)denode.de_pmp, 107221807Sstas &mnt->data, sizeof(mnt->data))) { 108221807Sstas free(mnt); 109221807Sstas warnx("can't read mount info at %p", 110221807Sstas (void *)denode.de_pmp); 111221807Sstas return (1); 112221807Sstas } 113221807Sstas mnt->next = mounts; 114221807Sstas mounts = mnt; 115221807Sstas mnt->kptr = denode.de_pmp; 116221807Sstas } 117221807Sstas 118221807Sstas vn->vn_fsid = dev2udev(kd, mnt->data.pm_dev); 119221807Sstas vn->vn_mode = 0555; 120221807Sstas vn->vn_mode |= denode.de_Attributes & ATTR_READONLY ? 0 : 0222; 121221807Sstas vn->vn_mode &= mnt->data.pm_mask; 122221807Sstas 123221807Sstas /* Distinguish directories and files. No "special" files in FAT. */ 124221807Sstas vn->vn_mode |= denode.de_Attributes & ATTR_DIRECTORY ? S_IFDIR : S_IFREG; 125221807Sstas vn->vn_size = denode.de_FileSize; 126221807Sstas 127221807Sstas /* 128221807Sstas * XXX - 129221807Sstas * Culled from msdosfs_vnops.c. There appears to be a problem 130221807Sstas * here, in that a directory has the same inode number as the first 131221807Sstas * file in the directory. stat(2) suffers from this problem also, so 132221807Sstas * I won't try to fix it here. 133221807Sstas * 134221807Sstas * The following computation of the fileid must be the same as that 135221807Sstas * used in msdosfs_readdir() to compute d_fileno. If not, pwd 136221807Sstas * doesn't work. 137221807Sstas */ 138221807Sstas dirsperblk = mnt->data.pm_BytesPerSec / sizeof(struct direntry); 139221807Sstas if (denode.de_Attributes & ATTR_DIRECTORY) { 140221807Sstas fileid = cntobn(&mnt->data, denode.de_StartCluster) 141221807Sstas * dirsperblk; 142221807Sstas if (denode.de_StartCluster == MSDOSFSROOT) 143221807Sstas fileid = 1; 144221807Sstas } else { 145221807Sstas fileid = cntobn(&mnt->data, denode.de_dirclust) * dirsperblk; 146221807Sstas if (denode.de_dirclust == MSDOSFSROOT) 147221807Sstas fileid = roottobn(&mnt->data, 0) * dirsperblk; 148221807Sstas fileid += denode.de_diroffset / sizeof(struct direntry); 149221807Sstas } 150221807Sstas 151221807Sstas vn->vn_fileid = fileid; 152221807Sstas return (0); 153221807Sstas} 154