summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/fs/iso9660/iso9660_mount.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/fs/iso9660/iso9660_mount.c')
-rw-r--r--qemu/roms/openbios/fs/iso9660/iso9660_mount.c210
1 files changed, 210 insertions, 0 deletions
diff --git a/qemu/roms/openbios/fs/iso9660/iso9660_mount.c b/qemu/roms/openbios/fs/iso9660/iso9660_mount.c
new file mode 100644
index 000000000..a58170408
--- /dev/null
+++ b/qemu/roms/openbios/fs/iso9660/iso9660_mount.c
@@ -0,0 +1,210 @@
+/*
+ *
+ * (c) 2005-2009 Laurent Vivier <Laurent@vivier.eu>
+ *
+ * This file has been copied from EMILE, http://emile.sf.net
+ *
+ * some parts from mkisofs (c) J. Schilling
+ *
+ */
+
+#include "libiso9660.h"
+#include "libopenbios/bindings.h"
+#include "libc/diskio.h"
+
+void iso9660_name(iso9660_VOLUME *volume, struct iso_directory_record *idr, char *buffer)
+{
+ int j;
+ unsigned char ul, uc;
+
+ buffer[0] = 0;
+ if (idr->name_len[0] == 1 && idr->name[0] == 0)
+ strcpy(buffer, ".");
+ else if (idr->name_len[0] == 1 && idr->name[0] == 1)
+ strcpy(buffer, "..");
+ else {
+ switch (volume->ucs_level) {
+ case 3:
+ case 2:
+ case 1:
+ /*
+ * Unicode name.
+ */
+
+ for (j = 0; j < (int)idr->name_len[0] / 2; j++) {
+ ul = idr->name[j*2+1];
+
+ /*
+ * unicode convertion
+ * up = unls->unls_uni2cs[uh];
+ *
+ * if (up == NULL)
+ * uc = '\0';
+ * else
+ * uc = up[ul];
+ *
+ * we use only low byte
+ */
+
+ uc = ul;
+
+ buffer[j] = uc ? uc : '_';
+ }
+ buffer[idr->name_len[0]/2] = '\0';
+ break;
+ case 0:
+ /*
+ * Normal non-Unicode name.
+ */
+ strncpy(buffer, idr->name, idr->name_len[0]);
+ buffer[idr->name_len[0]] = 0;
+ break;
+ default:
+ /*
+ * Don't know how to do these yet. Maybe they are the same
+ * as one of the above.
+ */
+ break;
+ }
+ }
+}
+
+iso9660_VOLUME *iso9660_mount(int fd)
+{
+ iso9660_VOLUME* volume;
+ struct iso_primary_descriptor *jpd;
+ struct iso_primary_descriptor ipd;
+ int block;
+ int ucs_level = 0;
+
+ /* read filesystem descriptor */
+
+ seek_io(fd, 16 * ISOFS_BLOCK_SIZE);
+ read_io(fd, &ipd, sizeof (ipd));
+
+ /*
+ * High sierra:
+ *
+ * DESC TYPE == 1 (VD_SFS) offset 8 len 1
+ * STR ID == "CDROM" offset 9 len 5
+ * STD_VER == 1 offset 14 len 1
+ */
+
+ /* High Sierra format ? */
+
+ if ((((char *)&ipd)[8] == 1) &&
+ (strncmp(&((char *)&ipd)[9], "CDROM", 5) == 0) &&
+ (((char *)&ipd)[14] == 1)) {
+ printk("Incompatible format: High Sierra format\n");
+ return NULL;
+ }
+
+ /*
+ * ISO 9660:
+ *
+ * DESC TYPE == 1 (VD_PVD) offset 0 len 1
+ * STR ID == "CD001" offset 1 len 5
+ * STD_VER == 1 offset 6 len 1
+ */
+
+ /* NOT ISO 9660 format ? */
+
+ if ((ipd.type[0] != ISO_VD_PRIMARY) ||
+ (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) ||
+ (ipd.version[0] != 1)) {
+ return NULL;
+ }
+
+ /* UCS info */
+
+ block = 16;
+
+ jpd = (struct iso_primary_descriptor *)
+ malloc(sizeof(struct iso_primary_descriptor));
+ if (jpd == NULL)
+ return NULL;
+
+ memcpy(jpd, &ipd, sizeof (ipd));
+ while ((uint8_t)jpd->type[0] != ISO_VD_END) {
+
+ /*
+ * If Joliet UCS escape sequence found, we may be wrong
+ */
+
+ if (jpd->unused3[0] == '%' &&
+ jpd->unused3[1] == '/' &&
+ (jpd->unused3[3] == '\0' ||
+ jpd->unused3[3] == ' ') &&
+ (jpd->unused3[2] == '@' ||
+ jpd->unused3[2] == 'C' ||
+ jpd->unused3[2] == 'E')) {
+
+ if (jpd->version[0] != 1)
+ break;
+ }
+
+ block++;
+ seek_io(fd, block * ISOFS_BLOCK_SIZE);
+ read_io(fd, jpd, sizeof (*jpd));
+ }
+
+ ucs_level = 0;
+ if (((unsigned char) jpd->type[0] == ISO_VD_END)) {
+ memcpy(jpd, &ipd, sizeof (ipd));
+ } else {
+ switch (jpd->unused3[2]) {
+ case '@':
+ ucs_level = 1;
+ break;
+ case 'C':
+ ucs_level = 2;
+ break;
+ case 'E':
+ ucs_level = 3;
+ break;
+ }
+
+ if (ucs_level && jpd->unused3[3] == ' ')
+ printk("Warning: Joliet escape sequence uses illegal space at offset 3\n");
+ }
+
+ volume = (iso9660_VOLUME*)malloc(sizeof(iso9660_VOLUME));
+ if (volume == NULL)
+ return NULL;
+
+ volume->descriptor = jpd;
+ volume->ucs_level = ucs_level;
+ volume->fd = fd;
+
+ return volume;
+}
+
+int iso9660_umount(iso9660_VOLUME* volume)
+{
+ if (volume == NULL)
+ return -1;
+ free(volume->descriptor);
+ free(volume);
+ return 0;
+}
+
+int iso9660_probe(int fd, long long offset)
+{
+ struct iso_primary_descriptor ipd;
+
+ seek_io(fd, 16 * ISOFS_BLOCK_SIZE + offset);
+ read_io(fd, &ipd, sizeof (ipd));
+
+ if ((ipd.type[0] != ISO_VD_PRIMARY) ||
+ (strncmp(ipd.id, ISO_STANDARD_ID, sizeof (ipd.id)) != 0) ||
+ (ipd.version[0] != 1)) {
+ return 0;
+ }
+
+ return -1;
+}
+
+struct iso_directory_record *iso9660_get_root_node(iso9660_VOLUME* volume)
+{
+ return (struct iso_directory_record *)volume->descriptor->root_directory_record;
+}