ISO9660 fs RockRidge filename extensions
This commit is contained in:
@@ -13,7 +13,7 @@ cp -v boot/limine/BOOTX64.EFI boot/limine/BOOTIA32.EFI iso_root/EFI/BOOT
|
|||||||
|
|
||||||
cp -v mop3dist.tar.lz4 iso_root/boot
|
cp -v mop3dist.tar.lz4 iso_root/boot
|
||||||
|
|
||||||
xorriso -as mkisofs -R -r -J -b boot/limine/limine-bios-cd.bin \
|
xorriso -as mkisofs -R -r -b boot/limine/limine-bios-cd.bin \
|
||||||
-no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \
|
-no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus \
|
||||||
-apm-block-size 2048 --efi-boot boot/limine/limine-uefi-cd.bin \
|
-apm-block-size 2048 --efi-boot boot/limine/limine-uefi-cd.bin \
|
||||||
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
-efi-boot-part --efi-boot-image --protective-msdos-label \
|
||||||
|
|||||||
@@ -296,8 +296,13 @@ DEFINE_VFS_READ_DIR_ENTRY (iso9660fs_read_dir_entry) {
|
|||||||
|
|
||||||
if (ent == entry_num) {
|
if (ent == entry_num) {
|
||||||
char namebuf[256];
|
char namebuf[256];
|
||||||
|
size_t out_len;
|
||||||
|
|
||||||
iso9660fs_copy_visible_name (namebuf, sizeof (namebuf), dirent);
|
const char* rockridge_name = l9660_get_rockridge_name (dirent, namebuf, &out_len);
|
||||||
|
|
||||||
|
if (rockridge_name == NULL) {
|
||||||
|
iso9660fs_copy_visible_name (namebuf, sizeof (namebuf), dirent);
|
||||||
|
}
|
||||||
|
|
||||||
entry->path[0] = '\0';
|
entry->path[0] = '\0';
|
||||||
|
|
||||||
|
|||||||
@@ -21,13 +21,9 @@
|
|||||||
#include <libk/string.h>
|
#include <libk/string.h>
|
||||||
#include <sys/debug.h>
|
#include <sys/debug.h>
|
||||||
|
|
||||||
#ifdef L9660_HAVE_STDIO
|
|
||||||
#include <stdio.h>
|
|
||||||
#else
|
|
||||||
#define SEEK_END L9660_SEEK_END
|
#define SEEK_END L9660_SEEK_END
|
||||||
#define SEEK_SET L9660_SEEK_SET
|
#define SEEK_SET L9660_SEEK_SET
|
||||||
#define SEEK_CUR L9660_SEEK_CUR
|
#define SEEK_CUR L9660_SEEK_CUR
|
||||||
#endif
|
|
||||||
|
|
||||||
#define DENT_EXISTS (1 << 0)
|
#define DENT_EXISTS (1 << 0)
|
||||||
#define DENT_ISDIR (1 << 1)
|
#define DENT_ISDIR (1 << 1)
|
||||||
@@ -46,17 +42,14 @@
|
|||||||
#define READ32(v) (((v).le[0]) | ((v).le[1] << 8) | ((v).le[2]) << 16 | ((v).le[3] << 24))
|
#define READ32(v) (((v).le[0]) | ((v).le[1] << 8) | ((v).le[2]) << 16 | ((v).le[3] << 24))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef L9660_SINGLEBUFFER
|
|
||||||
#define HAVEBUFFER(f) (true)
|
#define HAVEBUFFER(f) (true)
|
||||||
#define BUF(f) ((f)->buf)
|
#define BUF(f) ((f)->buf)
|
||||||
#else
|
|
||||||
#define HAVEBUFFER(f) ((f) == last_file)
|
|
||||||
#define BUF(f) (gbuf)
|
|
||||||
|
|
||||||
static l9660_file *last_file;
|
#define ROCKRIDGE_FILENAME_MAX 0xFF
|
||||||
static char gbuf[2048];
|
|
||||||
|
|
||||||
#endif
|
#define NM_CONTINUE 0x01
|
||||||
|
#define NM_CURRENT 0x02
|
||||||
|
#define NM_PARENT 0x04
|
||||||
|
|
||||||
static char *strchrnul(const char *s, int c)
|
static char *strchrnul(const char *s, int c)
|
||||||
{
|
{
|
||||||
@@ -80,6 +73,67 @@ static inline uint32_t fnextsectpos(l9660_file *f)
|
|||||||
return (f->position + 2047) & ~2047;
|
return (f->position + 2047) & ~2047;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* l9660_get_rockridge_name (l9660_dirent* dirent, char* out, size_t *out_len) {
|
||||||
|
uint8_t* ptr = (uint8_t*)dirent + sizeof (*dirent) + dirent->name_len;
|
||||||
|
|
||||||
|
if (!(dirent->name_len & 1))
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
uint8_t* end = (uint8_t*)dirent + dirent->length;
|
||||||
|
|
||||||
|
size_t total = 0;
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
while (ptr + sizeof (l9660_su_field) <= end) {
|
||||||
|
l9660_su_field* sufield = (l9660_su_field*)ptr;
|
||||||
|
|
||||||
|
if (sufield->len < 5 || ptr + sufield->len > end)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (sufield->sign[0] == 'N' && sufield->sign[1] == 'M') {
|
||||||
|
uint8_t flags = sufield->data[0];
|
||||||
|
|
||||||
|
if ((flags & NM_CURRENT)) {
|
||||||
|
out[0] = '.';
|
||||||
|
*out_len = 1;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((flags & NM_PARENT)) {
|
||||||
|
out[0] = '.';
|
||||||
|
out[1] = '.';
|
||||||
|
*out_len = 2;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t part_len = sufield->len - 5;
|
||||||
|
if (total + part_len > ROCKRIDGE_FILENAME_MAX)
|
||||||
|
part_len = ROCKRIDGE_FILENAME_MAX - total;
|
||||||
|
|
||||||
|
memcpy (out + total, &sufield->data[1], part_len);
|
||||||
|
total += part_len;
|
||||||
|
found = true;
|
||||||
|
|
||||||
|
if (total < ROCKRIDGE_FILENAME_MAX)
|
||||||
|
out[total] = '\0';
|
||||||
|
else
|
||||||
|
out[ROCKRIDGE_FILENAME_MAX - 1] = '\0';
|
||||||
|
|
||||||
|
if (!(flags & NM_CONTINUE))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr += sufield->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
*out_len = total;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
l9660_status l9660_openfs(
|
l9660_status l9660_openfs(
|
||||||
l9660_fs *fs,
|
l9660_fs *fs,
|
||||||
bool (*read_sector)(l9660_fs *fs, void *buf, uint32_t sector))
|
bool (*read_sector)(l9660_fs *fs, void *buf, uint32_t sector))
|
||||||
@@ -152,8 +206,10 @@ static l9660_status prebuffer(l9660_file *f)
|
|||||||
|
|
||||||
static l9660_status openat_raw(l9660_file *child, l9660_dir *parent, const char *name, bool isdir)
|
static l9660_status openat_raw(l9660_file *child, l9660_dir *parent, const char *name, bool isdir)
|
||||||
{
|
{
|
||||||
|
char rr_namebuf[ROCKRIDGE_FILENAME_MAX];
|
||||||
l9660_status rv;
|
l9660_status rv;
|
||||||
l9660_dirent *dent = NULL;
|
l9660_dirent *dent = NULL;
|
||||||
|
size_t dent_rr_name_len = 0;
|
||||||
if ((rv = l9660_seekdir(parent, 0))) return rv;
|
if ((rv = l9660_seekdir(parent, 0))) return rv;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -179,24 +235,33 @@ static l9660_status openat_raw(l9660_file *child, l9660_dir *parent, const char
|
|||||||
if (!dent)
|
if (!dent)
|
||||||
return L9660_ENOENT;
|
return L9660_ENOENT;
|
||||||
|
|
||||||
/* wrong length */
|
const char* rockridge_name = l9660_get_rockridge_name (dent, rr_namebuf, &dent_rr_name_len);
|
||||||
if (seglen > dent->name_len)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* check name */
|
if (rockridge_name == NULL) {
|
||||||
if (memcmp(seg, dent->name, seglen) != 0)
|
/* wrong length */
|
||||||
continue;
|
if (seglen != dent->name_len)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* check for a revision tag */
|
/* check name */
|
||||||
if (dent->name_len > seglen && dent->name[seglen] != ';')
|
if (memcmp(seg, dent->name, seglen) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* all tests pass */
|
/* check for a revision tag */
|
||||||
break;
|
if (dent->name_len > seglen && dent->name[seglen] != ';')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* all tests pass */
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (seglen == dent_rr_name_len && memcmp (seg, rockridge_name, seglen) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
child->fs = parent->file.fs;
|
child->fs = parent->file.fs;
|
||||||
child->first_sector = READ32(dent->sector) + dent->xattr_length;
|
child->first_sector = READ32(dent->sector);
|
||||||
child->length = READ32(dent->size);
|
child->length = READ32(dent->size);
|
||||||
child->position = 0;
|
child->position = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -18,23 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef LIB9660_H
|
#ifndef LIB9660_H
|
||||||
#define LIB9660_H
|
#define LIB9660_H
|
||||||
#include <stdint.h>
|
|
||||||
#include <stddef.h>
|
#include <libk/std.h>
|
||||||
#include <stdbool.h>
|
#include <aux/compiler.h>
|
||||||
|
|
||||||
struct proc;
|
struct proc;
|
||||||
struct reschedule_ctx;
|
struct reschedule_ctx;
|
||||||
|
|
||||||
#ifdef L9660_HAVE_STDIO
|
|
||||||
#include <stdio.h>
|
|
||||||
#define L9660_SEEK_END SEEK_END
|
|
||||||
#define L9660_SEEK_SET SEEK_SET
|
|
||||||
#define L9660_SEEK_CUR SEEK_CUR
|
|
||||||
#else
|
|
||||||
#define L9660_SEEK_END -1
|
#define L9660_SEEK_END -1
|
||||||
#define L9660_SEEK_SET 0
|
#define L9660_SEEK_SET 0
|
||||||
#define L9660_SEEK_CUR +1
|
#define L9660_SEEK_CUR +1
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Our error return format */
|
/* Our error return format */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -56,22 +49,22 @@ typedef enum {
|
|||||||
} l9660_status;
|
} l9660_status;
|
||||||
|
|
||||||
/* ISO9660 uses big/little/dual endian integers */
|
/* ISO9660 uses big/little/dual endian integers */
|
||||||
typedef struct { uint8_t le[2]; } l9660_luint16;
|
typedef struct { uint8_t le[2]; } PACKED l9660_luint16;
|
||||||
typedef struct { uint8_t be[2]; } l9660_buint16;
|
typedef struct { uint8_t be[2]; } PACKED l9660_buint16;
|
||||||
typedef struct { uint8_t le[2], be[2]; } l9660_duint16;
|
typedef struct { uint8_t le[2], be[2]; } PACKED l9660_duint16;
|
||||||
typedef struct { uint8_t le[4]; } l9660_luint32;
|
typedef struct { uint8_t le[4]; } PACKED l9660_luint32;
|
||||||
typedef struct { uint8_t be[4]; } l9660_buint32;
|
typedef struct { uint8_t be[4]; } PACKED l9660_buint32;
|
||||||
typedef struct { uint8_t le[4], be[4]; } l9660_duint32;
|
typedef struct { uint8_t le[4], be[4]; } PACKED l9660_duint32;
|
||||||
|
|
||||||
/* Descriptor time format */
|
/* Descriptor time format */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char d[17];
|
char d[17];
|
||||||
} l9660_desctime;
|
} PACKED l9660_desctime;
|
||||||
|
|
||||||
/* File time format */
|
/* File time format */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char d[7];
|
char d[7];
|
||||||
} l9660_filetime;
|
} PACKED l9660_filetime;
|
||||||
|
|
||||||
/* Directory entry */
|
/* Directory entry */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -86,14 +79,21 @@ typedef struct {
|
|||||||
l9660_duint16 vol_seq_number;
|
l9660_duint16 vol_seq_number;
|
||||||
uint8_t name_len;
|
uint8_t name_len;
|
||||||
char name[/*name_len*/];
|
char name[/*name_len*/];
|
||||||
} l9660_dirent;
|
} PACKED l9660_dirent;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char sign[2];
|
||||||
|
uint8_t len;
|
||||||
|
uint8_t version;
|
||||||
|
char data[];
|
||||||
|
} PACKED l9660_su_field;
|
||||||
|
|
||||||
/* Volume descriptor header */
|
/* Volume descriptor header */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
char magic[5];
|
char magic[5];
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
} l9660_vdesc_header;
|
} PACKED l9660_vdesc_header;
|
||||||
|
|
||||||
/* Primary volume descriptor */
|
/* Primary volume descriptor */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -115,7 +115,7 @@ typedef struct {
|
|||||||
union {
|
union {
|
||||||
l9660_dirent root_dir_ent;
|
l9660_dirent root_dir_ent;
|
||||||
char pad3[34];
|
char pad3[34];
|
||||||
} rde;
|
} PACKED rde;
|
||||||
char volume_set_id[128];
|
char volume_set_id[128];
|
||||||
char data_preparer_id[128];
|
char data_preparer_id[128];
|
||||||
char app_id[128];
|
char app_id[128];
|
||||||
@@ -130,13 +130,13 @@ typedef struct {
|
|||||||
char pad4[1];
|
char pad4[1];
|
||||||
char app_reserved[512];
|
char app_reserved[512];
|
||||||
char reserved[653];
|
char reserved[653];
|
||||||
} l9660_vdesc_primary;
|
} PACKED l9660_vdesc_primary;
|
||||||
|
|
||||||
/* A generic volume descriptor (i.e. 2048 bytes) */
|
/* A generic volume descriptor (i.e. 2048 bytes) */
|
||||||
typedef union {
|
typedef union {
|
||||||
l9660_vdesc_header hdr;
|
l9660_vdesc_header hdr;
|
||||||
char _bits[2048];
|
char _bits[2048];
|
||||||
} l9660_vdesc;
|
} PACKED l9660_vdesc;
|
||||||
|
|
||||||
/* File system structure.
|
/* File system structure.
|
||||||
* Stick this inside your own structure and cast/offset as appropriate to store
|
* Stick this inside your own structure and cast/offset as appropriate to store
|
||||||
@@ -146,25 +146,15 @@ typedef struct l9660_fs {
|
|||||||
void* udata;
|
void* udata;
|
||||||
struct proc* proc;
|
struct proc* proc;
|
||||||
struct reschedule_ctx* rctx;
|
struct reschedule_ctx* rctx;
|
||||||
#ifdef L9660_SINGLEBUFFER
|
/* Sector buffer to hold the PVD */
|
||||||
union {
|
l9660_vdesc pvd;
|
||||||
l9660_dirent root_dir_ent;
|
/* read_sector func */
|
||||||
char root_dir_pad[34];
|
bool (*read_sector)(struct l9660_fs *fs, void *buf, uint32_t sector);
|
||||||
};
|
|
||||||
#else
|
|
||||||
/* Sector buffer to hold the PVD */
|
|
||||||
l9660_vdesc pvd;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* read_sector func */
|
|
||||||
bool (*read_sector)(struct l9660_fs *fs, void *buf, uint32_t sector);
|
|
||||||
} l9660_fs;
|
} l9660_fs;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
#ifndef L9660_SINGLEBUFFER
|
|
||||||
/* single sector buffer */
|
/* single sector buffer */
|
||||||
char buf[2048];
|
char buf[2048];
|
||||||
#endif
|
|
||||||
l9660_fs *fs;
|
l9660_fs *fs;
|
||||||
uint32_t first_sector;
|
uint32_t first_sector;
|
||||||
uint32_t position;
|
uint32_t position;
|
||||||
@@ -207,4 +197,6 @@ l9660_status l9660_seek(l9660_file *file, int whence, int32_t offset);
|
|||||||
/*! Return the current position (suitable for passing to l9660_seek(file, SEEK_SET, ...)) */
|
/*! Return the current position (suitable for passing to l9660_seek(file, SEEK_SET, ...)) */
|
||||||
uint32_t l9660_tell(l9660_file *file);
|
uint32_t l9660_tell(l9660_file *file);
|
||||||
|
|
||||||
|
const char* l9660_get_rockridge_name (l9660_dirent* dirent, char* out, size_t *out_len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user