cd9660_vnops.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950
  1. /* $OpenBSD: cd9660_vnops.c,v 1.72 2015/04/17 04:43:20 guenther Exp $ */
  2. /* $NetBSD: cd9660_vnops.c,v 1.42 1997/10/16 23:56:57 christos 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_vnops.c 8.15 (Berkeley) 12/5/94
  37. */
  38. #include <sys/param.h>
  39. #include <sys/systm.h>
  40. #include <sys/namei.h>
  41. #include <sys/resourcevar.h>
  42. #include <sys/kernel.h>
  43. #include <sys/file.h>
  44. #include <sys/stat.h>
  45. #include <sys/buf.h>
  46. #include <sys/conf.h>
  47. #include <sys/mount.h>
  48. #include <sys/vnode.h>
  49. #include <sys/lock.h>
  50. #include <sys/malloc.h>
  51. #include <sys/pool.h>
  52. #include <sys/dirent.h>
  53. #include <sys/ioctl.h>
  54. #include <sys/ioccom.h>
  55. #include <sys/poll.h>
  56. #include <sys/specdev.h>
  57. #include <sys/unistd.h>
  58. #include <miscfs/fifofs/fifo.h>
  59. #include <isofs/cd9660/iso.h>
  60. #include <isofs/cd9660/cd9660_extern.h>
  61. #include <isofs/cd9660/cd9660_node.h>
  62. #include <isofs/cd9660/iso_rrip.h>
  63. /*
  64. * Structure for reading directories
  65. */
  66. struct isoreaddir {
  67. struct dirent saveent;
  68. struct dirent assocent;
  69. struct dirent current;
  70. off_t saveoff;
  71. off_t assocoff;
  72. off_t curroff;
  73. struct uio *uio;
  74. off_t uio_off;
  75. int eofflag;
  76. };
  77. int iso_uiodir(struct isoreaddir *, struct dirent *, off_t);
  78. int iso_shipdir(struct isoreaddir *);
  79. /*
  80. * Setattr call. Only allowed for block and character special devices.
  81. */
  82. int
  83. cd9660_setattr(void *v)
  84. {
  85. struct vop_setattr_args *ap = v;
  86. struct vnode *vp = ap->a_vp;
  87. struct vattr *vap = ap->a_vap;
  88. if (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
  89. vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_nsec != VNOVAL ||
  90. vap->va_mtime.tv_nsec != VNOVAL || vap->va_mode != (mode_t)VNOVAL ||
  91. (vap->va_vaflags & VA_UTIMES_CHANGE))
  92. return (EROFS);
  93. if (vap->va_size != VNOVAL) {
  94. switch (vp->v_type) {
  95. case VDIR:
  96. return (EISDIR);
  97. case VLNK:
  98. case VREG:
  99. return (EROFS);
  100. case VCHR:
  101. case VBLK:
  102. case VSOCK:
  103. case VFIFO:
  104. return (0);
  105. default:
  106. return (EINVAL);
  107. }
  108. }
  109. return (EINVAL);
  110. }
  111. /*
  112. * Open called.
  113. *
  114. * Nothing to do.
  115. */
  116. /* ARGSUSED */
  117. int
  118. cd9660_open(void *v)
  119. {
  120. return (0);
  121. }
  122. /*
  123. * Close called
  124. *
  125. * Update the times on the inode on writeable file systems.
  126. */
  127. /* ARGSUSED */
  128. int
  129. cd9660_close(void *v)
  130. {
  131. return (0);
  132. }
  133. /*
  134. * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
  135. * The mode is shifted to select the owner/group/other fields. The
  136. * super user is granted all permissions.
  137. */
  138. int
  139. cd9660_access(void *v)
  140. {
  141. struct vop_access_args *ap = v;
  142. struct iso_node *ip = VTOI(ap->a_vp);
  143. return (vaccess(ap->a_vp->v_type, ip->inode.iso_mode & ALLPERMS,
  144. ip->inode.iso_uid, ip->inode.iso_gid, ap->a_mode, ap->a_cred));
  145. }
  146. int
  147. cd9660_getattr(void *v)
  148. {
  149. struct vop_getattr_args *ap = v;
  150. struct vnode *vp = ap->a_vp;
  151. register struct vattr *vap = ap->a_vap;
  152. register struct iso_node *ip = VTOI(vp);
  153. vap->va_fsid = ip->i_dev;
  154. vap->va_fileid = ip->i_number;
  155. vap->va_mode = ip->inode.iso_mode & ALLPERMS;
  156. vap->va_nlink = ip->inode.iso_links;
  157. vap->va_uid = ip->inode.iso_uid;
  158. vap->va_gid = ip->inode.iso_gid;
  159. vap->va_atime = ip->inode.iso_atime;
  160. vap->va_mtime = ip->inode.iso_mtime;
  161. vap->va_ctime = ip->inode.iso_ctime;
  162. vap->va_rdev = ip->inode.iso_rdev;
  163. vap->va_size = (u_quad_t) ip->i_size;
  164. if (ip->i_size == 0 && vp->v_type == VLNK) {
  165. struct vop_readlink_args rdlnk;
  166. struct iovec aiov;
  167. struct uio auio;
  168. char *cp;
  169. cp = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  170. aiov.iov_base = cp;
  171. aiov.iov_len = MAXPATHLEN;
  172. auio.uio_iov = &aiov;
  173. auio.uio_iovcnt = 1;
  174. auio.uio_offset = 0;
  175. auio.uio_rw = UIO_READ;
  176. auio.uio_segflg = UIO_SYSSPACE;
  177. auio.uio_procp = ap->a_p;
  178. auio.uio_resid = MAXPATHLEN;
  179. rdlnk.a_uio = &auio;
  180. rdlnk.a_vp = ap->a_vp;
  181. rdlnk.a_cred = ap->a_cred;
  182. if (cd9660_readlink(&rdlnk) == 0)
  183. vap->va_size = MAXPATHLEN - auio.uio_resid;
  184. free(cp, M_TEMP, 0);
  185. }
  186. vap->va_flags = 0;
  187. vap->va_gen = 1;
  188. vap->va_blocksize = ip->i_mnt->logical_block_size;
  189. vap->va_bytes = (u_quad_t) ip->i_size;
  190. vap->va_type = vp->v_type;
  191. return (0);
  192. }
  193. /*
  194. * Vnode op for reading.
  195. */
  196. int
  197. cd9660_read(void *v)
  198. {
  199. struct vop_read_args *ap = v;
  200. struct vnode *vp = ap->a_vp;
  201. register struct uio *uio = ap->a_uio;
  202. register struct iso_node *ip = VTOI(vp);
  203. register struct iso_mnt *imp;
  204. struct buf *bp;
  205. daddr_t lbn, rablock;
  206. off_t diff;
  207. int error = 0;
  208. long size, n, on;
  209. if (uio->uio_resid == 0)
  210. return (0);
  211. if (uio->uio_offset < 0)
  212. return (EINVAL);
  213. ip->i_flag |= IN_ACCESS;
  214. imp = ip->i_mnt;
  215. do {
  216. struct cluster_info *ci = &ip->i_ci;
  217. lbn = lblkno(imp, uio->uio_offset);
  218. on = blkoff(imp, uio->uio_offset);
  219. n = min((u_int)(imp->logical_block_size - on),
  220. uio->uio_resid);
  221. diff = (off_t)ip->i_size - uio->uio_offset;
  222. if (diff <= 0)
  223. return (0);
  224. if (diff < n)
  225. n = diff;
  226. size = blksize(imp, ip, lbn);
  227. rablock = lbn + 1;
  228. #define MAX_RA 32
  229. if (ci->ci_lastr + 1 == lbn) {
  230. struct ra {
  231. daddr_t blks[MAX_RA];
  232. int sizes[MAX_RA];
  233. } *ra;
  234. int i;
  235. ra = malloc(sizeof *ra, M_TEMP, M_WAITOK);
  236. for (i = 0; i < MAX_RA &&
  237. lblktosize(imp, (rablock + i)) < ip->i_size;
  238. i++) {
  239. ra->blks[i] = rablock + i;
  240. ra->sizes[i] = blksize(imp, ip, rablock + i);
  241. }
  242. error = breadn(vp, lbn, size, ra->blks,
  243. ra->sizes, i, &bp);
  244. free(ra, M_TEMP, 0);
  245. } else
  246. error = bread(vp, lbn, size, &bp);
  247. ci->ci_lastr = lbn;
  248. n = min(n, size - bp->b_resid);
  249. if (error) {
  250. brelse(bp);
  251. return (error);
  252. }
  253. error = uiomovei(bp->b_data + on, (int)n, uio);
  254. brelse(bp);
  255. } while (error == 0 && uio->uio_resid > 0 && n != 0);
  256. return (error);
  257. }
  258. /* ARGSUSED */
  259. int
  260. cd9660_ioctl(void *v)
  261. {
  262. return (ENOTTY);
  263. }
  264. /* ARGSUSED */
  265. int
  266. cd9660_poll(void *v)
  267. {
  268. struct vop_poll_args *ap = v;
  269. /*
  270. * We should really check to see if I/O is possible.
  271. */
  272. return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
  273. }
  274. /*
  275. * Mmap a file
  276. *
  277. * NB Currently unsupported.
  278. */
  279. /* ARGSUSED */
  280. int
  281. cd9660_mmap(void *v)
  282. {
  283. return (EINVAL);
  284. }
  285. /*
  286. * Seek on a file
  287. *
  288. * Nothing to do, so just return.
  289. */
  290. /* ARGSUSED */
  291. int
  292. cd9660_seek(void *v)
  293. {
  294. return (0);
  295. }
  296. int
  297. iso_uiodir(idp,dp,off)
  298. struct isoreaddir *idp;
  299. struct dirent *dp;
  300. off_t off;
  301. {
  302. int error;
  303. dp->d_name[dp->d_namlen] = 0;
  304. dp->d_reclen = DIRENT_SIZE(dp);
  305. if (idp->uio->uio_resid < dp->d_reclen) {
  306. idp->eofflag = 0;
  307. return (-1);
  308. }
  309. dp->d_off = off;
  310. if ((error = uiomovei((caddr_t)dp, dp->d_reclen, idp->uio)) != 0)
  311. return (error);
  312. idp->uio_off = off;
  313. return (0);
  314. }
  315. int
  316. iso_shipdir(idp)
  317. struct isoreaddir *idp;
  318. {
  319. struct dirent *dp;
  320. int cl, sl, assoc;
  321. int error;
  322. char *cname, *sname;
  323. cl = idp->current.d_namlen;
  324. cname = idp->current.d_name;
  325. if ((assoc = cl > 1 && *cname == ASSOCCHAR)) {
  326. cl--;
  327. cname++;
  328. }
  329. dp = &idp->saveent;
  330. sname = dp->d_name;
  331. if (!(sl = dp->d_namlen)) {
  332. dp = &idp->assocent;
  333. sname = dp->d_name + 1;
  334. sl = dp->d_namlen - 1;
  335. }
  336. if (sl > 0) {
  337. if (sl != cl
  338. || bcmp(sname,cname,sl)) {
  339. if (idp->assocent.d_namlen) {
  340. error = iso_uiodir(idp, &idp->assocent,
  341. idp->assocoff);
  342. if (error)
  343. return (error);
  344. idp->assocent.d_namlen = 0;
  345. }
  346. if (idp->saveent.d_namlen) {
  347. error = iso_uiodir(idp, &idp->saveent,
  348. idp->saveoff);
  349. if (error)
  350. return (error);
  351. idp->saveent.d_namlen = 0;
  352. }
  353. }
  354. }
  355. idp->current.d_reclen = DIRENT_SIZE(&idp->current);
  356. if (assoc) {
  357. idp->assocoff = idp->curroff;
  358. bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
  359. } else {
  360. idp->saveoff = idp->curroff;
  361. bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
  362. }
  363. return (0);
  364. }
  365. /*
  366. * Vnode op for readdir
  367. */
  368. int
  369. cd9660_readdir(void *v)
  370. {
  371. struct vop_readdir_args *ap = v;
  372. register struct uio *uio = ap->a_uio;
  373. struct isoreaddir *idp;
  374. struct vnode *vdp = ap->a_vp;
  375. struct iso_node *dp;
  376. struct iso_mnt *imp;
  377. struct buf *bp = NULL;
  378. struct iso_directory_record *ep;
  379. int entryoffsetinblock;
  380. doff_t endsearch;
  381. u_long bmask;
  382. int error = 0;
  383. int reclen;
  384. u_short namelen;
  385. cdino_t ino;
  386. dp = VTOI(vdp);
  387. imp = dp->i_mnt;
  388. bmask = imp->im_bmask;
  389. idp = malloc(sizeof(*idp), M_TEMP, M_WAITOK);
  390. /*
  391. * These are passed to copyout(), so make sure there's no garbage
  392. * being leaked in padding or after short names.
  393. */
  394. memset(&idp->saveent, 0, sizeof(idp->saveent));
  395. memset(&idp->assocent, 0, sizeof(idp->assocent));
  396. memset(&idp->current, 0, sizeof(idp->current));
  397. /*
  398. * XXX
  399. * Is it worth trying to figure out the type?
  400. */
  401. idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
  402. DT_UNKNOWN;
  403. idp->uio = uio;
  404. idp->eofflag = 1;
  405. idp->curroff = uio->uio_offset;
  406. idp->uio_off = uio->uio_offset;
  407. if ((entryoffsetinblock = idp->curroff & bmask) &&
  408. (error = cd9660_bufatoff(dp, (off_t)idp->curroff, NULL, &bp))) {
  409. free(idp, M_TEMP, 0);
  410. return (error);
  411. }
  412. endsearch = dp->i_size;
  413. while (idp->curroff < endsearch) {
  414. /*
  415. * If offset is on a block boundary,
  416. * read the next directory block.
  417. * Release previous if it exists.
  418. */
  419. if ((idp->curroff & bmask) == 0) {
  420. if (bp != NULL)
  421. brelse(bp);
  422. error = cd9660_bufatoff(dp, (off_t)idp->curroff,
  423. NULL, &bp);
  424. if (error)
  425. break;
  426. entryoffsetinblock = 0;
  427. }
  428. /*
  429. * Get pointer to next entry.
  430. */
  431. ep = (struct iso_directory_record *)
  432. ((char *)bp->b_data + entryoffsetinblock);
  433. reclen = isonum_711(ep->length);
  434. if (reclen == 0) {
  435. /* skip to next block, if any */
  436. idp->curroff =
  437. (idp->curroff & ~bmask) + imp->logical_block_size;
  438. continue;
  439. }
  440. if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
  441. error = EINVAL;
  442. /* illegal entry, stop */
  443. break;
  444. }
  445. if (entryoffsetinblock + reclen > imp->logical_block_size) {
  446. error = EINVAL;
  447. /* illegal directory, so stop looking */
  448. break;
  449. }
  450. idp->current.d_namlen = isonum_711(ep->name_len);
  451. if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
  452. error = EINVAL;
  453. /* illegal entry, stop */
  454. break;
  455. }
  456. if (isonum_711(ep->flags)&2)
  457. ino = isodirino(ep, imp);
  458. else
  459. ino = dbtob(bp->b_blkno) + entryoffsetinblock;
  460. idp->curroff += reclen;
  461. switch (imp->iso_ftype) {
  462. case ISO_FTYPE_RRIP:
  463. cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
  464. &ino, imp);
  465. idp->current.d_fileno = ino;
  466. idp->current.d_namlen = (u_char)namelen;
  467. if (idp->current.d_namlen)
  468. error = iso_uiodir(idp,&idp->current,idp->curroff);
  469. break;
  470. default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
  471. idp->current.d_fileno = ino;
  472. strlcpy(idp->current.d_name,"..",
  473. sizeof idp->current.d_name);
  474. if (idp->current.d_namlen == 1 && ep->name[0] == 0) {
  475. idp->current.d_namlen = 1;
  476. error = iso_uiodir(idp,&idp->current,idp->curroff);
  477. } else if (idp->current.d_namlen == 1 &&
  478. ep->name[0] == 1) {
  479. idp->current.d_namlen = 2;
  480. error = iso_uiodir(idp,&idp->current,idp->curroff);
  481. } else {
  482. isofntrans(ep->name,idp->current.d_namlen,
  483. idp->current.d_name, &namelen,
  484. imp->iso_ftype == ISO_FTYPE_9660,
  485. isonum_711(ep->flags) & 4,
  486. imp->joliet_level);
  487. idp->current.d_namlen = (u_char)namelen;
  488. if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
  489. error = iso_shipdir(idp);
  490. else
  491. error = iso_uiodir(idp,&idp->current,idp->curroff);
  492. }
  493. }
  494. if (error)
  495. break;
  496. entryoffsetinblock += reclen;
  497. }
  498. if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
  499. idp->current.d_namlen = 0;
  500. error = iso_shipdir(idp);
  501. }
  502. if (error < 0)
  503. error = 0;
  504. if (bp)
  505. brelse (bp);
  506. uio->uio_offset = idp->uio_off;
  507. *ap->a_eofflag = idp->eofflag;
  508. free(idp, M_TEMP, 0);
  509. return (error);
  510. }
  511. /*
  512. * Return target name of a symbolic link
  513. * Shouldn't we get the parent vnode and read the data from there?
  514. * This could eventually result in deadlocks in cd9660_lookup.
  515. * But otherwise the block read here is in the block buffer two times.
  516. */
  517. typedef struct iso_directory_record ISODIR;
  518. typedef struct iso_node ISONODE;
  519. typedef struct iso_mnt ISOMNT;
  520. int
  521. cd9660_readlink(void *v)
  522. {
  523. struct vop_readlink_args *ap = v;
  524. ISONODE *ip;
  525. ISODIR *dirp;
  526. ISOMNT *imp;
  527. struct buf *bp;
  528. struct uio *uio;
  529. u_short symlen;
  530. int error;
  531. char *symname;
  532. ip = VTOI(ap->a_vp);
  533. imp = ip->i_mnt;
  534. uio = ap->a_uio;
  535. if (imp->iso_ftype != ISO_FTYPE_RRIP)
  536. return (EINVAL);
  537. /*
  538. * Get parents directory record block that this inode included.
  539. */
  540. error = bread(imp->im_devvp,
  541. (ip->i_number >> imp->im_bshift) <<
  542. (imp->im_bshift - DEV_BSHIFT),
  543. imp->logical_block_size, &bp);
  544. if (error) {
  545. brelse(bp);
  546. return (EINVAL);
  547. }
  548. /*
  549. * Setup the directory pointer for this inode
  550. */
  551. dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
  552. /*
  553. * Just make sure, we have a right one....
  554. * 1: Check not cross boundary on block
  555. */
  556. if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
  557. > imp->logical_block_size) {
  558. brelse(bp);
  559. return (EINVAL);
  560. }
  561. /*
  562. * Now get a buffer
  563. * Abuse a namei buffer for now.
  564. */
  565. if (uio->uio_segflg == UIO_SYSSPACE &&
  566. uio->uio_iov->iov_len >= MAXPATHLEN)
  567. symname = uio->uio_iov->iov_base;
  568. else
  569. symname = pool_get(&namei_pool, PR_WAITOK);
  570. /*
  571. * Ok, we just gathering a symbolic name in SL record.
  572. */
  573. if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
  574. if (uio->uio_segflg != UIO_SYSSPACE ||
  575. uio->uio_iov->iov_len < MAXPATHLEN)
  576. pool_put(&namei_pool, symname);
  577. brelse(bp);
  578. return (EINVAL);
  579. }
  580. /*
  581. * Don't forget before you leave from home ;-)
  582. */
  583. brelse(bp);
  584. /*
  585. * return with the symbolic name to caller's.
  586. */
  587. if (uio->uio_segflg != UIO_SYSSPACE ||
  588. uio->uio_iov->iov_len < MAXPATHLEN) {
  589. error = uiomovei(symname, symlen, uio);
  590. pool_put(&namei_pool, symname);
  591. return (error);
  592. }
  593. uio->uio_resid -= symlen;
  594. uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen;
  595. uio->uio_iov->iov_len -= symlen;
  596. return (0);
  597. }
  598. int
  599. cd9660_link(void *v)
  600. {
  601. struct vop_link_args *ap = v;
  602. VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
  603. vput(ap->a_dvp);
  604. return (EROFS);
  605. }
  606. int
  607. cd9660_symlink(void *v)
  608. {
  609. struct vop_symlink_args *ap = v;
  610. VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
  611. vput(ap->a_dvp);
  612. return (EROFS);
  613. }
  614. /*
  615. * Lock an inode.
  616. */
  617. int
  618. cd9660_lock(void *v)
  619. {
  620. struct vop_lock_args *ap = v;
  621. struct vnode *vp = ap->a_vp;
  622. return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, NULL));
  623. }
  624. /*
  625. * Unlock an inode.
  626. */
  627. int
  628. cd9660_unlock(void *v)
  629. {
  630. struct vop_unlock_args *ap = v;
  631. struct vnode *vp = ap->a_vp;
  632. return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, NULL));
  633. }
  634. /*
  635. * Calculate the logical to physical mapping if not done already,
  636. * then call the device strategy routine.
  637. */
  638. int
  639. cd9660_strategy(void *v)
  640. {
  641. struct vop_strategy_args *ap = v;
  642. struct buf *bp = ap->a_bp;
  643. struct vnode *vp = bp->b_vp;
  644. struct iso_node *ip;
  645. int error;
  646. int s;
  647. ip = VTOI(vp);
  648. if (vp->v_type == VBLK || vp->v_type == VCHR)
  649. panic("cd9660_strategy: spec");
  650. if (bp->b_blkno == bp->b_lblkno) {
  651. error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
  652. if (error) {
  653. bp->b_error = error;
  654. bp->b_flags |= B_ERROR;
  655. s = splbio();
  656. biodone(bp);
  657. splx(s);
  658. return (error);
  659. }
  660. if ((long)bp->b_blkno == -1)
  661. clrbuf(bp);
  662. }
  663. if ((long)bp->b_blkno == -1) {
  664. s = splbio();
  665. biodone(bp);
  666. splx(s);
  667. return (0);
  668. }
  669. vp = ip->i_devvp;
  670. bp->b_dev = vp->v_rdev;
  671. (vp->v_op->vop_strategy)(ap);
  672. return (0);
  673. }
  674. /*
  675. * Print out the contents of an inode.
  676. */
  677. /*ARGSUSED*/
  678. int
  679. cd9660_print(void *v)
  680. {
  681. printf("tag VT_ISOFS, isofs vnode\n");
  682. return (0);
  683. }
  684. /*
  685. * Check for a locked inode.
  686. */
  687. int
  688. cd9660_islocked(void *v)
  689. {
  690. struct vop_islocked_args *ap = v;
  691. return (lockstatus(&VTOI(ap->a_vp)->i_lock));
  692. }
  693. /*
  694. * Return POSIX pathconf information applicable to cd9660 filesystems.
  695. */
  696. int
  697. cd9660_pathconf(void *v)
  698. {
  699. struct vop_pathconf_args *ap = v;
  700. int error = 0;
  701. switch (ap->a_name) {
  702. case _PC_LINK_MAX:
  703. *ap->a_retval = 1;
  704. break;
  705. case _PC_NAME_MAX:
  706. if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
  707. *ap->a_retval = NAME_MAX;
  708. else
  709. *ap->a_retval = 37;
  710. break;
  711. case _PC_CHOWN_RESTRICTED:
  712. *ap->a_retval = 1;
  713. break;
  714. case _PC_NO_TRUNC:
  715. *ap->a_retval = 1;
  716. break;
  717. case _PC_TIMESTAMP_RESOLUTION:
  718. *ap->a_retval = 1000000000; /* one billion nanoseconds */
  719. break;
  720. default:
  721. error = EINVAL;
  722. break;
  723. }
  724. return (error);
  725. }
  726. /*
  727. * Global vfs data structures for isofs
  728. */
  729. #define cd9660_create eopnotsupp
  730. #define cd9660_mknod eopnotsupp
  731. #define cd9660_write eopnotsupp
  732. #define cd9660_fsync nullop
  733. #define cd9660_remove eopnotsupp
  734. #define cd9660_rename eopnotsupp
  735. #define cd9660_mkdir eopnotsupp
  736. #define cd9660_rmdir eopnotsupp
  737. #define cd9660_advlock eopnotsupp
  738. #define cd9660_valloc eopnotsupp
  739. #define cd9660_vfree eopnotsupp
  740. #define cd9660_truncate eopnotsupp
  741. #define cd9660_update eopnotsupp
  742. #define cd9660_bwrite eopnotsupp
  743. #define cd9660_revoke vop_generic_revoke
  744. /* Global vfs data structures for cd9660. */
  745. struct vops cd9660_vops = {
  746. .vop_lookup = cd9660_lookup,
  747. .vop_create = cd9660_create,
  748. .vop_mknod = cd9660_mknod,
  749. .vop_open = cd9660_open,
  750. .vop_close = cd9660_close,
  751. .vop_access = cd9660_access,
  752. .vop_getattr = cd9660_getattr,
  753. .vop_setattr = cd9660_setattr,
  754. .vop_read = cd9660_read,
  755. .vop_write = cd9660_write,
  756. .vop_ioctl = cd9660_ioctl,
  757. .vop_poll = cd9660_poll,
  758. .vop_revoke = cd9660_revoke,
  759. .vop_fsync = cd9660_fsync,
  760. .vop_remove = cd9660_remove,
  761. .vop_link = cd9660_link,
  762. .vop_rename = cd9660_rename,
  763. .vop_mkdir = cd9660_mkdir,
  764. .vop_rmdir = cd9660_rmdir,
  765. .vop_symlink = cd9660_symlink,
  766. .vop_readdir = cd9660_readdir,
  767. .vop_readlink = cd9660_readlink,
  768. .vop_abortop = vop_generic_abortop,
  769. .vop_inactive = cd9660_inactive,
  770. .vop_reclaim = cd9660_reclaim,
  771. .vop_lock = cd9660_lock,
  772. .vop_unlock = cd9660_unlock,
  773. .vop_bmap = cd9660_bmap,
  774. .vop_strategy = cd9660_strategy,
  775. .vop_print = cd9660_print,
  776. .vop_islocked = cd9660_islocked,
  777. .vop_pathconf = cd9660_pathconf,
  778. .vop_advlock = cd9660_advlock,
  779. .vop_bwrite = vop_generic_bwrite
  780. };
  781. /* Special device vnode ops */
  782. struct vops cd9660_specvops = {
  783. .vop_access = cd9660_access,
  784. .vop_getattr = cd9660_getattr,
  785. .vop_setattr = cd9660_setattr,
  786. .vop_inactive = cd9660_inactive,
  787. .vop_reclaim = cd9660_reclaim,
  788. .vop_lock = cd9660_lock,
  789. .vop_unlock = cd9660_unlock,
  790. .vop_print = cd9660_print,
  791. .vop_islocked = cd9660_islocked,
  792. /* XXX: Keep in sync with spec_vops. */
  793. .vop_lookup = vop_generic_lookup,
  794. .vop_create = spec_badop,
  795. .vop_mknod = spec_badop,
  796. .vop_open = spec_open,
  797. .vop_close = spec_close,
  798. .vop_read = spec_read,
  799. .vop_write = spec_write,
  800. .vop_ioctl = spec_ioctl,
  801. .vop_poll = spec_poll,
  802. .vop_kqfilter = spec_kqfilter,
  803. .vop_revoke = vop_generic_revoke,
  804. .vop_fsync = spec_fsync,
  805. .vop_remove = spec_badop,
  806. .vop_link = spec_badop,
  807. .vop_rename = spec_badop,
  808. .vop_mkdir = spec_badop,
  809. .vop_rmdir = spec_badop,
  810. .vop_symlink = spec_badop,
  811. .vop_readdir = spec_badop,
  812. .vop_readlink = spec_badop,
  813. .vop_abortop = spec_badop,
  814. .vop_bmap = vop_generic_bmap,
  815. .vop_strategy = spec_strategy,
  816. .vop_pathconf = spec_pathconf,
  817. .vop_advlock = spec_advlock,
  818. .vop_bwrite = vop_generic_bwrite,
  819. };
  820. #ifdef FIFO
  821. struct vops cd9660_fifovops = {
  822. .vop_access = cd9660_access,
  823. .vop_getattr = cd9660_getattr,
  824. .vop_setattr = cd9660_setattr,
  825. .vop_inactive = cd9660_inactive,
  826. .vop_reclaim = cd9660_reclaim,
  827. .vop_lock = cd9660_lock,
  828. .vop_unlock = cd9660_unlock,
  829. .vop_print = cd9660_print,
  830. .vop_islocked = cd9660_islocked,
  831. .vop_bwrite = vop_generic_bwrite,
  832. /* XXX: Keep in sync with fifo_vops. */
  833. .vop_lookup = vop_generic_lookup,
  834. .vop_create = fifo_badop,
  835. .vop_mknod = fifo_badop,
  836. .vop_open = fifo_open,
  837. .vop_close = fifo_close,
  838. .vop_read = fifo_read,
  839. .vop_write = fifo_write,
  840. .vop_ioctl = fifo_ioctl,
  841. .vop_poll = fifo_poll,
  842. .vop_kqfilter = fifo_kqfilter,
  843. .vop_revoke = vop_generic_revoke,
  844. .vop_fsync = nullop,
  845. .vop_remove = fifo_badop,
  846. .vop_link = fifo_badop,
  847. .vop_rename = fifo_badop,
  848. .vop_mkdir = fifo_badop,
  849. .vop_rmdir = fifo_badop,
  850. .vop_symlink = fifo_badop,
  851. .vop_readdir = fifo_badop,
  852. .vop_readlink = fifo_badop,
  853. .vop_abortop = fifo_badop,
  854. .vop_bmap = vop_generic_bmap,
  855. .vop_strategy = fifo_badop,
  856. .vop_pathconf = fifo_pathconf,
  857. .vop_advlock = fifo_advlock,
  858. };
  859. #endif /* FIFO */