summaryrefslogtreecommitdiffstats
path: root/lib/libstand
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2001-11-06 22:31:10 +0000
committerjhb <jhb@FreeBSD.org>2001-11-06 22:31:10 +0000
commit76b3e8adcb3c9cdb8ea9e12cdff6cc0f301d66e1 (patch)
treef38f61a943cefa06d34ec543a7a3fe99b56ac43f /lib/libstand
parent0a413f6f8075081d777132df6dff26f9cb5478eb (diff)
downloadFreeBSD-src-76b3e8adcb3c9cdb8ea9e12cdff6cc0f301d66e1.zip
FreeBSD-src-76b3e8adcb3c9cdb8ea9e12cdff6cc0f301d66e1.tar.gz
- Change the f_isdir field of struct file to be a flags field and two
new flags: F_ROOTDIR and F_RR (Rock Ridge present). - Cache the SUSP LEN_SKP parameter in struct file as well. - If we open() '/', then force a read of the directory's contents so we can examine the directory record of '.' to see if Rock Ridge is present. - If Rock Ridge extensions are present, lookup Rock Ridge names in readdir().
Diffstat (limited to 'lib/libstand')
-rw-r--r--lib/libstand/cd9660.c67
1 files changed, 54 insertions, 13 deletions
diff --git a/lib/libstand/cd9660.c b/lib/libstand/cd9660.c
index f6ff294..1c43e75 100644
--- a/lib/libstand/cd9660.c
+++ b/lib/libstand/cd9660.c
@@ -92,13 +92,18 @@ struct fs_ops cd9660_fsops = {
cd9660_readdir
};
+#define F_ISDIR 0x0001 /* Directory */
+#define F_ROOTDIR 0x0002 /* Root directory */
+#define F_RR 0x0004 /* Rock Ridge on this volume */
+
struct file {
- int f_isdir; /* nonzero if file is directory */
+ int f_flags; /* file flags */
off_t f_off; /* Current offset within file */
daddr_t f_bno; /* Starting block number */
off_t f_size; /* Size of file */
daddr_t f_buf_blkno; /* block number of data block */
char *f_buf; /* buffer for data block */
+ int f_susp_skip; /* len_skip for SUSP records */
};
struct ptable_ent {
@@ -376,7 +381,30 @@ cd9660_open(const char *path, struct open_file *f)
bzero(fp, sizeof(struct file));
f->f_fsdata = (void *)fp;
- fp->f_isdir = (isonum_711(rec.flags) & 2) != 0;
+ 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();
+ 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);
@@ -473,7 +501,8 @@ cd9660_readdir(struct open_file *f, struct dirent *d)
struct iso_directory_record *ep;
size_t buf_size, reclen, namelen;
int error = 0;
- char *buf;
+ int lenskip;
+ char *buf, *name;
again:
if (fp->f_off >= fp->f_size)
@@ -492,9 +521,26 @@ again:
goto again;
}
- namelen = isonum_711(ep->name_len);
- if (namelen == 1 && ep->name[0] == 1)
- namelen = 2;
+ if (fp->f_flags & F_RR) {
+ if (fp->f_flags & F_ROOTDIR && fp->f_off == 0)
+ lenskip = 0;
+ else
+ lenskip = fp->f_susp_skip;
+ name = rrip_lookup_name(f, ep, lenskip, &namelen);
+ } else
+ name = NULL;
+ if (name == NULL) {
+ namelen = isonum_711(ep->name_len);
+ name = ep->name;
+ if (namelen == 1) {
+ if (ep->name[0] == 0)
+ name = ".";
+ else if (ep->name[0] == 1) {
+ namelen = 2;
+ name = "..";
+ }
+ }
+ }
reclen = sizeof(struct dirent) - (MAXNAMLEN+1) + namelen + 1;
reclen = (reclen + 3) & ~3;
@@ -506,12 +552,7 @@ again:
d->d_type = DT_REG;
d->d_namlen = namelen;
- if (isonum_711(ep->name_len) == 1 && ep->name[0] == 0)
- strcpy(d->d_name, ".");
- else if (isonum_711(ep->name_len) == 1 && ep->name[0] == 1)
- strcpy(d->d_name, "..");
- else
- bcopy(ep->name, d->d_name, d->d_namlen);
+ bcopy(name, d->d_name, d->d_namlen);
d->d_name[d->d_namlen] = 0;
fp->f_off += isonum_711(ep->length);
@@ -552,7 +593,7 @@ cd9660_stat(struct open_file *f, struct stat *sb)
/* only important stuff */
sb->st_mode = S_IRUSR | S_IRGRP | S_IROTH;
- if (fp->f_isdir)
+ if (fp->f_flags & F_ISDIR)
sb->st_mode |= S_IFDIR;
else
sb->st_mode |= S_IFREG;
OpenPOWER on IntegriCloud