From: Minep Date: Sun, 13 Nov 2022 00:08:59 +0000 (+0000) Subject: feat: (iso9660) rock ridge extension X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/40941f94f7c8522f65f9ebc425a300d40412bc16?hp=1e54f1850eda97e3b41c302b72c07a1f9cc4d637 feat: (iso9660) rock ridge extension fix: (pcache) over-reading the page cache --- diff --git a/lunaix-os/includes/lunaix/fs.h b/lunaix-os/includes/lunaix/fs.h index 024b4ea..075cc01 100644 --- a/lunaix-os/includes/lunaix/fs.h +++ b/lunaix-os/includes/lunaix/fs.h @@ -275,6 +275,7 @@ struct pcache_pg void* pg; uint32_t flags; uint32_t fpos; + uint32_t len; }; void diff --git a/lunaix-os/includes/lunaix/fs/iso9660.h b/lunaix-os/includes/lunaix/fs/iso9660.h index de433d4..9d16961 100644 --- a/lunaix-os/includes/lunaix/fs/iso9660.h +++ b/lunaix-os/includes/lunaix/fs/iso9660.h @@ -14,6 +14,7 @@ #include #include +#include #include #define ISO_SIGNATURE_LO 0x30304443UL @@ -135,22 +136,24 @@ struct iso_var_mdu u8_t content[0]; } PACKED; +struct iso_datetime2 +{ + u8_t year; + u8_t month; + u8_t day; + u8_t hour; + u8_t min; + u8_t sec; + u8_t gmt; +} PACKED; + // (9.1) Directory Record [Embedded into Variable MDU] struct iso_drecord { u8_t xattr_len; iso_bbo32_t extent_addr; iso_bbo32_t data_size; - struct - { - u8_t year; - u8_t month; - u8_t day; - u8_t hour; - u8_t min; - u8_t sec; - u8_t gmt; - } PACKED mktime; // Time the record is made, see 9.1.5 + struct iso_datetime2 PACKED mktime; // Time the record is made, see 9.1.5 u8_t flags; u8_t fu_sz; // size of file unit (FU) u8_t gap_sz; // size of gap if FU is interleaved. @@ -158,15 +161,6 @@ struct iso_drecord struct iso_var_mdu name; } PACKED; -// (9.4) L-Path Table Record. [Embedded into Variable MDU] -struct iso_precord -{ - u8_t xattr_len; - u32_t extent_addr; - u8_t parent; // indexed into path table - u8_t id[0]; // length = iso_var_mdu::len -} PACKED; - struct iso_xattr { iso_bbo16_t owner; @@ -190,20 +184,91 @@ struct iso_xattr // It however marked as optional, hence we ignore it. } PACKED; -struct iso_ptable +/// +/// -------- IEEE P1281 SUSP --------- +/// + +#define ISOSU_ER 0x5245 +#define ISOSU_ST 0x5453 + +struct isosu_base { - u32_t start_lba; - u32_t current_lba; - u32_t size; - u32_t range_lower; - u32_t range_upper; - void* ptable_part; -}; + u16_t signature; + u8_t length; + u8_t version; +} PACKED; + +struct isosu_er +{ + struct isosu_base header; + u8_t id_len; + u8_t des_len; + u8_t src_len; + u8_t ext_ver; + u8_t id_des_src[0]; +} PACKED; + +/// +/// -------- Rock Ridge Extension -------- +/// + +#define ISORR_PX 0x5850 +#define ISORR_PN 0x4e50 +#define ISORR_SL 0x4c53 +#define ISORR_NM 0x4d4e +#define ISORR_TF 0x4654 + +#define ISORR_NM_CONT 0x1 + +#define ISORR_TF_CTIME 0x1 +#define ISORR_TF_MTIME 0x2 +#define ISORR_TF_ATIME 0x4 +#define ISORR_TF_LONG_FORM 0x80 + +struct isorr_px +{ + struct isosu_base header; + iso_bbo32_t mode; + iso_bbo32_t link; + iso_bbo32_t uid; + iso_bbo32_t gid; + iso_bbo32_t sn; +} PACKED; + +struct isorr_pn +{ + struct isosu_base header; + iso_bbo32_t dev_hi; + iso_bbo32_t dev_lo; +} PACKED; + +struct isorr_sl +{ + struct isosu_base header; + u8_t flags; + char symlink[0]; +} PACKED; + +struct isorr_nm +{ + struct isosu_base header; + u8_t flags; + char name[0]; +} PACKED; + +struct isorr_tf +{ + struct isosu_base header; + u8_t flags; + char times[0]; +} PACKED; + +/// +/// -------- VFS integration --------- +/// struct iso_inode { - time_t ctime; - time_t mtime; u32_t record_fmt; u32_t fu_size; u32_t gap_size; @@ -216,9 +281,13 @@ struct iso_drecache u32_t extent_addr; u32_t data_size; u32_t xattr_len; + u32_t fno; u32_t fu_size; u32_t gap_size; u32_t flags; + time_t ctime; + time_t atime; + time_t mtime; struct hstr name; char name_val[ISO9660_IDLEN]; }; @@ -238,6 +307,9 @@ iso9660_fill_inode(struct v_inode* inode, struct iso_drecache* dir, int ino); time_t iso9660_dt2unix(struct iso_datetime* isodt); +time_t +iso9660_dt22unix(struct iso_datetime2* isodt2); + void iso9660_init(); @@ -245,7 +317,9 @@ int iso9660_setup_dnode(struct v_dnode* dnode, struct v_inode* inode); void -iso9660_fill_drecache(struct iso_drecache* cache, struct iso_drecord* drec); +iso9660_fill_drecache(struct iso_drecache* cache, + struct iso_drecord* drec, + u32_t len); int iso9660_dir_lookup(struct v_inode* this, struct v_dnode* dnode); @@ -268,4 +342,13 @@ iso9660_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos); int iso9660_seek(struct v_inode* inode, size_t offset); +int +isorr_parse_px(struct iso_drecache* cache, void* px_start); + +int +isorr_parse_nm(struct iso_drecache* cache, void* nm_start); + +int +isorr_parse_tf(struct iso_drecache* cache, void* tf_start); + #endif /* __LUNAIX_ISO9660_H */ diff --git a/lunaix-os/kernel/fs/iso9660/directory.c b/lunaix-os/kernel/fs/iso9660/directory.c index 816f6eb..e1b3789 100644 --- a/lunaix-os/kernel/fs/iso9660/directory.c +++ b/lunaix-os/kernel/fs/iso9660/directory.c @@ -10,7 +10,9 @@ extern struct cake_pile* drec_cache_pile; void -iso9660_fill_drecache(struct iso_drecache* cache, struct iso_drecord* drec) +iso9660_fill_drecache(struct iso_drecache* cache, + struct iso_drecord* drec, + u32_t drec_len) { *cache = (struct iso_drecache){ .data_size = drec->data_size.le, .extent_addr = drec->extent_addr.le, @@ -18,16 +20,44 @@ iso9660_fill_drecache(struct iso_drecache* cache, struct iso_drecord* drec) .fu_size = drec->fu_sz ? drec->fu_sz : 1, .gap_size = drec->gap_sz, .xattr_len = drec->xattr_len }; - u32_t l = drec->name.len; - while (l < (u32_t)-1 && drec->name.content[l--] != ';') - ; - l++; - l = l ? l : drec->name.len; - l = MIN(l, ISO9660_IDLEN - 1); - - strncpy(cache->name_val, drec->name.content, l); - cache->name = HSTR(cache->name_val, l); - hstr_rehash(&cache->name, HSTR_FULL_HASH); + u32_t padding = ((drec->name.len + sizeof(drec->name)) % 2) != 0; + u32_t su_offset = drec->name.len + sizeof(struct iso_drecord) + padding; + int su_len = drec_len - su_offset - 2, i = 0; + + while (i < su_len) { + struct isosu_base* su_entry = + (struct isosu_base*)((void*)drec + su_offset + i); + switch (su_entry->signature) { + case ISORR_NM: + i += isorr_parse_nm(cache, (void*)su_entry); + break; + case ISORR_PX: + i += isorr_parse_px(cache, (void*)su_entry); + break; + case ISORR_TF: + i += isorr_parse_tf(cache, (void*)su_entry); + break; + case ISOSU_ST: + goto done; + default: + i += su_entry->length; + break; + } + } + +done: + if (!cache->name.len) { + // Load ISO9660 file id if no NM found. + u32_t l = drec->name.len; + while (l < (u32_t)-1 && drec->name.content[l--] != ';') + ; + l = (l + 1) ? l : drec->name.len; + l = MIN(l, ISO9660_IDLEN - 1); + + strncpy(cache->name_val, drec->name.content, l); + cache->name = HSTR(cache->name_val, l); + hstr_rehash(&cache->name, HSTR_FULL_HASH); + } } int @@ -74,7 +104,7 @@ iso9660_setup_dnode(struct v_dnode* dnode, struct v_inode* inode) struct iso_drecache* cache = cake_grab(drec_cache_pile); - iso9660_fill_drecache(cache, drec); + iso9660_fill_drecache(cache, drec, mdu->len); llist_append(lead, &cache->caches); cont: blk_offset += mdu->len; diff --git a/lunaix-os/kernel/fs/iso9660/inode.c b/lunaix-os/kernel/fs/iso9660/inode.c index f88eee5..e564910 100644 --- a/lunaix-os/kernel/fs/iso9660/inode.c +++ b/lunaix-os/kernel/fs/iso9660/inode.c @@ -62,13 +62,18 @@ iso9660_fill_inode(struct v_inode* inode, struct iso_drecache* dir, int ino) return EIO; } isoino->record_fmt = xattr->record_fmt; - isoino->ctime = iso9660_dt2unix(&xattr->ctime); - isoino->mtime = iso9660_dt2unix(&xattr->mtime); + + inode->ctime = iso9660_dt2unix(&xattr->ctime); + inode->mtime = iso9660_dt2unix(&xattr->mtime); inode->lb_addr += dir->xattr_len * dir->fu_size; vfree(xattr); } + inode->ctime = dir->ctime ? dir->ctime : inode->ctime; + inode->mtime = dir->mtime ? dir->mtime : inode->mtime; + inode->atime = dir->atime ? dir->atime : inode->atime; + return 0; } \ No newline at end of file diff --git a/lunaix-os/kernel/fs/iso9660/mount.c b/lunaix-os/kernel/fs/iso9660/mount.c index 5d7bb81..51679ca 100644 --- a/lunaix-os/kernel/fs/iso9660/mount.c +++ b/lunaix-os/kernel/fs/iso9660/mount.c @@ -57,8 +57,8 @@ iso9660_mount(struct v_superblock* vsb, struct v_dnode* mount_point) vsb->ops.read_capacity = iso9660_rd_capacity; struct v_inode* rootino = vfs_i_alloc(vsb); - struct iso_drecord* dir = - iso9660_get_drecord((struct iso_var_mdu*)vprim->root_record); + struct iso_var_mdu* mdu = (struct iso_var_mdu*)vprim->root_record; + struct iso_drecord* dir = iso9660_get_drecord(mdu); if (!dir) { vfree(isovsb); @@ -67,7 +67,7 @@ iso9660_mount(struct v_superblock* vsb, struct v_dnode* mount_point) } struct iso_drecache drecache; - iso9660_fill_drecache(&drecache, dir); + iso9660_fill_drecache(&drecache, dir, mdu->len); if ((errno = iso9660_fill_inode(rootino, &drecache, 0)) < 0) { vfree(isovsb); diff --git a/lunaix-os/kernel/fs/iso9660/rockridge.c b/lunaix-os/kernel/fs/iso9660/rockridge.c new file mode 100644 index 0000000..b211fdb --- /dev/null +++ b/lunaix-os/kernel/fs/iso9660/rockridge.c @@ -0,0 +1,60 @@ +#include + +int +isorr_parse_px(struct iso_drecache* cache, void* px_start) +{ + struct isorr_px* px = (struct isorr_px*)px_start; + cache->fno = px->sn.le; + // TODO read other file attributes + return px->header.length; +} + +time_t +isorr_tf_gettime(struct isorr_tf* tf, int* index, u32_t type) +{ + time_t t = 0; + if ((tf->flags & type)) { + if ((tf->flags & ISORR_TF_LONG_FORM)) { + t = + iso9660_dt2unix((struct iso_datetime*)(tf->times + 17 * *index)); + } else { + t = + iso9660_dt22unix((struct iso_datetime2*)(tf->times + 7 * *index)); + } + *index = *index + 1; + } + return t; +} + +int +isorr_parse_tf(struct iso_drecache* cache, void* tf_start) +{ + struct isorr_tf* tf = (struct isorr_tf*)tf_start; + int i = 0; + cache->ctime = isorr_tf_gettime(tf, &i, ISORR_TF_CTIME); + cache->mtime = isorr_tf_gettime(tf, &i, ISORR_TF_MTIME); + cache->atime = isorr_tf_gettime(tf, &i, ISORR_TF_ATIME); + // TODO read other file attributes + return tf->header.length; +} + +int +isorr_parse_nm(struct iso_drecache* cache, void* nm_start) +{ + u32_t i = 0, adv = 0; + struct isorr_nm* nm; + + do { + nm = (struct isorr_nm*)(nm_start + adv); + u32_t len_name = nm->header.length - sizeof(*nm); + memcpy(cache->name_val + i, nm->name, len_name); + i += len_name; + adv += nm->header.length; + } while ((nm->flags & ISORR_NM_CONT) && i < ISO9660_IDLEN - 1); + + cache->name_val[i] = 0; + cache->name = HSTR(cache->name_val, i); + hstr_rehash(&cache->name, HSTR_FULL_HASH); + + return adv; +} \ No newline at end of file diff --git a/lunaix-os/kernel/fs/iso9660/utils.c b/lunaix-os/kernel/fs/iso9660/utils.c index 748077d..3b19c95 100644 --- a/lunaix-os/kernel/fs/iso9660/utils.c +++ b/lunaix-os/kernel/fs/iso9660/utils.c @@ -22,3 +22,14 @@ iso9660_dt2unix(struct iso_datetime* isodt) TWO_DIGIT(isodt->min), TWO_DIGIT(isodt->sec)); } + +time_t +iso9660_dt22unix(struct iso_datetime2* isodt2) +{ + return time_tounix(isodt2->year + 1900, + isodt2->month, + isodt2->day, + isodt2->hour, + isodt2->min, + isodt2->sec); +} \ No newline at end of file diff --git a/lunaix-os/kernel/fs/pcache.c b/lunaix-os/kernel/fs/pcache.c index 317e491..a6c4c31 100644 --- a/lunaix-os/kernel/fs/pcache.c +++ b/lunaix-os/kernel/fs/pcache.c @@ -115,6 +115,7 @@ pcache_write(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos) pcache_set_dirty(pcache, pg); + pg->len = pg_off + wr_bytes; buf_off += wr_bytes; fpos += wr_bytes; } @@ -146,8 +147,13 @@ pcache_read(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos) } else if (errno < 0) { break; } + pg->len = errno; } - uint32_t rd_bytes = MIN(PG_SIZE - pg_off, len - buf_off); + uint32_t rd_bytes = MIN(pg->len - pg_off, len - buf_off); + + if (!rd_bytes) + break; + memcpy((data + buf_off), pg->pg + pg_off, rd_bytes); buf_off += rd_bytes;