cd9660_vfsops.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  1. /* $OpenBSD: cd9660_vfsops.c,v 1.70 2015/03/14 03:38:50 jsg Exp $ */
  2. /* $NetBSD: cd9660_vfsops.c,v 1.26 1997/06/13 15:38:58 pk Exp $ */
  3. /*-
  4. * Copyright (c) 1994
  5. * The Regents of the University of California. All rights reserved.
  6. *
  7. * This code is derived from software contributed to Berkeley
  8. * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension
  9. * Support code is derived from software contributed to Berkeley
  10. * by Atsushi Murai (amurai@spec.co.jp).
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions
  14. * are met:
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in the
  19. * documentation and/or other materials provided with the distribution.
  20. * 3. Neither the name of the University nor the names of its contributors
  21. * may be used to endorse or promote products derived from this software
  22. * without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34. * SUCH DAMAGE.
  35. *
  36. * @(#)cd9660_vfsops.c 8.9 (Berkeley) 12/5/94
  37. */
  38. #include <sys/param.h>
  39. #include <sys/systm.h>
  40. #include <sys/namei.h>
  41. #include <sys/proc.h>
  42. #include <sys/kernel.h>
  43. #include <sys/vnode.h>
  44. #include <sys/lock.h>
  45. #include <sys/specdev.h>
  46. #include <sys/mount.h>
  47. #include <sys/buf.h>
  48. #include <sys/file.h>
  49. #include <sys/disklabel.h>
  50. #include <sys/ioctl.h>
  51. #include <sys/cdio.h>
  52. #include <sys/errno.h>
  53. #include <sys/malloc.h>
  54. #include <sys/stat.h>
  55. #include <isofs/cd9660/iso.h>
  56. #include <isofs/cd9660/cd9660_extern.h>
  57. #include <isofs/cd9660/iso_rrip.h>
  58. #include <isofs/cd9660/cd9660_node.h>
  59. const struct vfsops cd9660_vfsops = {
  60. cd9660_mount,
  61. cd9660_start,
  62. cd9660_unmount,
  63. cd9660_root,
  64. cd9660_quotactl,
  65. cd9660_statfs,
  66. cd9660_sync,
  67. cd9660_vget,
  68. cd9660_fhtovp,
  69. cd9660_vptofh,
  70. cd9660_init,
  71. cd9660_sysctl,
  72. cd9660_check_export
  73. };
  74. /*
  75. * Called by vfs_mountroot when iso is going to be mounted as root.
  76. */
  77. static int iso_mountfs(struct vnode *devvp, struct mount *mp,
  78. struct proc *p, struct iso_args *argp);
  79. int iso_disklabelspoof(dev_t dev, void (*strat)(struct buf *),
  80. struct disklabel *lp);
  81. int
  82. cd9660_mountroot()
  83. {
  84. struct mount *mp;
  85. extern struct vnode *rootvp;
  86. struct proc *p = curproc; /* XXX */
  87. int error;
  88. struct iso_args args;
  89. /*
  90. * Get vnodes for swapdev and rootdev.
  91. */
  92. if ((error = bdevvp(swapdev, &swapdev_vp)) ||
  93. (error = bdevvp(rootdev, &rootvp))) {
  94. printf("cd9660_mountroot: can't setup bdevvp's");
  95. return (error);
  96. }
  97. if ((error = vfs_rootmountalloc("cd9660", "root_device", &mp)) != 0)
  98. return (error);
  99. args.flags = ISOFSMNT_ROOT;
  100. if ((error = iso_mountfs(rootvp, mp, p, &args)) != 0) {
  101. mp->mnt_vfc->vfc_refcount--;
  102. vfs_unbusy(mp);
  103. free(mp, M_MOUNT, 0);
  104. return (error);
  105. }
  106. TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
  107. (void)cd9660_statfs(mp, &mp->mnt_stat, p);
  108. vfs_unbusy(mp);
  109. inittodr(0);
  110. return (0);
  111. }
  112. /*
  113. * VFS Operations.
  114. *
  115. * mount system call
  116. */
  117. int
  118. cd9660_mount(mp, path, data, ndp, p)
  119. register struct mount *mp;
  120. const char *path;
  121. void *data;
  122. struct nameidata *ndp;
  123. struct proc *p;
  124. {
  125. struct iso_mnt *imp = NULL;
  126. struct iso_args args;
  127. struct vnode *devvp;
  128. char fspec[MNAMELEN];
  129. int error;
  130. if ((mp->mnt_flag & MNT_RDONLY) == 0)
  131. return (EROFS);
  132. error = copyin(data, &args, sizeof(struct iso_args));
  133. if (error)
  134. return (error);
  135. /*
  136. * If updating, check whether changing from read-only to
  137. * read/write; if there is no device name, that's all we do.
  138. */
  139. if (mp->mnt_flag & MNT_UPDATE) {
  140. imp = VFSTOISOFS(mp);
  141. if (args.fspec == NULL)
  142. return (vfs_export(mp, &imp->im_export,
  143. &args.export_info));
  144. }
  145. /*
  146. * Not an update, or updating the name: look up the name
  147. * and verify that it refers to a sensible block device.
  148. */
  149. error = copyinstr(args.fspec, fspec, sizeof(fspec), NULL);
  150. if (error)
  151. return (error);
  152. NDINIT(ndp, LOOKUP, FOLLOW, UIO_SYSSPACE, fspec, p);
  153. if ((error = namei(ndp)) != 0)
  154. return (error);
  155. devvp = ndp->ni_vp;
  156. if (devvp->v_type != VBLK) {
  157. vrele(devvp);
  158. return (ENOTBLK);
  159. }
  160. if (major(devvp->v_rdev) >= nblkdev) {
  161. vrele(devvp);
  162. return (ENXIO);
  163. }
  164. /*
  165. * If mount by non-root, then verify that user has necessary
  166. * permissions on the device.
  167. */
  168. if (suser(p, 0) != 0) {
  169. vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
  170. error = VOP_ACCESS(devvp, VREAD, p->p_ucred, p);
  171. if (error) {
  172. vput(devvp);
  173. return (error);
  174. }
  175. VOP_UNLOCK(devvp, 0, p);
  176. }
  177. if ((mp->mnt_flag & MNT_UPDATE) == 0)
  178. error = iso_mountfs(devvp, mp, p, &args);
  179. else {
  180. if (devvp != imp->im_devvp)
  181. error = EINVAL; /* needs translation */
  182. else
  183. vrele(devvp);
  184. }
  185. if (error) {
  186. vrele(devvp);
  187. return (error);
  188. }
  189. imp = VFSTOISOFS(mp);
  190. bzero(mp->mnt_stat.f_mntonname, MNAMELEN);
  191. strlcpy(mp->mnt_stat.f_mntonname, path, MNAMELEN);
  192. bzero(mp->mnt_stat.f_mntfromname, MNAMELEN);
  193. strlcpy(mp->mnt_stat.f_mntfromname, fspec, MNAMELEN);
  194. bzero(mp->mnt_stat.f_mntfromspec, MNAMELEN);
  195. strlcpy(mp->mnt_stat.f_mntfromspec, fspec, MNAMELEN);
  196. bcopy(&args, &mp->mnt_stat.mount_info.iso_args, sizeof(args));
  197. cd9660_statfs(mp, &mp->mnt_stat, p);
  198. return (0);
  199. }
  200. /*
  201. * Common code for mount and mountroot
  202. */
  203. static int
  204. iso_mountfs(devvp, mp, p, argp)
  205. register struct vnode *devvp;
  206. struct mount *mp;
  207. struct proc *p;
  208. struct iso_args *argp;
  209. {
  210. register struct iso_mnt *isomp = (struct iso_mnt *)0;
  211. struct buf *bp = NULL;
  212. struct buf *pribp = NULL, *supbp = NULL;
  213. dev_t dev = devvp->v_rdev;
  214. int error = EINVAL;
  215. int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
  216. extern struct vnode *rootvp;
  217. int iso_bsize;
  218. int iso_blknum;
  219. int joliet_level;
  220. struct iso_volume_descriptor *vdp;
  221. struct iso_primary_descriptor *pri = NULL;
  222. struct iso_supplementary_descriptor *sup = NULL;
  223. struct iso_directory_record *rootp;
  224. int logical_block_size;
  225. int sess;
  226. if (!ronly)
  227. return (EROFS);
  228. /*
  229. * Disallow multiple mounts of the same device.
  230. * Disallow mounting of a device that is currently in use
  231. * (except for root, which might share swap device for miniroot).
  232. * Flush out any old buffers remaining from a previous use.
  233. */
  234. if ((error = vfs_mountedon(devvp)) != 0)
  235. return (error);
  236. if (vcount(devvp) > 1 && devvp != rootvp)
  237. return (EBUSY);
  238. vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
  239. error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0);
  240. VOP_UNLOCK(devvp, 0, p);
  241. if (error)
  242. return (error);
  243. error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
  244. if (error)
  245. return (error);
  246. /*
  247. * This is the "logical sector size". The standard says this
  248. * should be 2048 or the physical sector size on the device,
  249. * whichever is greater. For now, we'll just use a constant.
  250. */
  251. iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
  252. if (argp->flags & ISOFSMNT_SESS) {
  253. sess = argp->sess;
  254. if (sess < 0)
  255. sess = 0;
  256. } else {
  257. sess = 0;
  258. error = VOP_IOCTL(devvp, CDIOREADMSADDR, (caddr_t)&sess, 0,
  259. FSCRED, p);
  260. if (error)
  261. sess = 0;
  262. }
  263. joliet_level = 0;
  264. for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
  265. if ((error = bread(devvp,
  266. (iso_blknum + sess) * btodb(iso_bsize),
  267. iso_bsize, &bp)) != 0)
  268. goto out;
  269. vdp = (struct iso_volume_descriptor *)bp->b_data;
  270. if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
  271. error = EINVAL;
  272. goto out;
  273. }
  274. switch (isonum_711 (vdp->type)){
  275. case ISO_VD_PRIMARY:
  276. if (pribp == NULL) {
  277. pribp = bp;
  278. bp = NULL;
  279. pri = (struct iso_primary_descriptor *)vdp;
  280. }
  281. break;
  282. case ISO_VD_SUPPLEMENTARY:
  283. if (supbp == NULL) {
  284. supbp = bp;
  285. bp = NULL;
  286. sup = (struct iso_supplementary_descriptor *)vdp;
  287. if (!(argp->flags & ISOFSMNT_NOJOLIET)) {
  288. if (bcmp(sup->escape, "%/@", 3) == 0)
  289. joliet_level = 1;
  290. if (bcmp(sup->escape, "%/C", 3) == 0)
  291. joliet_level = 2;
  292. if (bcmp(sup->escape, "%/E", 3) == 0)
  293. joliet_level = 3;
  294. if (isonum_711 (sup->flags) & 1)
  295. joliet_level = 0;
  296. }
  297. }
  298. break;
  299. case ISO_VD_END:
  300. goto vd_end;
  301. default:
  302. break;
  303. }
  304. if (bp) {
  305. brelse(bp);
  306. bp = NULL;
  307. }
  308. }
  309. vd_end:
  310. if (bp) {
  311. brelse(bp);
  312. bp = NULL;
  313. }
  314. if (pri == NULL) {
  315. error = EINVAL;
  316. goto out;
  317. }
  318. logical_block_size = isonum_723 (pri->logical_block_size);
  319. if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE
  320. || (logical_block_size & (logical_block_size - 1)) != 0) {
  321. error = EINVAL;
  322. goto out;
  323. }
  324. rootp = (struct iso_directory_record *)pri->root_directory_record;
  325. isomp = malloc(sizeof *isomp, M_ISOFSMNT, M_WAITOK);
  326. bzero((caddr_t)isomp, sizeof *isomp);
  327. isomp->logical_block_size = logical_block_size;
  328. isomp->volume_space_size = isonum_733 (pri->volume_space_size);
  329. bcopy (rootp, isomp->root, sizeof isomp->root);
  330. isomp->root_extent = isonum_733 (rootp->extent);
  331. isomp->root_size = isonum_733 (rootp->size);
  332. isomp->joliet_level = 0;
  333. /*
  334. * Since an ISO9660 multi-session CD can also access previous sessions,
  335. * we have to include them into the space considerations.
  336. */
  337. isomp->volume_space_size += sess;
  338. isomp->im_bmask = logical_block_size - 1;
  339. isomp->im_bshift = ffs(logical_block_size) - 1;
  340. brelse(pribp);
  341. pribp = NULL;
  342. mp->mnt_data = (qaddr_t)isomp;
  343. mp->mnt_stat.f_fsid.val[0] = (long)dev;
  344. mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
  345. mp->mnt_maxsymlinklen = 0;
  346. mp->mnt_flag |= MNT_LOCAL;
  347. isomp->im_mountp = mp;
  348. isomp->im_dev = dev;
  349. isomp->im_devvp = devvp;
  350. /* Check the Rock Ridge Extension support */
  351. if (!(argp->flags & ISOFSMNT_NORRIP)) {
  352. if ((error = bread(isomp->im_devvp, (isomp->root_extent +
  353. isonum_711(rootp->ext_attr_length)) <<
  354. (isomp->im_bshift - DEV_BSHIFT),
  355. isomp->logical_block_size, &bp)) != 0)
  356. goto out;
  357. rootp = (struct iso_directory_record *)bp->b_data;
  358. if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
  359. argp->flags |= ISOFSMNT_NORRIP;
  360. } else {
  361. argp->flags &= ~ISOFSMNT_GENS;
  362. }
  363. /*
  364. * The contents are valid,
  365. * but they will get reread as part of another vnode, so...
  366. */
  367. brelse(bp);
  368. bp = NULL;
  369. }
  370. isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
  371. ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET);
  372. switch (isomp->im_flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS)) {
  373. default:
  374. isomp->iso_ftype = ISO_FTYPE_DEFAULT;
  375. break;
  376. case ISOFSMNT_GENS|ISOFSMNT_NORRIP:
  377. isomp->iso_ftype = ISO_FTYPE_9660;
  378. break;
  379. case 0:
  380. isomp->iso_ftype = ISO_FTYPE_RRIP;
  381. break;
  382. }
  383. /* Decide whether to use the Joliet descriptor */
  384. if (isomp->iso_ftype != ISO_FTYPE_RRIP && joliet_level) {
  385. rootp = (struct iso_directory_record *)
  386. sup->root_directory_record;
  387. bcopy(rootp, isomp->root, sizeof isomp->root);
  388. isomp->root_extent = isonum_733(rootp->extent);
  389. isomp->root_size = isonum_733(rootp->size);
  390. isomp->joliet_level = joliet_level;
  391. }
  392. if (supbp) {
  393. brelse(supbp);
  394. supbp = NULL;
  395. }
  396. devvp->v_specmountpoint = mp;
  397. return (0);
  398. out:
  399. if (bp)
  400. brelse(bp);
  401. if (supbp)
  402. brelse(supbp);
  403. vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
  404. VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED, p);
  405. VOP_UNLOCK(devvp, 0, p);
  406. if (isomp) {
  407. free((caddr_t)isomp, M_ISOFSMNT, 0);
  408. mp->mnt_data = (qaddr_t)0;
  409. }
  410. return (error);
  411. }
  412. /*
  413. * Test to see if the device is an ISOFS filesystem.
  414. */
  415. int
  416. iso_disklabelspoof(dev, strat, lp)
  417. dev_t dev;
  418. void (*strat)(struct buf *);
  419. register struct disklabel *lp;
  420. {
  421. struct buf *bp = NULL;
  422. struct iso_volume_descriptor *vdp;
  423. struct iso_primary_descriptor *pri;
  424. int logical_block_size;
  425. int error = EINVAL;
  426. int iso_blknum;
  427. int i;
  428. bp = geteblk(ISO_DEFAULT_BLOCK_SIZE);
  429. bp->b_dev = dev;
  430. for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
  431. bp->b_blkno = iso_blknum * btodb(ISO_DEFAULT_BLOCK_SIZE);
  432. bp->b_bcount = ISO_DEFAULT_BLOCK_SIZE;
  433. CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
  434. SET(bp->b_flags, B_BUSY | B_READ | B_RAW);
  435. /*printf("d_secsize %d iso_blknum %d b_blkno %d bcount %d\n",
  436. lp->d_secsize, iso_blknum, bp->b_blkno, bp->b_bcount);*/
  437. (*strat)(bp);
  438. if (biowait(bp))
  439. goto out;
  440. vdp = (struct iso_volume_descriptor *)bp->b_data;
  441. /*printf("%2x%2x%2x type %2x\n", vdp->id[0], vdp->id[1],
  442. vdp->id[2], isonum_711(vdp->type));*/
  443. if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0 ||
  444. isonum_711 (vdp->type) == ISO_VD_END)
  445. goto out;
  446. if (isonum_711 (vdp->type) == ISO_VD_PRIMARY)
  447. break;
  448. }
  449. if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
  450. goto out;
  451. pri = (struct iso_primary_descriptor *)vdp;
  452. logical_block_size = isonum_723 (pri->logical_block_size);
  453. if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE ||
  454. (logical_block_size & (logical_block_size - 1)) != 0)
  455. goto out;
  456. /*
  457. * build a disklabel for the CD
  458. */
  459. strncpy(lp->d_typename, pri->volume_id, sizeof lp->d_typename);
  460. strncpy(lp->d_packname, pri->volume_id+16, sizeof lp->d_packname);
  461. for (i = 0; i < MAXPARTITIONS; i++) {
  462. DL_SETPSIZE(&lp->d_partitions[i], 0);
  463. DL_SETPOFFSET(&lp->d_partitions[i], 0);
  464. }
  465. DL_SETPOFFSET(&lp->d_partitions[0], 0);
  466. DL_SETPSIZE(&lp->d_partitions[0], DL_GETDSIZE(lp));
  467. lp->d_partitions[0].p_fstype = FS_ISO9660;
  468. DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
  469. DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
  470. lp->d_partitions[RAW_PART].p_fstype = FS_ISO9660;
  471. lp->d_npartitions = MAXPARTITIONS;
  472. lp->d_bbsize = 8192; /* fake */
  473. lp->d_sbsize = 64*1024; /* fake */
  474. lp->d_version = 1;
  475. lp->d_magic = DISKMAGIC;
  476. lp->d_magic2 = DISKMAGIC;
  477. lp->d_checksum = dkcksum(lp);
  478. error = 0;
  479. out:
  480. bp->b_flags |= B_INVAL;
  481. brelse(bp);
  482. return (error);
  483. }
  484. /*
  485. * Make a filesystem operational.
  486. * Nothing to do at the moment.
  487. */
  488. /* ARGSUSED */
  489. int
  490. cd9660_start(mp, flags, p)
  491. struct mount *mp;
  492. int flags;
  493. struct proc *p;
  494. {
  495. return (0);
  496. }
  497. /*
  498. * unmount system call
  499. */
  500. int
  501. cd9660_unmount(mp, mntflags, p)
  502. struct mount *mp;
  503. int mntflags;
  504. struct proc *p;
  505. {
  506. register struct iso_mnt *isomp;
  507. int error, flags = 0;
  508. if (mntflags & MNT_FORCE)
  509. flags |= FORCECLOSE;
  510. #if 0
  511. mntflushbuf(mp, 0);
  512. if (mntinvalbuf(mp))
  513. return (EBUSY);
  514. #endif
  515. if ((error = vflush(mp, NULLVP, flags)) != 0)
  516. return (error);
  517. isomp = VFSTOISOFS(mp);
  518. isomp->im_devvp->v_specmountpoint = NULL;
  519. vn_lock(isomp->im_devvp, LK_EXCLUSIVE | LK_RETRY, p);
  520. error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p);
  521. vput(isomp->im_devvp);
  522. free((caddr_t)isomp, M_ISOFSMNT, 0);
  523. mp->mnt_data = (qaddr_t)0;
  524. mp->mnt_flag &= ~MNT_LOCAL;
  525. return (error);
  526. }
  527. /*
  528. * Return root of a filesystem
  529. */
  530. int
  531. cd9660_root(mp, vpp)
  532. struct mount *mp;
  533. struct vnode **vpp;
  534. {
  535. struct iso_mnt *imp = VFSTOISOFS(mp);
  536. struct iso_directory_record *dp =
  537. (struct iso_directory_record *)imp->root;
  538. cdino_t ino = isodirino(dp, imp);
  539. /*
  540. * With RRIP we must use the `.' entry of the root directory.
  541. * Simply tell vget, that it's a relocated directory.
  542. */
  543. return (cd9660_vget_internal(mp, ino, vpp,
  544. imp->iso_ftype == ISO_FTYPE_RRIP, dp));
  545. }
  546. /*
  547. * Do operations associated with quotas, not supported
  548. */
  549. /* ARGSUSED */
  550. int
  551. cd9660_quotactl(mp, cmd, uid, arg, p)
  552. struct mount *mp;
  553. int cmd;
  554. uid_t uid;
  555. caddr_t arg;
  556. struct proc *p;
  557. {
  558. return (EOPNOTSUPP);
  559. }
  560. /*
  561. * Get file system statistics.
  562. */
  563. int
  564. cd9660_statfs(mp, sbp, p)
  565. struct mount *mp;
  566. register struct statfs *sbp;
  567. struct proc *p;
  568. {
  569. register struct iso_mnt *isomp;
  570. isomp = VFSTOISOFS(mp);
  571. sbp->f_bsize = isomp->logical_block_size;
  572. sbp->f_iosize = sbp->f_bsize; /* XXX */
  573. sbp->f_blocks = isomp->volume_space_size;
  574. sbp->f_bfree = 0; /* total free blocks */
  575. sbp->f_bavail = 0; /* blocks free for non superuser */
  576. sbp->f_files = 0; /* total files */
  577. sbp->f_ffree = 0; /* free file nodes */
  578. if (sbp != &mp->mnt_stat) {
  579. bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
  580. bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname,
  581. MNAMELEN);
  582. bcopy(&mp->mnt_stat.mount_info.iso_args,
  583. &sbp->mount_info.iso_args, sizeof(struct iso_args));
  584. }
  585. return (0);
  586. }
  587. /* ARGSUSED */
  588. int
  589. cd9660_sync(mp, waitfor, cred, p)
  590. struct mount *mp;
  591. int waitfor;
  592. struct ucred *cred;
  593. struct proc *p;
  594. {
  595. return (0);
  596. }
  597. /*
  598. * File handle to vnode
  599. *
  600. * Have to be really careful about stale file handles:
  601. * - check that the inode number is in range
  602. * - call iget() to get the locked inode
  603. * - check for an unallocated inode (i_mode == 0)
  604. * - check that the generation number matches
  605. */
  606. struct ifid {
  607. ushort ifid_len;
  608. ushort ifid_pad;
  609. int ifid_ino;
  610. long ifid_start;
  611. };
  612. /* ARGSUSED */
  613. int
  614. cd9660_fhtovp(mp, fhp, vpp)
  615. register struct mount *mp;
  616. struct fid *fhp;
  617. struct vnode **vpp;
  618. {
  619. struct ifid *ifhp = (struct ifid *)fhp;
  620. register struct iso_node *ip;
  621. struct vnode *nvp;
  622. int error;
  623. #ifdef ISOFS_DBG
  624. printf("fhtovp: ino %d, start %ld\n", ifhp->ifid_ino,
  625. ifhp->ifid_start);
  626. #endif
  627. if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
  628. *vpp = NULLVP;
  629. return (error);
  630. }
  631. ip = VTOI(nvp);
  632. if (ip->inode.iso_mode == 0) {
  633. vput(nvp);
  634. *vpp = NULLVP;
  635. return (ESTALE);
  636. }
  637. *vpp = nvp;
  638. return (0);
  639. }
  640. int
  641. cd9660_vget(mp, ino, vpp)
  642. struct mount *mp;
  643. ino_t ino;
  644. struct vnode **vpp;
  645. {
  646. if (ino > (cdino_t)-1)
  647. panic("cd9660_vget: alien ino_t %llu",
  648. (unsigned long long)ino);
  649. /*
  650. * XXXX
  651. * It would be nice if we didn't always set the `relocated' flag
  652. * and force the extra read, but I don't want to think about fixing
  653. * that right now.
  654. */
  655. return (cd9660_vget_internal(mp, ino, vpp,
  656. #if 0
  657. VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
  658. #else
  659. 0,
  660. #endif
  661. NULL));
  662. }
  663. int
  664. cd9660_vget_internal(mp, ino, vpp, relocated, isodir)
  665. struct mount *mp;
  666. cdino_t ino;
  667. struct vnode **vpp;
  668. int relocated;
  669. struct iso_directory_record *isodir;
  670. {
  671. register struct iso_mnt *imp;
  672. struct iso_node *ip;
  673. struct buf *bp;
  674. struct vnode *vp, *nvp;
  675. dev_t dev;
  676. int error;
  677. retry:
  678. imp = VFSTOISOFS(mp);
  679. dev = imp->im_dev;
  680. if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP)
  681. return (0);
  682. /* Allocate a new vnode/iso_node. */
  683. if ((error = getnewvnode(VT_ISOFS, mp, &cd9660_vops, &vp)) != 0) {
  684. *vpp = NULLVP;
  685. return (error);
  686. }
  687. ip = malloc(sizeof(*ip), M_ISOFSNODE, M_WAITOK | M_ZERO);
  688. lockinit(&ip->i_lock, PINOD, "isoinode", 0, 0);
  689. vp->v_data = ip;
  690. ip->i_vnode = vp;
  691. ip->i_dev = dev;
  692. ip->i_number = ino;
  693. /*
  694. * Put it onto its hash chain and lock it so that other requests for
  695. * this inode will block if they arrive while we are sleeping waiting
  696. * for old data structures to be purged or for the contents of the
  697. * disk portion of this inode to be read.
  698. */
  699. error = cd9660_ihashins(ip);
  700. if (error) {
  701. vrele(vp);
  702. if (error == EEXIST)
  703. goto retry;
  704. return (error);
  705. }
  706. if (isodir == 0) {
  707. int lbn, off;
  708. lbn = lblkno(imp, ino);
  709. if (lbn >= imp->volume_space_size) {
  710. vput(vp);
  711. printf("fhtovp: lbn exceed volume space %d\n", lbn);
  712. return (ESTALE);
  713. }
  714. off = blkoff(imp, ino);
  715. if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size)
  716. {
  717. vput(vp);
  718. printf("fhtovp: crosses block boundary %d\n",
  719. off + ISO_DIRECTORY_RECORD_SIZE);
  720. return (ESTALE);
  721. }
  722. error = bread(imp->im_devvp,
  723. lbn << (imp->im_bshift - DEV_BSHIFT),
  724. imp->logical_block_size, &bp);
  725. if (error) {
  726. vput(vp);
  727. brelse(bp);
  728. printf("fhtovp: bread error %d\n",error);
  729. return (error);
  730. }
  731. isodir = (struct iso_directory_record *)(bp->b_data + off);
  732. if (off + isonum_711(isodir->length) >
  733. imp->logical_block_size) {
  734. vput(vp);
  735. if (bp != 0)
  736. brelse(bp);
  737. printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
  738. off +isonum_711(isodir->length), off,
  739. isonum_711(isodir->length));
  740. return (ESTALE);
  741. }
  742. #if 0
  743. if (isonum_733(isodir->extent) +
  744. isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
  745. if (bp != 0)
  746. brelse(bp);
  747. printf("fhtovp: file start miss %d vs %d\n",
  748. isonum_733(isodir->extent) +
  749. isonum_711(isodir->ext_attr_length),
  750. ifhp->ifid_start);
  751. return (ESTALE);
  752. }
  753. #endif
  754. } else
  755. bp = 0;
  756. ip->i_mnt = imp;
  757. ip->i_devvp = imp->im_devvp;
  758. vref(ip->i_devvp);
  759. if (relocated) {
  760. /*
  761. * On relocated directories we must
  762. * read the `.' entry out of a dir.
  763. */
  764. ip->iso_start = ino >> imp->im_bshift;
  765. if (bp != 0)
  766. brelse(bp);
  767. if ((error = cd9660_bufatoff(ip, (off_t)0, NULL, &bp)) != 0) {
  768. vput(vp);
  769. return (error);
  770. }
  771. isodir = (struct iso_directory_record *)bp->b_data;
  772. }
  773. ip->iso_extent = isonum_733(isodir->extent);
  774. ip->i_size = (u_int32_t) isonum_733(isodir->size);
  775. ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
  776. /*
  777. * Setup time stamp, attribute
  778. */
  779. vp->v_type = VNON;
  780. switch (imp->iso_ftype) {
  781. default: /* ISO_FTYPE_9660 */
  782. {
  783. struct buf *bp2;
  784. int off;
  785. if ((imp->im_flags & ISOFSMNT_EXTATT) &&
  786. (off = isonum_711(isodir->ext_attr_length)))
  787. cd9660_bufatoff(ip, (off_t)-(off << imp->im_bshift),
  788. NULL, &bp2);
  789. else
  790. bp2 = NULL;
  791. cd9660_defattr(isodir, ip, bp2);
  792. cd9660_deftstamp(isodir, ip, bp2);
  793. if (bp2)
  794. brelse(bp2);
  795. break;
  796. }
  797. case ISO_FTYPE_RRIP:
  798. cd9660_rrip_analyze(isodir, ip, imp);
  799. break;
  800. }
  801. if (bp != 0)
  802. brelse(bp);
  803. /*
  804. * Initialize the associated vnode
  805. */
  806. switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
  807. case VFIFO:
  808. #ifdef FIFO
  809. vp->v_op = &cd9660_fifovops;
  810. break;
  811. #else
  812. vput(vp);
  813. return (EOPNOTSUPP);
  814. #endif /* FIFO */
  815. case VCHR:
  816. case VBLK:
  817. /*
  818. * if device, look at device number table for translation
  819. */
  820. vp->v_op = &cd9660_specvops;
  821. if ((nvp = checkalias(vp, ip->inode.iso_rdev, mp)) != NULL) {
  822. /*
  823. * Discard unneeded vnode, but save its iso_node.
  824. * Note that the lock is carried over in the iso_node
  825. */
  826. nvp->v_data = vp->v_data;
  827. vp->v_data = NULL;
  828. vp->v_op = &spec_vops;
  829. vrele(vp);
  830. vgone(vp);
  831. /*
  832. * Reinitialize aliased inode.
  833. */
  834. vp = nvp;
  835. ip->i_vnode = vp;
  836. }
  837. break;
  838. case VLNK:
  839. case VNON:
  840. case VSOCK:
  841. case VDIR:
  842. case VBAD:
  843. break;
  844. case VREG:
  845. uvm_vnp_setsize(vp, ip->i_size);
  846. break;
  847. }
  848. if (ip->iso_extent == imp->root_extent)
  849. vp->v_flag |= VROOT;
  850. /*
  851. * XXX need generation number?
  852. */
  853. *vpp = vp;
  854. return (0);
  855. }
  856. /*
  857. * Vnode pointer to File handle
  858. */
  859. /* ARGSUSED */
  860. int
  861. cd9660_vptofh(vp, fhp)
  862. struct vnode *vp;
  863. struct fid *fhp;
  864. {
  865. register struct iso_node *ip = VTOI(vp);
  866. register struct ifid *ifhp;
  867. ifhp = (struct ifid *)fhp;
  868. ifhp->ifid_len = sizeof(struct ifid);
  869. ifhp->ifid_ino = ip->i_number;
  870. ifhp->ifid_start = ip->iso_start;
  871. #ifdef ISOFS_DBG
  872. printf("vptofh: ino %d, start %ld\n",
  873. ifhp->ifid_ino,ifhp->ifid_start);
  874. #endif
  875. return (0);
  876. }
  877. /*
  878. * Verify a remote client has export rights and return these rights via
  879. * exflagsp and credanonp.
  880. */
  881. int
  882. cd9660_check_export(mp, nam, exflagsp, credanonp)
  883. register struct mount *mp;
  884. struct mbuf *nam;
  885. int *exflagsp;
  886. struct ucred **credanonp;
  887. {
  888. register struct netcred *np;
  889. register struct iso_mnt *imp = VFSTOISOFS(mp);
  890. /*
  891. * Get the export permission structure for this <mp, client> tuple.
  892. */
  893. np = vfs_export_lookup(mp, &imp->im_export, nam);
  894. if (np == NULL)
  895. return (EACCES);
  896. *exflagsp = np->netc_exflags;
  897. *credanonp = &np->netc_anon;
  898. return (0);
  899. }