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 */ |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 */ |
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 |
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 |
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 |
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 */ |
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 */ |
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 |
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 */ |
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 */ |
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 |
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 |
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 |
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 */ |
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 */ |
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 |
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 */ |
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 |
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 |
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 |
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 |
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 */ |
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 |
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 |
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 |
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 |
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 |
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)(); |
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}; |
2044static struct vnodeopv_desc msdosfs_vnodeop_opv_desc = |
2045 { &msdosfs_vnodeop_p, msdosfs_vnodeop_entries }; 2046 2047VNODEOP_SET(msdosfs_vnodeop_opv_desc); |