Deleted Added
full compact
1/* $Id: msdosfs_vnops.c,v 1.24 1995/10/07 10:14:12 bde Exp $ */
1/* $Id: msdosfs_vnops.c,v 1.25 1995/10/22 09:32:37 davidg Exp $ */
2/* $NetBSD: msdosfs_vnops.c,v 1.20 1994/08/21 18:44:13 ws Exp $ */
3
4/*-
5 * Copyright (C) 1994 Wolfgang Solfrank.
6 * Copyright (C) 1994 TooLs GmbH.
7 * All rights reserved.
8 * Original code by Paul Popelka (paulp@uts.amdahl.com) (see below).
9 *

--- 56 unchanged lines hidden (view full) ---

66
67#include <vm/vm.h>
68
69#include <msdosfs/bpb.h>
70#include <msdosfs/direntry.h>
71#include <msdosfs/denode.h>
72#include <msdosfs/msdosfsmount.h>
73#include <msdosfs/fat.h>
74
75/*
76 * Prototypes for MSDOSFS vnode operations
77 */
78static int msdosfs_create __P((struct vop_create_args *));
79static int msdosfs_mknod __P((struct vop_mknod_args *));
80static int msdosfs_open __P((struct vop_open_args *));
81static int msdosfs_close __P((struct vop_close_args *));
82static int msdosfs_access __P((struct vop_access_args *));
83static int msdosfs_getattr __P((struct vop_getattr_args *));
84static int msdosfs_setattr __P((struct vop_setattr_args *));
85static int msdosfs_read __P((struct vop_read_args *));
86static int msdosfs_write __P((struct vop_write_args *));
87static int msdosfs_ioctl __P((struct vop_ioctl_args *));
88static int msdosfs_select __P((struct vop_select_args *));
89static int msdosfs_mmap __P((struct vop_mmap_args *));
90static int msdosfs_fsync __P((struct vop_fsync_args *));
91static int msdosfs_seek __P((struct vop_seek_args *));
92static int msdosfs_remove __P((struct vop_remove_args *));
93static int msdosfs_link __P((struct vop_link_args *));
94static int msdosfs_rename __P((struct vop_rename_args *));
95static int msdosfs_mkdir __P((struct vop_mkdir_args *));
96static int msdosfs_rmdir __P((struct vop_rmdir_args *));
97static int msdosfs_symlink __P((struct vop_symlink_args *));
98static int msdosfs_readdir __P((struct vop_readdir_args *));
99static int msdosfs_readlink __P((struct vop_readlink_args *));
100static int msdosfs_abortop __P((struct vop_abortop_args *));
101static int msdosfs_lock __P((struct vop_lock_args *));
102static int msdosfs_unlock __P((struct vop_unlock_args *));
103static int msdosfs_bmap __P((struct vop_bmap_args *));
104static int msdosfs_strategy __P((struct vop_strategy_args *));
105static int msdosfs_print __P((struct vop_print_args *));
106static int msdosfs_islocked __P((struct vop_islocked_args *));
107static int msdosfs_advlock __P((struct vop_advlock_args *));
108static int msdosfs_reallocblks __P((struct vop_reallocblks_args *));
109
110/*
111 * Some general notes:
112 *
113 * In the ufs filesystem the inodes, superblocks, and indirect blocks are
114 * read/written using the vnode for the filesystem. Blocks that represent
115 * the contents of a file are read/written using the vnode for the file
116 * (including directories when they are read/written as files). This
117 * presents problems for the dos filesystem because data that should be in
118 * an inode (if dos had them) resides in the directory itself. Since we

--- 7 unchanged lines hidden (view full) ---

126 */
127
128/*
129 * Create a regular file. On entry the directory to contain the file being
130 * created is locked. We must release before we return. We must also free
131 * the pathname buffer pointed at by cnp->cn_pnbuf, always on error, or
132 * only if the SAVESTART bit in cn_flags is clear on success.
133 */
98int
134static int
135msdosfs_create(ap)
136 struct vop_create_args /* {
137 struct vnode *a_dvp;
138 struct vnode **a_vpp;
139 struct componentname *a_cnp;
140 struct vattr *a_vap;
141 } */ *ap;
142{

--- 34 unchanged lines hidden (view full) ---

177 free(cnp->cn_pnbuf, M_NAMEI);
178 } else {
179 free(cnp->cn_pnbuf, M_NAMEI);
180 }
181 vput(ap->a_dvp); /* release parent dir */
182 return error;
183}
184
149int
185static int
186msdosfs_mknod(ap)
187 struct vop_mknod_args /* {
188 struct vnode *a_dvp;
189 struct vnode **a_vpp;
190 struct componentname *a_cnp;
191 struct vattr *a_vap;
192 } */ *ap;
193{

--- 12 unchanged lines hidden (view full) ---

206 error = EINVAL;
207 free(ap->a_cnp->cn_pnbuf, M_NAMEI);
208 vput(ap->a_dvp);
209 break;
210 }
211 return error;
212}
213
178int
214static int
215msdosfs_open(ap)
216 struct vop_open_args /* {
217 struct vnode *a_vp;
218 int a_mode;
219 struct ucred *a_cred;
220 struct proc *a_p;
221 } */ *ap;
222{
223 return 0;
224}
225
190int
226static int
227msdosfs_close(ap)
228 struct vop_close_args /* {
229 struct vnode *a_vp;
230 int a_fflag;
231 struct ucred *a_cred;
232 struct proc *a_p;
233 } */ *ap;
234{
235 struct vnode *vp = ap->a_vp;
236 struct denode *dep = VTODE(vp);
237
238 if (vp->v_usecount > 1 && !(dep->de_flag & DE_LOCKED))
239 DE_TIMES(dep, &time);
240 return 0;
241}
242
207int
243static int
244msdosfs_access(ap)
245 struct vop_access_args /* {
246 struct vnode *a_vp;
247 int a_mode;
248 struct ucred *a_cred;
249 struct proc *a_p;
250 } */ *ap;
251{

--- 59 unchanged lines hidden (view full) ---

311 mask |= S_IXOTH;
312 if (mode & VREAD)
313 mask |= S_IROTH;
314 if (mode & VWRITE)
315 mask |= S_IWOTH;
316 return (file_mode & mask) == mask ? 0 : EACCES;
317}
318
283int
319static int
320msdosfs_getattr(ap)
321 struct vop_getattr_args /* {
322 struct vnode *a_vp;
323 struct vattr *a_vap;
324 struct ucred *a_cred;
325 struct proc *a_p;
326 } */ *ap;
327{

--- 41 unchanged lines hidden (view full) ---

369 vap->va_blocksize = dep->de_pmp->pm_bpcluster;
370 vap->va_bytes = (dep->de_FileSize + dep->de_pmp->pm_crbomask) &
371 ~(dep->de_pmp->pm_crbomask);
372 vap->va_type = ap->a_vp->v_type;
373 vap->va_filerev = dep->de_modrev;
374 return 0;
375}
376
341int
377static int
378msdosfs_setattr(ap)
379 struct vop_setattr_args /* {
380 struct vnode *a_vp;
381 struct vattr *a_vap;
382 struct ucred *a_cred;
383 struct proc *a_p;
384 } */ *ap;
385{

--- 107 unchanged lines hidden (view full) ---

493 dep->de_Attributes &= ~ATTR_READONLY;
494 else
495 dep->de_Attributes |= ATTR_READONLY;
496 dep->de_flag |= DE_MODIFIED;
497 }
498 return error;
499}
500
465int
501static int
502msdosfs_read(ap)
503 struct vop_read_args /* {
504 struct vnode *a_vp;
505 struct uio *a_uio;
506 int a_ioflag;
507 struct ucred *a_cred;
508 } */ *ap;
509{

--- 76 unchanged lines hidden (view full) ---

586 brelse(bp);
587 } while (error == 0 && uio->uio_resid > 0 && n != 0);
588 return error;
589}
590
591/*
592 * Write data to a file or directory.
593 */
558int
594static int
595msdosfs_write(ap)
596 struct vop_write_args /* {
597 struct vnode *a_vp;
598 struct uio *a_uio;
599 int a_ioflag;
600 struct ucred *a_cred;
601 } */ *ap;
602{

--- 197 unchanged lines hidden (view full) ---

800 }
801 } else {
802 TIMEVAL_TO_TIMESPEC(&time, &ts);
803 error = deupdat(dep, &ts, 1);
804 }
805 return error;
806}
807
772int
808static int
809msdosfs_ioctl(ap)
810 struct vop_ioctl_args /* {
811 struct vnode *a_vp;
812 int a_command;
813 caddr_t a_data;
814 int a_fflag;
815 struct ucred *a_cred;
816 struct proc *a_p;
817 } */ *ap;
818{
819 return ENOTTY;
820}
821
786int
822static int
823msdosfs_select(ap)
824 struct vop_select_args /* {
825 struct vnode *a_vp;
826 int a_which;
827 int a_fflags;
828 struct ucred *a_cred;
829 struct proc *a_p;
830 } */ *ap;
831{
832 return 1; /* DOS filesystems never block? */
833}
834
799int
835static int
836msdosfs_mmap(ap)
837 struct vop_mmap_args /* {
838 struct vnode *a_vp;
839 int a_fflags;
840 struct ucred *a_cred;
841 struct proc *a_p;
842 } */ *ap;
843{
844 return EINVAL;
845}
846
847/*
848 * Flush the blocks of a file to disk.
849 *
850 * This function is worthless for vnodes that represent directories. Maybe we
851 * could just do a sync if they try an fsync on a directory file.
852 */
817int
853static int
854msdosfs_fsync(ap)
855 struct vop_fsync_args /* {
856 struct vnode *a_vp;
857 struct ucred *a_cred;
858 int a_waitfor;
859 struct proc *a_p;
860 } */ *ap;
861{

--- 35 unchanged lines hidden (view full) ---

897 TIMEVAL_TO_TIMESPEC(&time, &ts);
898 return deupdat(VTODE(vp), &ts, wait);
899}
900
901/*
902 * Now the whole work of extending a file is done in the write function.
903 * So nothing to do here.
904 */
869int
905static int
906msdosfs_seek(ap)
907 struct vop_seek_args /* {
908 struct vnode *a_vp;
909 off_t a_oldoff;
910 off_t a_newoff;
911 struct ucred *a_cred;
912 } */ *ap;
913{
914 return 0;
915}
916
881int
917static int
918msdosfs_remove(ap)
919 struct vop_remove_args /* {
920 struct vnode *a_dvp;
921 struct vnode *a_vp;
922 struct componentname *a_cnp;
923 } */ *ap;
924{
925 int error;

--- 13 unchanged lines hidden (view full) ---

939 return error;
940}
941
942/*
943 * DOS filesystems don't know what links are. But since we already called
944 * msdosfs_lookup() with create and lockparent, the parent is locked so we
945 * have to free it before we return the error.
946 */
911int
947static int
948msdosfs_link(ap)
949 struct vop_link_args /* {
950 struct vnode *a_tdvp;
951 struct vnode *a_vp;
952 struct componentname *a_cnp;
953 } */ *ap;
954{
955 VOP_ABORTOP(ap->a_tdvp, ap->a_cnp);

--- 47 unchanged lines hidden (view full) ---

1003 * On exit:
1004 * all denodes should be released
1005 *
1006 * Notes:
1007 * I'm not sure how the memory containing the pathnames pointed at by the
1008 * componentname structures is freed, there may be some memory bleeding
1009 * for each rename done.
1010 */
975int
1011static int
1012msdosfs_rename(ap)
1013 struct vop_rename_args /* {
1014 struct vnode *a_fdvp;
1015 struct vnode *a_fvp;
1016 struct componentname *a_fcnp;
1017 struct vnode *a_tdvp;
1018 struct vnode *a_tvp;
1019 struct componentname *a_tcnp;

--- 238 unchanged lines hidden (view full) ---

1258 vrele(DETOV(fddep));
1259 if (tdep)
1260 vput(DETOV(tdep));
1261 if (tddep)
1262 vput(DETOV(tddep));
1263 return error;
1264}
1265
1230struct {
1266static struct {
1267 struct direntry dot;
1268 struct direntry dotdot;
1269} dosdirtemplate = {
1270 {
1271 ". ", " ", /* the . entry */
1272 ATTR_DIRECTORY, /* file attribute */
1273 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* resevered */
1274 {210, 4}, {210, 4}, /* time and date */

--- 4 unchanged lines hidden (view full) ---

1279 ATTR_DIRECTORY, /* file attribute */
1280 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* resevered */
1281 {210, 4}, {210, 4}, /* time and date */
1282 {0, 0}, /* startcluster */
1283 {0, 0, 0, 0}, /* filesize */
1284 }
1285};
1286
1251int
1287static int
1288msdosfs_mkdir(ap)
1289 struct vop_mkdir_args /* {
1290 struct vnode *a_dvp;
1291 struvt vnode **a_vpp;
1292 struvt componentname *a_cnp;
1293 struct vattr *a_vap;
1294 } */ *ap;
1295{

--- 85 unchanged lines hidden (view full) ---

1381 free(ap->a_cnp->cn_pnbuf, M_NAMEI);
1382#ifdef MSDOSFS_DEBUG
1383 printf("msdosfs_mkdir(): vput(%08x)\n", ap->a_dvp);
1384#endif
1385 vput(ap->a_dvp);
1386 return error;
1387}
1388
1353int
1389static int
1390msdosfs_rmdir(ap)
1391 struct vop_rmdir_args /* {
1392 struct vnode *a_dvp;
1393 struct vnode *a_vp;
1394 struct componentname *a_cnp;
1395 } */ *ap;
1396{
1397 struct denode *ddep;

--- 52 unchanged lines hidden (view full) ---

1450 vput(ap->a_dvp);
1451 vput(ap->a_vp);
1452 return error;
1453}
1454
1455/*
1456 * DOS filesystems don't know what symlinks are.
1457 */
1422int
1458static int
1459msdosfs_symlink(ap)
1460 struct vop_symlink_args /* {
1461 struct vnode *a_dvp;
1462 struct vnode **a_vpp;
1463 struct componentname *a_cnp;
1464 struct vattr *a_vap;
1465 char *a_target;
1466 } */ *ap;
1467{
1468 free(ap->a_cnp->cn_pnbuf, M_NAMEI);
1469 vput(ap->a_dvp);
1470 return EINVAL;
1471}
1472
1473/*
1474 * Dummy dirents to simulate the "." and ".." entries of the root directory
1475 * in a dos filesystem. Dos doesn't provide these. Note that each entry
1476 * must be the same size as a dos directory entry (32 bytes).
1477 */
1442struct dos_dirent {
1478static struct dos_dirent {
1479 u_long d_fileno;
1480 u_short d_reclen;
1481 u_char d_type;
1482 u_char d_namlen;
1483 u_char d_name[24];
1484} rootdots[2] = {
1485
1486 {

--- 7 unchanged lines hidden (view full) ---

1494 1, /* d_fileno */
1495 sizeof(struct direntry), /* d_reclen */
1496 DT_DIR, /* d_type */
1497 2, /* d_namlen */
1498 ".." /* d_name */
1499 }
1500};
1501
1466int
1502static int
1503msdosfs_readdir(ap)
1504 struct vop_readdir_args /* {
1505 struct vnode *a_vp;
1506 struct uio *a_uio;
1507 struct ucred *a_cred;
1508 int *a_eofflag;
1509 u_int *a_cookies;
1510 int a_ncookies;

--- 257 unchanged lines hidden (view full) ---

1768 *ap->a_eofflag = 0;
1769
1770 return error;
1771}
1772
1773/*
1774 * DOS filesystems don't know what symlinks are.
1775 */
1740int
1776static int
1777msdosfs_readlink(ap)
1778 struct vop_readlink_args /* {
1779 struct vnode *a_vp;
1780 struct uio *a_uio;
1781 struct ucred *a_cred;
1782 } */ *ap;
1783{
1784 return EINVAL;
1785}
1786
1751int
1787static int
1788msdosfs_abortop(ap)
1789 struct vop_abortop_args /* {
1790 struct vnode *a_dvp;
1791 struct componentname *a_cnp;
1792 } */ *ap;
1793{
1794 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
1795 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
1796 return 0;
1797}
1798
1763int
1799static int
1800msdosfs_lock(ap)
1801 struct vop_lock_args /* {
1802 struct vnode *a_vp;
1803 } */ *ap;
1804{
1805 struct denode *dep = VTODE(ap->a_vp);
1806
1807 while (dep->de_flag & DE_LOCKED) {

--- 4 unchanged lines hidden (view full) ---

1812 (void) tsleep((caddr_t) dep, PINOD, "msdlck", 0);
1813 }
1814 dep->de_lockwaiter = 0;
1815 dep->de_lockholder = curproc->p_pid;
1816 dep->de_flag |= DE_LOCKED;
1817 return 0;
1818}
1819
1784int
1820static int
1821msdosfs_unlock(ap)
1822 struct vop_unlock_args /* {
1823 struct vnode *vp;
1824 } */ *ap;
1825{
1826 struct denode *dep = VTODE(ap->a_vp);
1827
1828 if (!(dep->de_flag & DE_LOCKED))
1829 panic("msdosfs_unlock: denode not locked");
1830 dep->de_lockholder = 0;
1831 dep->de_flag &= ~DE_LOCKED;
1832 if (dep->de_flag & DE_WANTED) {
1833 dep->de_flag &= ~DE_WANTED;
1834 wakeup((caddr_t) dep);
1835 }
1836 return 0;
1837}
1838
1803int
1839static int
1840msdosfs_islocked(ap)
1841 struct vop_islocked_args /* {
1842 struct vnode *a_vp;
1843 } */ *ap;
1844{
1845 return VTODE(ap->a_vp)->de_flag & DE_LOCKED ? 1 : 0;
1846}
1847
1848/*
1849 * vp - address of vnode file the file
1850 * bn - which cluster we are interested in mapping to a filesystem block number.
1851 * vpp - returns the vnode for the block special file holding the filesystem
1852 * containing the file of interest
1853 * bnp - address of where to return the filesystem relative block number
1854 */
1819int
1855static int
1856msdosfs_bmap(ap)
1857 struct vop_bmap_args /* {
1858 struct vnode *a_vp;
1859 daddr_t a_bn;
1860 struct vnode **a_vpp;
1861 daddr_t *a_bnp;
1862 int *a_runp;
1863 int *a_runb;

--- 12 unchanged lines hidden (view full) ---

1876 *ap->a_runp = 0;
1877 }
1878 if (ap->a_runb) {
1879 *ap->a_runb = 0;
1880 }
1881 return pcbmap(dep, ap->a_bn, ap->a_bnp, 0);
1882}
1883
1848int msdosfs_reallocblks(ap)
1884static int
1885msdosfs_reallocblks(ap)
1886 struct vop_reallocblks_args /* {
1887 struct vnode *a_vp;
1888 struct cluster_save *a_buflist;
1889 } */ *ap;
1890{
1891 /* Currently no support for clustering */ /* XXX */
1892 return ENOSPC;
1893}
1894
1858int
1895static int
1896msdosfs_strategy(ap)
1897 struct vop_strategy_args /* {
1898 struct buf *a_bp;
1899 } */ *ap;
1900{
1901 struct buf *bp = ap->a_bp;
1902 struct denode *dep = VTODE(bp->b_vp);
1903 struct vnode *vp;

--- 25 unchanged lines hidden (view full) ---

1929 * file block.
1930 */
1931 vp = dep->de_devvp;
1932 bp->b_dev = vp->v_rdev;
1933 VOCALL(vp->v_op, VOFFSET(vop_strategy), ap);
1934 return 0;
1935}
1936
1900int
1937static int
1938msdosfs_print(ap)
1939 struct vop_print_args /* {
1940 struct vnode *vp;
1941 } */ *ap;
1942{
1943 struct denode *dep = VTODE(ap->a_vp);
1944
1945 printf(

--- 6 unchanged lines hidden (view full) ---

1952 printf(" owner pid %d", (int)dep->de_lockholder);
1953 if (dep->de_lockwaiter)
1954 printf(" waiting pid %d", (int)dep->de_lockwaiter);
1955 printf("\n");
1956 }
1957 return 0;
1958}
1959
1923int
1960static int
1961msdosfs_advlock(ap)
1962 struct vop_advlock_args /* {
1963 struct vnode *a_vp;
1964 caddr_t a_id;
1965 int a_op;
1966 struct flock *a_fl;
1967 int a_flags;
1968 } */ *ap;
1969{
1970 return EINVAL; /* we don't do locking yet */
1971}
1972
1936int
1973static int
1974msdosfs_pathconf(ap)
1975 struct vop_pathconf_args /* {
1976 struct vnode *a_vp;
1977 int a_name;
1978 int *a_retval;
1979 } */ *ap;
1980{
1981 switch (ap->a_name) {

--- 14 unchanged lines hidden (view full) ---

1996 return 0;
1997 default:
1998 return EINVAL;
1999 }
2000}
2001
2002/* Global vfs data structures for msdosfs */
2003int (**msdosfs_vnodeop_p)();
1967struct vnodeopv_entry_desc msdosfs_vnodeop_entries[] = {
2004static struct vnodeopv_entry_desc msdosfs_vnodeop_entries[] = {
2005 { &vop_default_desc, vn_default_error },
2006 { &vop_lookup_desc, msdosfs_lookup }, /* lookup */
2007 { &vop_create_desc, msdosfs_create }, /* create */
2008 { &vop_mknod_desc, msdosfs_mknod }, /* mknod */
2009 { &vop_open_desc, msdosfs_open }, /* open */
2010 { &vop_close_desc, msdosfs_close }, /* close */
2011 { &vop_access_desc, msdosfs_access }, /* access */
2012 { &vop_getattr_desc, msdosfs_getattr }, /* getattr */

--- 23 unchanged lines hidden (view full) ---

2036 { &vop_print_desc, msdosfs_print }, /* print */
2037 { &vop_islocked_desc, msdosfs_islocked }, /* islocked */
2038 { &vop_pathconf_desc, msdosfs_pathconf }, /* pathconf */
2039 { &vop_advlock_desc, msdosfs_advlock }, /* advlock */
2040 { &vop_reallocblks_desc, msdosfs_reallocblks }, /* reallocblks */
2041 { &vop_bwrite_desc, vn_bwrite },
2042 { (struct vnodeop_desc *)NULL, (int (*)())NULL }
2043};
2007struct vnodeopv_desc msdosfs_vnodeop_opv_desc =
2044static struct vnodeopv_desc msdosfs_vnodeop_opv_desc =
2045 { &msdosfs_vnodeop_p, msdosfs_vnodeop_entries };
2046
2047VNODEOP_SET(msdosfs_vnodeop_opv_desc);