void* pg;
uint32_t flags;
uint32_t fpos;
+ uint32_t len;
};
void
#include <lunaix/clock.h>
#include <lunaix/device.h>
+#include <lunaix/fs.h>
#include <lunaix/types.h>
#define ISO_SIGNATURE_LO 0x30304443UL
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.
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;
// 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;
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];
};
time_t
iso9660_dt2unix(struct iso_datetime* isodt);
+time_t
+iso9660_dt22unix(struct iso_datetime2* isodt2);
+
void
iso9660_init();
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);
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 */
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,
.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
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;
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
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);
}
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);
--- /dev/null
+#include <lunaix/fs/iso9660.h>
+
+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
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
pcache_set_dirty(pcache, pg);
+ pg->len = pg_off + wr_bytes;
buf_off += wr_bytes;
fpos += wr_bytes;
}
} 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;