/* glob1 -- glob pattern path against the file system */ static List *glob1(const char *pattern, const char *quote) { const char *s, *q; char *d, *p, *qd, *qp; size_t psize; List *matched; static char *dir = NULL, *pat = NULL, *qdir = NULL, *qpat = NULL, *raw = NULL; static size_t dsize = 0; assert(quote != QUOTED); if ((psize = strlen(pattern) + 1) > dsize || pat == NULL) { pat = erealloc(pat, psize); raw = erealloc(raw, psize); dir = erealloc(dir, psize); qpat = erealloc(qpat, psize); qdir = erealloc(qdir, psize); dsize = psize; memset(raw, 'r', psize); } d = dir; qd = qdir; q = (quote == UNQUOTED) ? raw : quote; s = pattern; if (*s == '/') while (*s == '/') *d++ = *s++, *qd++ = *q++; else while (*s != '/' && *s != '\0') *d++ = *s++, *qd++ = *q++; /* get first directory component */ *d = '\0'; /* * Special case: no slashes in the pattern, i.e., open the current directory. * Remember that w cannot consist of slashes alone (the other way *s could be * zero) since doglob gets called iff there's a metacharacter to be matched */ if (*s == '\0') return dirmatch("", ".", dir, qdir); matched = (*pattern == '/') ? mklist(mkstr(dir), NULL) : dirmatch("", ".", dir, qdir); do { size_t slashcount; SIGCHK(); for (slashcount = 0; *s == '/'; s++, q++) slashcount++; /* skip slashes */ for (p = pat, qp = qpat; *s != '/' && *s != '\0';) *p++ = *s++, *qp++ = *q++; /* get pat */ *p = '\0'; matched = listglob(matched, pat, qpat, slashcount); } while (*s != '\0' && matched != NULL); return matched; }
/* listglob -- glob a directory plus a filename pattern into a list of names */ static List *listglob(List *list, char *pattern, char *quote, size_t slashcount) { List *result, **prevp; for (result = NULL, prevp = &result; list != NULL; list = list->next) { const char *dir; size_t dirlen; static char *prefix = NULL; static size_t prefixlen = 0; assert(list->term != NULL); assert(!isclosure(list->term)); dir = getstr(list->term); dirlen = strlen(dir); if (dirlen + slashcount + 1 >= prefixlen) { prefixlen = dirlen + slashcount + 1; prefix = erealloc(prefix, prefixlen); } memcpy(prefix, dir, dirlen); memset(prefix + dirlen, '/', slashcount); prefix[dirlen + slashcount] = '\0'; *prevp = dirmatch(prefix, dir, pattern, quote); while (*prevp != NULL) prevp = &(*prevp)->next; } return result; }
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; }
static int cd9660_findfile(int disk, const char *path, int *startp, int *lenp) { 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 = 0; int rc = 0; /* First find the volume descriptor */ buf = malloc(buf_size = ISO_DEFAULT_BLOCK_SIZE); vd = buf; for (bno = 16;; bno++) { read = pread(disk, buf, ISO_DEFAULT_BLOCK_SIZE, cdb2off(bno)); 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) { rc = EINVAL; goto out; } rec = *(struct iso_directory_record *) vd->root_directory_record; if (*path == '/') path++; /* eat leading '/' */ 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) { read = pread(disk, buf, ISO_DEFAULT_BLOCK_SIZE, cdb2off(bno + boff)); 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; } if (dirmatch(path, dp)) break; dp = (struct iso_directory_record *) ((char *) dp + isonum_711(dp->length)); 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 '/' */ } *startp = cdb2off(isonum_733(rec.extent) + isonum_711(rec.ext_attr_length)); *lenp = isonum_733(rec.size); rc = 0; out: free(buf); return rc; }