1170757Sdelphij/*
2170757Sdelphij * Copyright (c) 2000 Peter Edwards
330862Sache * Copyright (c) 1988, 1993
4170757Sdelphij *	The Regents of the University of California.  All rights reserved.
530862Sache *
6170757Sdelphij * This code is derived from software contributed to Berkeley by Peter Edwards
730862Sache *
830862Sache * Redistribution and use in source and binary forms, with or without
9170757Sdelphij * modification, are permitted provided that the following conditions
10170757Sdelphij * are met:
11170757Sdelphij * 1. Redistributions of source code must retain the above copyright
1230862Sache *    notice, this list of conditions and the following disclaimer.
1330862Sache * 2. Redistributions in binary form must reproduce the above copyright
14170757Sdelphij *    notice, this list of conditions and the following disclaimer in the
15170757Sdelphij *    documentation and/or other materials provided with the distribution.
16170757Sdelphij * 3. All advertising materials mentioning features or use of this software
17170757Sdelphij *    must display the following acknowledgement:
18170757Sdelphij *	This product includes software developed by the University of
19170757Sdelphij *	California, Berkeley and its contributors.
20170757Sdelphij * 4. Neither the name of the University nor the names of its contributors
21170757Sdelphij *    may be used to endorse or promote products derived from this software
22170757Sdelphij *    without specific prior written permission.
23170757Sdelphij *
24170757Sdelphij * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25170757Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26170757Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27170757Sdelphij * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28170757Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29170757Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30170757Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31170757Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32170757Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33170757Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34170757Sdelphij * SUCH DAMAGE.
35170757Sdelphij */
36170757Sdelphij
37170757Sdelphij#include <sys/cdefs.h>
38170757Sdelphij__FBSDID("$FreeBSD$");
39170757Sdelphij
40170757Sdelphij#include <sys/param.h>
41170757Sdelphij#include <sys/time.h>
42170757Sdelphij#include <sys/stat.h>
43170757Sdelphij#include <sys/vnode.h>
44170757Sdelphij
45170757Sdelphij#include <netinet/in.h>
46170757Sdelphij
47170757Sdelphij#define	_KERNEL
48170757Sdelphij#include <sys/mount.h>
49170757Sdelphij#include <fs/msdosfs/bpb.h>
50170757Sdelphij#include <fs/msdosfs/msdosfsmount.h>
51170757Sdelphij#undef _KERNEL
52170757Sdelphij
53170757Sdelphij#include <fs/msdosfs/denode.h>
54170757Sdelphij#include <fs/msdosfs/direntry.h>
55170757Sdelphij#include <fs/msdosfs/fat.h>
56170757Sdelphij
57170757Sdelphij#include <err.h>
58170757Sdelphij#include <kvm.h>
59170757Sdelphij#include <stdio.h>
6030862Sache#include <stdlib.h>
6130862Sache
62170757Sdelphij/*
63170757Sdelphij * XXX -
6430862Sache * VTODE is defined in denode.h only if _KERNEL is defined, but that leads to
65170757Sdelphij * header explosion
66170757Sdelphij */
6730862Sache#define VTODE(vp) ((struct denode *)getvnodedata(vp))
68170757Sdelphij
69170757Sdelphij#include "libprocstat.h"
70170757Sdelphij#include "common_kvm.h"
71170757Sdelphij
72170757Sdelphijstruct dosmount {
73170757Sdelphij	struct dosmount *next;
74170757Sdelphij	struct msdosfsmount *kptr;	/* Pointer in kernel space */
75170757Sdelphij	struct msdosfsmount data;	/* User space copy of structure */
76170757Sdelphij};
77170757Sdelphij
78170757Sdelphijint
79170757Sdelphijmsdosfs_filestat(kvm_t *kd, struct vnode *vp, struct vnstat *vn)
80170757Sdelphij{
81170757Sdelphij	struct denode denode;
82170757Sdelphij	static struct dosmount *mounts;
83170757Sdelphij	struct dosmount *mnt;
84170757Sdelphij	u_long dirsperblk;
85170757Sdelphij	int fileid;
86170757Sdelphij
87170757Sdelphij	if (!kvm_read_all(kd, (unsigned long)VTODE(vp), &denode,
88170757Sdelphij	    sizeof(denode))) {
89170757Sdelphij		warnx("can't read denode at %p", (void *)VTODE(vp));
90170757Sdelphij		return (1);
91170757Sdelphij	}
92170757Sdelphij
93170757Sdelphij	/*
94170757Sdelphij	 * Find msdosfsmount structure for the vnode's filesystem. Needed
95170757Sdelphij	 * for some filesystem parameters
96170757Sdelphij	 */
97170757Sdelphij	for (mnt = mounts; mnt; mnt = mnt->next)
98170757Sdelphij		if (mnt->kptr == denode.de_pmp)
99170757Sdelphij			break;
100170757Sdelphij
101170757Sdelphij	if (!mnt) {
102170757Sdelphij		if ((mnt = malloc(sizeof(struct dosmount))) == NULL) {
103170757Sdelphij			warn("malloc()");
104170757Sdelphij			return (1);
105170757Sdelphij		}
106170757Sdelphij		if (!kvm_read_all(kd, (unsigned long)denode.de_pmp,
107170757Sdelphij		    &mnt->data, sizeof(mnt->data))) {
108170757Sdelphij			free(mnt);
109170757Sdelphij			    warnx("can't read mount info at %p",
110170757Sdelphij			    (void *)denode.de_pmp);
111170757Sdelphij			return (1);
112170757Sdelphij		}
113170757Sdelphij		mnt->next = mounts;
114170757Sdelphij		mounts = mnt;
115170757Sdelphij		mnt->kptr = denode.de_pmp;
116170757Sdelphij	}
117170757Sdelphij
118170757Sdelphij	vn->vn_fsid = dev2udev(kd, mnt->data.pm_dev);
119170757Sdelphij	vn->vn_mode = 0555;
120170757Sdelphij	vn->vn_mode |= denode.de_Attributes & ATTR_READONLY ? 0 : 0222;
121170757Sdelphij	vn->vn_mode &= mnt->data.pm_mask;
122170757Sdelphij
123170757Sdelphij	/* Distinguish directories and files. No "special" files in FAT. */
124170757Sdelphij	vn->vn_mode |= denode.de_Attributes & ATTR_DIRECTORY ? S_IFDIR : S_IFREG;
125170757Sdelphij	vn->vn_size = denode.de_FileSize;
126170757Sdelphij
127170757Sdelphij	/*
128170757Sdelphij	 * XXX -
129170757Sdelphij	 * Culled from msdosfs_vnops.c. There appears to be a problem
130170757Sdelphij	 * here, in that a directory has the same inode number as the first
131170757Sdelphij	 * file in the directory. stat(2) suffers from this problem also, so
132170757Sdelphij	 * I won't try to fix it here.
133170757Sdelphij	 *
134170757Sdelphij	 * The following computation of the fileid must be the same as that
135170757Sdelphij	 * used in msdosfs_readdir() to compute d_fileno. If not, pwd
136170757Sdelphij	 * doesn't work.
137170757Sdelphij	 */
138170757Sdelphij	dirsperblk = mnt->data.pm_BytesPerSec / sizeof(struct direntry);
139170757Sdelphij	if (denode.de_Attributes & ATTR_DIRECTORY) {
140170757Sdelphij		fileid = cntobn(&mnt->data, denode.de_StartCluster)
141170757Sdelphij		    * dirsperblk;
142170757Sdelphij		if (denode.de_StartCluster == MSDOSFSROOT)
143170757Sdelphij			fileid = 1;
144170757Sdelphij	} else {
145170757Sdelphij		fileid = cntobn(&mnt->data, denode.de_dirclust) * dirsperblk;
146170757Sdelphij		if (denode.de_dirclust == MSDOSFSROOT)
147170757Sdelphij			fileid = roottobn(&mnt->data, 0) * dirsperblk;
148170757Sdelphij		fileid += denode.de_diroffset / sizeof(struct direntry);
149170757Sdelphij	}
150170757Sdelphij
151170757Sdelphij	vn->vn_fileid = fileid;
152170757Sdelphij	return (0);
153170757Sdelphij}
154170757Sdelphij