/* * * (c) 2005-2009 Laurent Vivier * * 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; }