1*0a6a1f1dSLionel Sambuc /* $NetBSD: cd9660.c,v 1.30 2014/03/20 03:13:18 christos Exp $ */
258a2b000SEvgeniy Ivanov
358a2b000SEvgeniy Ivanov /*
458a2b000SEvgeniy Ivanov * Copyright (C) 1996 Wolfgang Solfrank.
558a2b000SEvgeniy Ivanov * Copyright (C) 1996 TooLs GmbH.
658a2b000SEvgeniy Ivanov * All rights reserved.
758a2b000SEvgeniy Ivanov *
858a2b000SEvgeniy Ivanov * Redistribution and use in source and binary forms, with or without
958a2b000SEvgeniy Ivanov * modification, are permitted provided that the following conditions
1058a2b000SEvgeniy Ivanov * are met:
1158a2b000SEvgeniy Ivanov * 1. Redistributions of source code must retain the above copyright
1258a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer.
1358a2b000SEvgeniy Ivanov * 2. Redistributions in binary form must reproduce the above copyright
1458a2b000SEvgeniy Ivanov * notice, this list of conditions and the following disclaimer in the
1558a2b000SEvgeniy Ivanov * documentation and/or other materials provided with the distribution.
1658a2b000SEvgeniy Ivanov * 3. All advertising materials mentioning features or use of this software
1758a2b000SEvgeniy Ivanov * must display the following acknowledgement:
1858a2b000SEvgeniy Ivanov * This product includes software developed by TooLs GmbH.
1958a2b000SEvgeniy Ivanov * 4. The name of TooLs GmbH may not be used to endorse or promote products
2058a2b000SEvgeniy Ivanov * derived from this software without specific prior written permission.
2158a2b000SEvgeniy Ivanov *
2258a2b000SEvgeniy Ivanov * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
2358a2b000SEvgeniy Ivanov * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2458a2b000SEvgeniy Ivanov * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2558a2b000SEvgeniy Ivanov * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2658a2b000SEvgeniy Ivanov * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2758a2b000SEvgeniy Ivanov * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2858a2b000SEvgeniy Ivanov * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2958a2b000SEvgeniy Ivanov * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
3058a2b000SEvgeniy Ivanov * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
3158a2b000SEvgeniy Ivanov * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3258a2b000SEvgeniy Ivanov */
3358a2b000SEvgeniy Ivanov
3458a2b000SEvgeniy Ivanov /*
3558a2b000SEvgeniy Ivanov * Stand-alone ISO9660 file reading package.
3658a2b000SEvgeniy Ivanov *
3758a2b000SEvgeniy Ivanov * Note: This doesn't support Rock Ridge extensions, extended attributes,
3858a2b000SEvgeniy Ivanov * blocksizes other than 2048 bytes, multi-extent files, etc.
3958a2b000SEvgeniy Ivanov */
4058a2b000SEvgeniy Ivanov #include <sys/param.h>
4158a2b000SEvgeniy Ivanov #ifdef _STANDALONE
4258a2b000SEvgeniy Ivanov #include <lib/libkern/libkern.h>
4358a2b000SEvgeniy Ivanov #else
4458a2b000SEvgeniy Ivanov #include <string.h>
4558a2b000SEvgeniy Ivanov #endif
4658a2b000SEvgeniy Ivanov #include <fs/cd9660/iso.h>
4758a2b000SEvgeniy Ivanov
4858a2b000SEvgeniy Ivanov #include "stand.h"
4958a2b000SEvgeniy Ivanov #include "cd9660.h"
5058a2b000SEvgeniy Ivanov
5158a2b000SEvgeniy Ivanov /*
5258a2b000SEvgeniy Ivanov * XXX Does not currently implement:
5358a2b000SEvgeniy Ivanov * XXX
5458a2b000SEvgeniy Ivanov * XXX LIBSA_NO_FS_SYMLINK (does this even make sense?)
5558a2b000SEvgeniy Ivanov * XXX LIBSA_FS_SINGLECOMPONENT
5658a2b000SEvgeniy Ivanov */
5758a2b000SEvgeniy Ivanov
5858a2b000SEvgeniy Ivanov struct file {
5958a2b000SEvgeniy Ivanov off_t off; /* Current offset within file */
6058a2b000SEvgeniy Ivanov daddr_t bno; /* Starting block number */
6158a2b000SEvgeniy Ivanov off_t size; /* Size of file */
6258a2b000SEvgeniy Ivanov };
6358a2b000SEvgeniy Ivanov
6458a2b000SEvgeniy Ivanov struct ptable_ent {
6558a2b000SEvgeniy Ivanov char namlen [ISODCL( 1, 1)]; /* 711 */
6658a2b000SEvgeniy Ivanov char extlen [ISODCL( 2, 2)]; /* 711 */
6758a2b000SEvgeniy Ivanov char block [ISODCL( 3, 6)]; /* 732 */
6858a2b000SEvgeniy Ivanov char parent [ISODCL( 7, 8)]; /* 722 */
6958a2b000SEvgeniy Ivanov char name [1];
7058a2b000SEvgeniy Ivanov };
7158a2b000SEvgeniy Ivanov #define PTFIXSZ 8
7258a2b000SEvgeniy Ivanov #define PTSIZE(pp) roundup(PTFIXSZ + isonum_711((pp)->namlen), 2)
7358a2b000SEvgeniy Ivanov
7458a2b000SEvgeniy Ivanov #define cdb2devb(bno) ((bno) * ISO_DEFAULT_BLOCK_SIZE / DEV_BSIZE)
7558a2b000SEvgeniy Ivanov
7658a2b000SEvgeniy Ivanov static int pnmatch(const char *, struct ptable_ent *);
7758a2b000SEvgeniy Ivanov static int dirmatch(const char *, struct iso_directory_record *);
7858a2b000SEvgeniy Ivanov
7958a2b000SEvgeniy Ivanov static int
pnmatch(const char * path,struct ptable_ent * pp)8058a2b000SEvgeniy Ivanov pnmatch(const char *path, struct ptable_ent *pp)
8158a2b000SEvgeniy Ivanov {
8258a2b000SEvgeniy Ivanov char *cp;
8358a2b000SEvgeniy Ivanov int i;
8458a2b000SEvgeniy Ivanov
8558a2b000SEvgeniy Ivanov cp = pp->name;
8658a2b000SEvgeniy Ivanov for (i = isonum_711(pp->namlen); --i >= 0; path++, cp++) {
8758a2b000SEvgeniy Ivanov if (toupper(*path) == *cp)
8858a2b000SEvgeniy Ivanov continue;
8958a2b000SEvgeniy Ivanov return 0;
9058a2b000SEvgeniy Ivanov }
9158a2b000SEvgeniy Ivanov if (*path != '/')
9258a2b000SEvgeniy Ivanov return 0;
9358a2b000SEvgeniy Ivanov return 1;
9458a2b000SEvgeniy Ivanov }
9558a2b000SEvgeniy Ivanov
9658a2b000SEvgeniy Ivanov static int
dirmatch(const char * path,struct iso_directory_record * dp)9758a2b000SEvgeniy Ivanov dirmatch(const char *path, struct iso_directory_record *dp)
9858a2b000SEvgeniy Ivanov {
9958a2b000SEvgeniy Ivanov char *cp;
10058a2b000SEvgeniy Ivanov int i;
10158a2b000SEvgeniy Ivanov
10258a2b000SEvgeniy Ivanov /* This needs to be a regular file */
10358a2b000SEvgeniy Ivanov if (dp->flags[0] & 6)
10458a2b000SEvgeniy Ivanov return 0;
10558a2b000SEvgeniy Ivanov
10658a2b000SEvgeniy Ivanov cp = dp->name;
10758a2b000SEvgeniy Ivanov for (i = isonum_711(dp->name_len); --i >= 0; path++, cp++) {
10858a2b000SEvgeniy Ivanov if (!*path)
10958a2b000SEvgeniy Ivanov break;
11058a2b000SEvgeniy Ivanov if (toupper(*path) == *cp)
11158a2b000SEvgeniy Ivanov continue;
11258a2b000SEvgeniy Ivanov return 0;
11358a2b000SEvgeniy Ivanov }
11458a2b000SEvgeniy Ivanov if (*path)
11558a2b000SEvgeniy Ivanov return 0;
11658a2b000SEvgeniy Ivanov /*
11758a2b000SEvgeniy Ivanov * Allow stripping of trailing dots and the version number.
11858a2b000SEvgeniy Ivanov * Note that this will find the first instead of the last version
11958a2b000SEvgeniy Ivanov * of a file.
12058a2b000SEvgeniy Ivanov */
12158a2b000SEvgeniy Ivanov if (i >= 0 && (*cp == ';' || *cp == '.')) {
12258a2b000SEvgeniy Ivanov /* This is to prevent matching of numeric extensions */
12358a2b000SEvgeniy Ivanov if (*cp == '.' && cp[1] != ';')
12458a2b000SEvgeniy Ivanov return 0;
12558a2b000SEvgeniy Ivanov while (--i >= 0)
12658a2b000SEvgeniy Ivanov if (*++cp != ';' && (*cp < '0' || *cp > '9'))
12758a2b000SEvgeniy Ivanov return 0;
12858a2b000SEvgeniy Ivanov }
12958a2b000SEvgeniy Ivanov return 1;
13058a2b000SEvgeniy Ivanov }
13158a2b000SEvgeniy Ivanov
13258a2b000SEvgeniy Ivanov __compactcall int
cd9660_open(const char * path,struct open_file * f)13358a2b000SEvgeniy Ivanov cd9660_open(const char *path, struct open_file *f)
13458a2b000SEvgeniy Ivanov {
13558a2b000SEvgeniy Ivanov struct file *fp = 0;
13658a2b000SEvgeniy Ivanov void *buf;
13758a2b000SEvgeniy Ivanov struct iso_primary_descriptor *vd;
13858a2b000SEvgeniy Ivanov size_t buf_size, nread, psize, dsize;
13958a2b000SEvgeniy Ivanov daddr_t bno;
14058a2b000SEvgeniy Ivanov int parent, ent;
14158a2b000SEvgeniy Ivanov struct ptable_ent *pp;
14258a2b000SEvgeniy Ivanov struct iso_directory_record *dp = 0;
14358a2b000SEvgeniy Ivanov int rc;
14458a2b000SEvgeniy Ivanov
14558a2b000SEvgeniy Ivanov /* First find the volume descriptor */
14658a2b000SEvgeniy Ivanov buf_size = ISO_DEFAULT_BLOCK_SIZE;
14758a2b000SEvgeniy Ivanov buf = alloc(buf_size);
14858a2b000SEvgeniy Ivanov vd = buf;
14958a2b000SEvgeniy Ivanov for (bno = 16;; bno++) {
15058a2b000SEvgeniy Ivanov #if !defined(LIBSA_NO_TWIDDLE)
15158a2b000SEvgeniy Ivanov twiddle();
15258a2b000SEvgeniy Ivanov #endif
15358a2b000SEvgeniy Ivanov rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno),
15458a2b000SEvgeniy Ivanov ISO_DEFAULT_BLOCK_SIZE, buf, &nread);
15558a2b000SEvgeniy Ivanov if (rc)
15658a2b000SEvgeniy Ivanov goto out;
15758a2b000SEvgeniy Ivanov if (nread != ISO_DEFAULT_BLOCK_SIZE) {
15858a2b000SEvgeniy Ivanov rc = EIO;
15958a2b000SEvgeniy Ivanov goto out;
16058a2b000SEvgeniy Ivanov }
16158a2b000SEvgeniy Ivanov rc = EINVAL;
16258a2b000SEvgeniy Ivanov if (memcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0)
16358a2b000SEvgeniy Ivanov goto out;
16458a2b000SEvgeniy Ivanov if (isonum_711(vd->type) == ISO_VD_END)
16558a2b000SEvgeniy Ivanov goto out;
16658a2b000SEvgeniy Ivanov if (isonum_711(vd->type) == ISO_VD_PRIMARY)
16758a2b000SEvgeniy Ivanov break;
16858a2b000SEvgeniy Ivanov }
16958a2b000SEvgeniy Ivanov if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE)
17058a2b000SEvgeniy Ivanov goto out;
17158a2b000SEvgeniy Ivanov
17258a2b000SEvgeniy Ivanov /* Now get the path table and lookup the directory of the file */
17358a2b000SEvgeniy Ivanov bno = isonum_732(vd->type_m_path_table);
17458a2b000SEvgeniy Ivanov psize = isonum_733(vd->path_table_size);
17558a2b000SEvgeniy Ivanov
17658a2b000SEvgeniy Ivanov if (psize > ISO_DEFAULT_BLOCK_SIZE) {
17758a2b000SEvgeniy Ivanov dealloc(buf, ISO_DEFAULT_BLOCK_SIZE);
17858a2b000SEvgeniy Ivanov buf = alloc(buf_size = roundup(psize, ISO_DEFAULT_BLOCK_SIZE));
17958a2b000SEvgeniy Ivanov }
18058a2b000SEvgeniy Ivanov
18158a2b000SEvgeniy Ivanov #if !defined(LIBSA_NO_TWIDDLE)
18258a2b000SEvgeniy Ivanov twiddle();
18358a2b000SEvgeniy Ivanov #endif
18458a2b000SEvgeniy Ivanov rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno),
18558a2b000SEvgeniy Ivanov buf_size, buf, &nread);
18658a2b000SEvgeniy Ivanov if (rc)
18758a2b000SEvgeniy Ivanov goto out;
18858a2b000SEvgeniy Ivanov if (nread != buf_size) {
18958a2b000SEvgeniy Ivanov rc = EIO;
19058a2b000SEvgeniy Ivanov goto out;
19158a2b000SEvgeniy Ivanov }
19258a2b000SEvgeniy Ivanov
19358a2b000SEvgeniy Ivanov parent = 1;
19458a2b000SEvgeniy Ivanov pp = (struct ptable_ent *)buf;
19558a2b000SEvgeniy Ivanov ent = 1;
19658a2b000SEvgeniy Ivanov bno = isonum_732(pp->block) + isonum_711(pp->extlen);
19758a2b000SEvgeniy Ivanov
19858a2b000SEvgeniy Ivanov rc = ENOENT;
19958a2b000SEvgeniy Ivanov
20058a2b000SEvgeniy Ivanov while (*path) {
20158a2b000SEvgeniy Ivanov /*
20258a2b000SEvgeniy Ivanov * Remove extra separators
20358a2b000SEvgeniy Ivanov */
20458a2b000SEvgeniy Ivanov while (*path == '/')
20558a2b000SEvgeniy Ivanov path++;
20658a2b000SEvgeniy Ivanov
20758a2b000SEvgeniy Ivanov if ((char *)pp >= (char *)buf + psize)
20858a2b000SEvgeniy Ivanov break;
20958a2b000SEvgeniy Ivanov if (isonum_722(pp->parent) != parent)
21058a2b000SEvgeniy Ivanov break;
21158a2b000SEvgeniy Ivanov if (!pnmatch(path, pp)) {
21258a2b000SEvgeniy Ivanov pp = (struct ptable_ent *)((char *)pp + PTSIZE(pp));
21358a2b000SEvgeniy Ivanov ent++;
21458a2b000SEvgeniy Ivanov continue;
21558a2b000SEvgeniy Ivanov }
21658a2b000SEvgeniy Ivanov path += isonum_711(pp->namlen) + 1;
21758a2b000SEvgeniy Ivanov parent = ent;
21858a2b000SEvgeniy Ivanov bno = isonum_732(pp->block) + isonum_711(pp->extlen);
21958a2b000SEvgeniy Ivanov while ((char *)pp < (char *)buf + psize) {
22058a2b000SEvgeniy Ivanov if (isonum_722(pp->parent) == parent)
22158a2b000SEvgeniy Ivanov break;
22258a2b000SEvgeniy Ivanov pp = (struct ptable_ent *)((char *)pp + PTSIZE(pp));
22358a2b000SEvgeniy Ivanov ent++;
22458a2b000SEvgeniy Ivanov }
22558a2b000SEvgeniy Ivanov }
22658a2b000SEvgeniy Ivanov
22758a2b000SEvgeniy Ivanov /*
22858a2b000SEvgeniy Ivanov * Now bno has the start of the directory that supposedly
22958a2b000SEvgeniy Ivanov * contains the file
23058a2b000SEvgeniy Ivanov */
23158a2b000SEvgeniy Ivanov bno--;
23258a2b000SEvgeniy Ivanov dsize = 1; /* Something stupid, but > 0 XXX */
23358a2b000SEvgeniy Ivanov for (psize = 0; psize < dsize;) {
23458a2b000SEvgeniy Ivanov if (!(psize % ISO_DEFAULT_BLOCK_SIZE)) {
23558a2b000SEvgeniy Ivanov bno++;
23658a2b000SEvgeniy Ivanov #if !defined(LIBSA_NO_TWIDDLE)
23758a2b000SEvgeniy Ivanov twiddle();
23858a2b000SEvgeniy Ivanov #endif
23958a2b000SEvgeniy Ivanov rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
24058a2b000SEvgeniy Ivanov cdb2devb(bno),
24158a2b000SEvgeniy Ivanov ISO_DEFAULT_BLOCK_SIZE,
24258a2b000SEvgeniy Ivanov buf, &nread);
24358a2b000SEvgeniy Ivanov if (rc)
24458a2b000SEvgeniy Ivanov goto out;
24558a2b000SEvgeniy Ivanov if (nread != ISO_DEFAULT_BLOCK_SIZE) {
24658a2b000SEvgeniy Ivanov rc = EIO;
24758a2b000SEvgeniy Ivanov goto out;
24858a2b000SEvgeniy Ivanov }
24958a2b000SEvgeniy Ivanov dp = (struct iso_directory_record *)buf;
25058a2b000SEvgeniy Ivanov }
25158a2b000SEvgeniy Ivanov if (!isonum_711(dp->length)) {
25258a2b000SEvgeniy Ivanov if ((void *)dp == buf)
25358a2b000SEvgeniy Ivanov psize += ISO_DEFAULT_BLOCK_SIZE;
25458a2b000SEvgeniy Ivanov else
25558a2b000SEvgeniy Ivanov psize = roundup(psize, ISO_DEFAULT_BLOCK_SIZE);
25658a2b000SEvgeniy Ivanov continue;
25758a2b000SEvgeniy Ivanov }
25858a2b000SEvgeniy Ivanov if (dsize == 1)
25958a2b000SEvgeniy Ivanov dsize = isonum_733(dp->size);
26058a2b000SEvgeniy Ivanov if (dirmatch(path, dp))
26158a2b000SEvgeniy Ivanov break;
26258a2b000SEvgeniy Ivanov psize += isonum_711(dp->length);
26358a2b000SEvgeniy Ivanov dp = (struct iso_directory_record *)
26458a2b000SEvgeniy Ivanov ((char *)dp + isonum_711(dp->length));
26558a2b000SEvgeniy Ivanov }
26658a2b000SEvgeniy Ivanov
26758a2b000SEvgeniy Ivanov if (psize >= dsize) {
26858a2b000SEvgeniy Ivanov rc = ENOENT;
26958a2b000SEvgeniy Ivanov goto out;
27058a2b000SEvgeniy Ivanov }
27158a2b000SEvgeniy Ivanov
27258a2b000SEvgeniy Ivanov /* allocate file system specific data structure */
27358a2b000SEvgeniy Ivanov fp = alloc(sizeof(struct file));
27458a2b000SEvgeniy Ivanov memset(fp, 0, sizeof(struct file));
27558a2b000SEvgeniy Ivanov f->f_fsdata = (void *)fp;
27658a2b000SEvgeniy Ivanov
27758a2b000SEvgeniy Ivanov fp->off = 0;
27858a2b000SEvgeniy Ivanov fp->bno = isonum_733(dp->extent);
27958a2b000SEvgeniy Ivanov fp->size = isonum_733(dp->size);
28058a2b000SEvgeniy Ivanov dealloc(buf, buf_size);
28158a2b000SEvgeniy Ivanov fsmod = "cd9660";
28258a2b000SEvgeniy Ivanov
28358a2b000SEvgeniy Ivanov return 0;
28458a2b000SEvgeniy Ivanov
28558a2b000SEvgeniy Ivanov out:
28658a2b000SEvgeniy Ivanov if (fp)
28758a2b000SEvgeniy Ivanov dealloc(fp, sizeof(struct file));
28858a2b000SEvgeniy Ivanov dealloc(buf, buf_size);
28958a2b000SEvgeniy Ivanov
29058a2b000SEvgeniy Ivanov return rc;
29158a2b000SEvgeniy Ivanov }
29258a2b000SEvgeniy Ivanov
29358a2b000SEvgeniy Ivanov #if !defined(LIBSA_NO_FS_CLOSE)
29458a2b000SEvgeniy Ivanov __compactcall int
cd9660_close(struct open_file * f)29558a2b000SEvgeniy Ivanov cd9660_close(struct open_file *f)
29658a2b000SEvgeniy Ivanov {
29758a2b000SEvgeniy Ivanov struct file *fp = (struct file *)f->f_fsdata;
29858a2b000SEvgeniy Ivanov
29958a2b000SEvgeniy Ivanov f->f_fsdata = 0;
30058a2b000SEvgeniy Ivanov dealloc(fp, sizeof *fp);
30158a2b000SEvgeniy Ivanov
30258a2b000SEvgeniy Ivanov return 0;
30358a2b000SEvgeniy Ivanov }
30458a2b000SEvgeniy Ivanov #endif /* !defined(LIBSA_NO_FS_CLOSE) */
30558a2b000SEvgeniy Ivanov
30658a2b000SEvgeniy Ivanov __compactcall int
cd9660_read(struct open_file * f,void * start,size_t size,size_t * resid)30758a2b000SEvgeniy Ivanov cd9660_read(struct open_file *f, void *start, size_t size, size_t *resid)
30858a2b000SEvgeniy Ivanov {
30958a2b000SEvgeniy Ivanov struct file *fp = (struct file *)f->f_fsdata;
31058a2b000SEvgeniy Ivanov int rc = 0;
31158a2b000SEvgeniy Ivanov daddr_t bno;
31258a2b000SEvgeniy Ivanov char buf[ISO_DEFAULT_BLOCK_SIZE];
31358a2b000SEvgeniy Ivanov char *dp;
31458a2b000SEvgeniy Ivanov size_t nread, off;
31558a2b000SEvgeniy Ivanov
31658a2b000SEvgeniy Ivanov while (size) {
31758a2b000SEvgeniy Ivanov if (fp->off < 0 || fp->off >= fp->size)
31858a2b000SEvgeniy Ivanov break;
31958a2b000SEvgeniy Ivanov bno = fp->off / ISO_DEFAULT_BLOCK_SIZE + fp->bno;
32058a2b000SEvgeniy Ivanov if (fp->off & (ISO_DEFAULT_BLOCK_SIZE - 1)
321f14fb602SLionel Sambuc || (fp->off + ISO_DEFAULT_BLOCK_SIZE) > fp->size
32258a2b000SEvgeniy Ivanov || size < ISO_DEFAULT_BLOCK_SIZE)
32358a2b000SEvgeniy Ivanov dp = buf;
32458a2b000SEvgeniy Ivanov else
32558a2b000SEvgeniy Ivanov dp = start;
32658a2b000SEvgeniy Ivanov #if !defined(LIBSA_NO_TWIDDLE)
32758a2b000SEvgeniy Ivanov twiddle();
32858a2b000SEvgeniy Ivanov #endif
32958a2b000SEvgeniy Ivanov rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno),
33058a2b000SEvgeniy Ivanov ISO_DEFAULT_BLOCK_SIZE, dp, &nread);
33158a2b000SEvgeniy Ivanov if (rc)
33258a2b000SEvgeniy Ivanov return rc;
33358a2b000SEvgeniy Ivanov if (nread != ISO_DEFAULT_BLOCK_SIZE)
33458a2b000SEvgeniy Ivanov return EIO;
33558a2b000SEvgeniy Ivanov if (dp == buf) {
33658a2b000SEvgeniy Ivanov off = fp->off & (ISO_DEFAULT_BLOCK_SIZE - 1);
33758a2b000SEvgeniy Ivanov if (nread > off + size)
33858a2b000SEvgeniy Ivanov nread = off + size;
33958a2b000SEvgeniy Ivanov nread -= off;
340f14fb602SLionel Sambuc if (nread > fp->size - fp->off)
341f14fb602SLionel Sambuc nread = fp->size - fp->off;
34258a2b000SEvgeniy Ivanov memcpy(start, buf + off, nread);
34358a2b000SEvgeniy Ivanov start = (char *)start + nread;
34458a2b000SEvgeniy Ivanov fp->off += nread;
34558a2b000SEvgeniy Ivanov size -= nread;
34658a2b000SEvgeniy Ivanov } else {
34758a2b000SEvgeniy Ivanov start = (char *)start + ISO_DEFAULT_BLOCK_SIZE;
34858a2b000SEvgeniy Ivanov fp->off += ISO_DEFAULT_BLOCK_SIZE;
34958a2b000SEvgeniy Ivanov size -= ISO_DEFAULT_BLOCK_SIZE;
35058a2b000SEvgeniy Ivanov }
35158a2b000SEvgeniy Ivanov }
35258a2b000SEvgeniy Ivanov if(fp->off > fp->size)
35358a2b000SEvgeniy Ivanov size += fp->off - fp->size;
35458a2b000SEvgeniy Ivanov if (resid)
35558a2b000SEvgeniy Ivanov *resid = size;
35658a2b000SEvgeniy Ivanov return rc;
35758a2b000SEvgeniy Ivanov }
35858a2b000SEvgeniy Ivanov
35958a2b000SEvgeniy Ivanov #if !defined(LIBSA_NO_FS_WRITE)
36058a2b000SEvgeniy Ivanov __compactcall int
cd9660_write(struct open_file * f,void * start,size_t size,size_t * resid)36158a2b000SEvgeniy Ivanov cd9660_write(struct open_file *f, void *start, size_t size, size_t *resid)
36258a2b000SEvgeniy Ivanov {
36358a2b000SEvgeniy Ivanov
36458a2b000SEvgeniy Ivanov return EROFS;
36558a2b000SEvgeniy Ivanov }
36658a2b000SEvgeniy Ivanov #endif /* !defined(LIBSA_NO_FS_WRITE) */
36758a2b000SEvgeniy Ivanov
36858a2b000SEvgeniy Ivanov #if !defined(LIBSA_NO_FS_SEEK)
36958a2b000SEvgeniy Ivanov __compactcall off_t
cd9660_seek(struct open_file * f,off_t offset,int where)37058a2b000SEvgeniy Ivanov cd9660_seek(struct open_file *f, off_t offset, int where)
37158a2b000SEvgeniy Ivanov {
37258a2b000SEvgeniy Ivanov struct file *fp = (struct file *)f->f_fsdata;
37358a2b000SEvgeniy Ivanov
37458a2b000SEvgeniy Ivanov switch (where) {
37558a2b000SEvgeniy Ivanov case SEEK_SET:
37658a2b000SEvgeniy Ivanov fp->off = offset;
37758a2b000SEvgeniy Ivanov break;
37858a2b000SEvgeniy Ivanov case SEEK_CUR:
37958a2b000SEvgeniy Ivanov fp->off += offset;
38058a2b000SEvgeniy Ivanov break;
38158a2b000SEvgeniy Ivanov case SEEK_END:
38258a2b000SEvgeniy Ivanov fp->off = fp->size - offset;
38358a2b000SEvgeniy Ivanov break;
38458a2b000SEvgeniy Ivanov default:
38558a2b000SEvgeniy Ivanov return -1;
38658a2b000SEvgeniy Ivanov }
38758a2b000SEvgeniy Ivanov return fp->off;
38858a2b000SEvgeniy Ivanov }
38958a2b000SEvgeniy Ivanov #endif /* !defined(LIBSA_NO_FS_SEEK) */
39058a2b000SEvgeniy Ivanov
39158a2b000SEvgeniy Ivanov __compactcall int
cd9660_stat(struct open_file * f,struct stat * sb)39258a2b000SEvgeniy Ivanov cd9660_stat(struct open_file *f, struct stat *sb)
39358a2b000SEvgeniy Ivanov {
39458a2b000SEvgeniy Ivanov struct file *fp = (struct file *)f->f_fsdata;
39558a2b000SEvgeniy Ivanov
39658a2b000SEvgeniy Ivanov /* only importatn stuff */
39758a2b000SEvgeniy Ivanov sb->st_mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH;
39858a2b000SEvgeniy Ivanov sb->st_uid = sb->st_gid = 0;
39958a2b000SEvgeniy Ivanov sb->st_size = fp->size;
40058a2b000SEvgeniy Ivanov return 0;
40158a2b000SEvgeniy Ivanov }
40258a2b000SEvgeniy Ivanov
40358a2b000SEvgeniy Ivanov #if defined(LIBSA_ENABLE_LS_OP)
404*0a6a1f1dSLionel Sambuc #include "ls.h"
40558a2b000SEvgeniy Ivanov __compactcall void
cd9660_ls(struct open_file * f,const char * pattern)406*0a6a1f1dSLionel Sambuc cd9660_ls(struct open_file *f, const char *pattern)
40758a2b000SEvgeniy Ivanov {
408*0a6a1f1dSLionel Sambuc lsunsup("cd9660");
40958a2b000SEvgeniy Ivanov }
410*0a6a1f1dSLionel Sambuc
411*0a6a1f1dSLionel Sambuc #if defined(__minix) && defined(LIBSA_ENABLE_LOAD_MODS_OP)
412*0a6a1f1dSLionel Sambuc __compactcall void
cd9660_load_mods(struct open_file * f,const char * pattern,void (* funcp)(char *),char * path)413*0a6a1f1dSLionel Sambuc cd9660_load_mods(struct open_file *f, const char *pattern,
414*0a6a1f1dSLionel Sambuc void (*funcp)(char *), char *path)
415*0a6a1f1dSLionel Sambuc {
416*0a6a1f1dSLionel Sambuc load_modsunsup("cd9660");
417*0a6a1f1dSLionel Sambuc }
418*0a6a1f1dSLionel Sambuc #endif /* defined(__minix) && defined(LIBSA_ENABLE_LOAD_MODS_OP) */
41958a2b000SEvgeniy Ivanov #endif
420