static int buf_read_file(struct open_file *f, char **buf_p, size_t *size_p) { struct file *fp = (struct file *)f->f_fsdata; daddr_t blkno, blkoff; int rc = 0; size_t read; blkno = fp->f_off / ISO_DEFAULT_BLOCK_SIZE + fp->f_bno; blkoff = fp->f_off % ISO_DEFAULT_BLOCK_SIZE; if (blkno != fp->f_buf_blkno) { if (fp->f_buf == (char *)0) fp->f_buf = malloc(ISO_DEFAULT_BLOCK_SIZE); twiddle(16); rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(blkno), ISO_DEFAULT_BLOCK_SIZE, fp->f_buf, &read); if (rc) return (rc); if (read != ISO_DEFAULT_BLOCK_SIZE) return (EIO); fp->f_buf_blkno = blkno; } *buf_p = fp->f_buf + blkoff; *size_p = ISO_DEFAULT_BLOCK_SIZE - blkoff; if (*size_p > fp->f_size - fp->f_off) *size_p = fp->f_size - fp->f_off; return (rc); }
int cd9660_read(struct open_file *f, void *start, size_t size, size_t *resid) { struct file *fp = (struct file *)f->f_fsdata; int rc = 0; daddr_t bno; char buf[ISO_DEFAULT_BLOCK_SIZE]; char *dp; size_t nread, off; while (size) { if (fp->off < 0 || fp->off >= fp->size) break; bno = fp->off / ISO_DEFAULT_BLOCK_SIZE + fp->bno; if (fp->off & (ISO_DEFAULT_BLOCK_SIZE - 1) || size < ISO_DEFAULT_BLOCK_SIZE) dp = buf; else dp = start; #if !defined(LIBSA_NO_TWIDDLE) twiddle(); #endif rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno), ISO_DEFAULT_BLOCK_SIZE, dp, &nread); if (rc) return rc; if (nread != ISO_DEFAULT_BLOCK_SIZE) return EIO; if (dp == buf) { off = fp->off & (ISO_DEFAULT_BLOCK_SIZE - 1); if (nread > off + size) nread = off + size; nread -= off; memcpy(start, buf + off, nread); start = (char *)start + nread; fp->off += nread; size -= nread; } else { start = (char *)start + ISO_DEFAULT_BLOCK_SIZE; fp->off += ISO_DEFAULT_BLOCK_SIZE; size -= ISO_DEFAULT_BLOCK_SIZE; } } if (resid) *resid = size; return rc; }
static ISO_SUSP_HEADER * susp_lookup_record(struct open_file *f, const char *identifier, struct iso_directory_record *dp, int lenskip) { static char susp_buffer[ISO_DEFAULT_BLOCK_SIZE]; ISO_SUSP_HEADER *sh; ISO_RRIP_CONT *shc; char *p, *end; int error; size_t read; p = dp->name + isonum_711(dp->name_len) + lenskip; /* Names of even length have a padding byte after the name. */ if ((isonum_711(dp->name_len) & 1) == 0) p++; end = (char *)dp + isonum_711(dp->length); while (p + 3 < end) { sh = (ISO_SUSP_HEADER *)p; if (bcmp(sh->type, identifier, 2) == 0) return (sh); if (bcmp(sh->type, SUSP_STOP, 2) == 0) return (NULL); if (bcmp(sh->type, SUSP_CONTINUATION, 2) == 0) { shc = (ISO_RRIP_CONT *)sh; error = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(isonum_733(shc->location)), ISO_DEFAULT_BLOCK_SIZE, susp_buffer, &read); /* Bail if it fails. */ if (error != 0 || read != ISO_DEFAULT_BLOCK_SIZE) return (NULL); p = susp_buffer + isonum_733(shc->offset); end = p + isonum_733(shc->length); } else { /* Ignore this record and skip to the next. */ p += isonum_711(sh->length); /* Avoid infinite loops with corrupted file systems */ if (isonum_711(sh->length) == 0) return (NULL); } } return (NULL); }
static int cd9660_open(const char *path, struct open_file *f) { struct file *fp = NULL; void *buf; struct iso_primary_descriptor *vd; size_t buf_size, read, dsize, off; daddr_t bno, boff; struct iso_directory_record rec; struct iso_directory_record *dp = NULL; int rc, first, use_rrip, lenskip; /* First find the volume descriptor */ buf = malloc(buf_size = ISO_DEFAULT_BLOCK_SIZE); vd = buf; for (bno = 16;; bno++) { twiddle(1); rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno), ISO_DEFAULT_BLOCK_SIZE, buf, &read); if (rc) goto out; if (read != ISO_DEFAULT_BLOCK_SIZE) { rc = EIO; goto out; } rc = EINVAL; if (bcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0) goto out; if (isonum_711(vd->type) == ISO_VD_END) goto out; if (isonum_711(vd->type) == ISO_VD_PRIMARY) break; } if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE) goto out; rec = *(struct iso_directory_record *) vd->root_directory_record; if (*path == '/') path++; /* eat leading '/' */ first = 1; use_rrip = 0; while (*path) { bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length); dsize = isonum_733(rec.size); off = 0; boff = 0; while (off < dsize) { if ((off % ISO_DEFAULT_BLOCK_SIZE) == 0) { twiddle(1); rc = f->f_dev->dv_strategy (f->f_devdata, F_READ, cdb2devb(bno + boff), ISO_DEFAULT_BLOCK_SIZE, buf, &read); if (rc) goto out; if (read != ISO_DEFAULT_BLOCK_SIZE) { rc = EIO; goto out; } boff++; dp = (struct iso_directory_record *) buf; } if (isonum_711(dp->length) == 0) { /* skip to next block, if any */ off = boff * ISO_DEFAULT_BLOCK_SIZE; continue; } /* See if RRIP is in use. */ if (first) use_rrip = rrip_check(f, dp, &lenskip); if (dirmatch(f, path, dp, use_rrip, first ? 0 : lenskip)) { first = 0; break; } else first = 0; dp = (struct iso_directory_record *) ((char *) dp + isonum_711(dp->length)); /* If the new block has zero length, it is padding. */ if (isonum_711(dp->length) == 0) { /* Skip to next block, if any. */ off = boff * ISO_DEFAULT_BLOCK_SIZE; continue; } off += isonum_711(dp->length); } if (off >= dsize) { rc = ENOENT; goto out; } rec = *dp; while (*path && *path != '/') /* look for next component */ path++; if (*path) path++; /* skip '/' */ } /* allocate file system specific data structure */ fp = malloc(sizeof(struct file)); bzero(fp, sizeof(struct file)); f->f_fsdata = (void *)fp; if ((isonum_711(rec.flags) & 2) != 0) { fp->f_flags = F_ISDIR; } if (first) { fp->f_flags |= F_ROOTDIR; /* Check for Rock Ridge since we didn't in the loop above. */ bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length); twiddle(1); rc = f->f_dev->dv_strategy(f->f_devdata, F_READ, cdb2devb(bno), ISO_DEFAULT_BLOCK_SIZE, buf, &read); if (rc) goto out; if (read != ISO_DEFAULT_BLOCK_SIZE) { rc = EIO; goto out; } dp = (struct iso_directory_record *)buf; use_rrip = rrip_check(f, dp, &lenskip); } if (use_rrip) { fp->f_flags |= F_RR; fp->f_susp_skip = lenskip; } fp->f_off = 0; fp->f_bno = isonum_733(rec.extent) + isonum_711(rec.ext_attr_length); fp->f_size = isonum_733(rec.size); free(buf); return 0; out: if (fp) free(fp); free(buf); return rc; }
int cd9660_open(const char *path, struct open_file *f) { struct file *fp = 0; void *buf; struct iso_primary_descriptor *vd; size_t buf_size, nread, psize, dsize; daddr_t bno; int parent, ent; struct ptable_ent *pp; struct iso_directory_record *dp = 0; int rc; /* First find the volume descriptor */ buf_size = ISO_DEFAULT_BLOCK_SIZE; buf = alloc(buf_size); vd = buf; for (bno = 16;; bno++) { #if !defined(LIBSA_NO_TWIDDLE) twiddle(); #endif rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno), ISO_DEFAULT_BLOCK_SIZE, buf, &nread); if (rc) goto out; if (nread != ISO_DEFAULT_BLOCK_SIZE) { rc = EIO; goto out; } rc = EINVAL; if (memcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0) goto out; if (isonum_711(vd->type) == ISO_VD_END) goto out; if (isonum_711(vd->type) == ISO_VD_PRIMARY) break; } if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE) goto out; /* Now get the path table and lookup the directory of the file */ bno = isonum_732(vd->type_m_path_table); psize = isonum_733(vd->path_table_size); if (psize > ISO_DEFAULT_BLOCK_SIZE) { dealloc(buf, ISO_DEFAULT_BLOCK_SIZE); buf = alloc(buf_size = roundup(psize, ISO_DEFAULT_BLOCK_SIZE)); } #if !defined(LIBSA_NO_TWIDDLE) twiddle(); #endif rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno), buf_size, buf, &nread); if (rc) goto out; if (nread != buf_size) { rc = EIO; goto out; } parent = 1; pp = (struct ptable_ent *)buf; ent = 1; bno = isonum_732(pp->block) + isonum_711(pp->extlen); rc = ENOENT; /* * Remove extra separators */ while (*path == '/') path++; while (*path) { if ((char *)pp >= (char *)buf + psize) break; if (isonum_722(pp->parent) != parent) break; if (!pnmatch(path, pp)) { pp = (struct ptable_ent *)((char *)pp + PTSIZE(pp)); ent++; continue; } path += isonum_711(pp->namlen) + 1; parent = ent; bno = isonum_732(pp->block) + isonum_711(pp->extlen); while ((char *)pp < (char *)buf + psize) { if (isonum_722(pp->parent) == parent) break; pp = (struct ptable_ent *)((char *)pp + PTSIZE(pp)); ent++; } } /* * Now bno has the start of the directory that supposedly * contains the file */ bno--; dsize = 1; /* Something stupid, but > 0 XXX */ for (psize = 0; psize < dsize;) { if (!(psize % ISO_DEFAULT_BLOCK_SIZE)) { bno++; #if !defined(LIBSA_NO_TWIDDLE) twiddle(); #endif rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, cdb2devb(bno), ISO_DEFAULT_BLOCK_SIZE, buf, &nread); if (rc) goto out; if (nread != ISO_DEFAULT_BLOCK_SIZE) { rc = EIO; goto out; } dp = (struct iso_directory_record *)buf; } if (!isonum_711(dp->length)) { if ((void *)dp == buf) psize += ISO_DEFAULT_BLOCK_SIZE; else psize = roundup(psize, ISO_DEFAULT_BLOCK_SIZE); continue; } if (dsize == 1) dsize = isonum_733(dp->size); if (dirmatch(path, dp)) break; psize += isonum_711(dp->length); dp = (struct iso_directory_record *) ((char *)dp + isonum_711(dp->length)); } if (psize >= dsize) { rc = ENOENT; goto out; } /* allocate file system specific data structure */ fp = alloc(sizeof(struct file)); memset(fp, 0, sizeof(struct file)); f->f_fsdata = (void *)fp; fp->off = 0; fp->bno = isonum_733(dp->extent); fp->size = isonum_733(dp->size); dealloc(buf, buf_size); return 0; out: if (fp) dealloc(fp, sizeof(struct file)); dealloc(buf, buf_size); return rc; }