📄 iso9660.c
字号:
// the first entry should have no name and is for the current directory if ((i == 0) && (b_offs == sizeof(iso9660_dentry))) { if (dentry->fi_len != 0) { // XXX } /* find how many more sectors are in the directory */ s_cnt = tsk_getu32(fs->endian, dentry->data_len_m) / ISO9660_SSIZE_B; /* use the specified name instead of "." */ if (strlen(a_fn) > ISO9660_MAXNAMLEN_STD) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "iso9660_load_inodes_dir: Name argument specified is too long"); return -1; } strncpy(in_node->inode.fn, a_fn, ISO9660_MAXNAMLEN_STD + 1); if (sizeof(iso9660_dentry) % 2) b_offs++; } else { char *file_ver; // the entry has a UTF-16 name if (ctype == ISO9660_CTYPE_UTF16) { UTF16 *name16; UTF8 *name8; int retVal; name16 = (UTF16 *) & buf[b_offs]; // the name is in UTF-16 BE -- convert to LE if needed if (fs->endian & TSK_LIT_ENDIAN) { int a; for (a = 0; a < dentry->fi_len / 2; a++) { name16[i] = ((name16[i] & 0xff) << 8) + ((name16[i] & 0xff00) >> 8); } } name8 = (UTF8 *) in_node->inode.fn; retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16, (UTF16 *) & buf[b_offs + dentry->fi_len], &name8, (UTF8 *) ((uintptr_t) & in_node->inode. fn[ISO9660_MAXNAMLEN_STD]), TSKlenientConversion); if (retVal != TSKconversionOK) { if (tsk_verbose) tsk_fprintf(stderr, "iso9660_load_inodes_dir: Error converting Joliet name to UTF8: %d", retVal); in_node->inode.fn[0] = '\0'; } *name8 = '\0'; } else if (ctype == ISO9660_CTYPE_ASCII) { int readlen; readlen = dentry->fi_len; if (readlen > ISO9660_MAXNAMLEN_STD) readlen = ISO9660_MAXNAMLEN_STD; memcpy(in_node->inode.fn, &buf[b_offs], readlen); in_node->inode.fn[readlen] = '\0'; } else { tsk_error_reset(); tsk_errno = TSK_ERR_FS_ARG; snprintf(tsk_errstr, TSK_ERRSTR_L, "Invalid ctype in iso9660_load_inodes_dir"); return -1; } // the version is embedded in the name file_ver = strchr(in_node->inode.fn, ';'); if (file_ver) { in_node->inode.version = atoi(file_ver + 1); *file_ver = '\0'; file_ver = NULL; } // if no extension, remove the final '.' if (in_node->inode.fn[strlen(in_node->inode.fn) - 1] == '.') in_node->inode.fn[strlen(in_node->inode.fn) - 1] = '\0'; /* skip past padding byte */ b_offs += dentry->fi_len; if (!(dentry->fi_len % 2)) { b_offs++; } } // copy the raw dentry data into the node memcpy(&(in_node->inode.dr), dentry, sizeof(iso9660_dentry)); in_node->inode.ea = NULL; in_node->offset = tsk_getu32(fs->endian, dentry->ext_loc_m) * fs->block_size; in_node->ea_size = dentry->ext_len; /* record size to make sure fifos show up as unique files */ in_node->size = tsk_getu32(fs->endian, in_node->inode.dr.data_len_m); in_node->inum = count++; /* RockRidge data is located after the name. See if it is there. */ if ((int) (dentry->entry_len - sizeof(iso9660_dentry) - dentry->fi_len) > 1) { int extra_bytes = dentry->entry_len - sizeof(iso9660_dentry) - dentry->fi_len; // this takes care of the length adjustment that we already did // on offs if (extra_bytes % 2) extra_bytes--; in_node->inode.rr = parse_susp(fs, &buf[b_offs], extra_bytes, NULL); in_node->inode.susp_off = b_offs + s_offs; in_node->inode.susp_len = extra_bytes; if (in_node->inode.rr == NULL) { // return -1; // @@@ Verbose error } b_offs += extra_bytes; } else { in_node->inode.susp_off = 0; in_node->inode.susp_len = 0; } /* add inode to the list */ /* list not empty */ if (iso->in_list) { iso9660_inode_node *tmp; tmp = iso->in_list; while ((tmp->next) && ((in_node->offset != tmp->offset) || (!in_node->size) || (!tmp->size))) tmp = tmp->next; /* see if the file is already in list */ if ((in_node->offset == tmp->offset) && (in_node->size) && (tmp->size)) { if ((in_node->inode.rr) && (!tmp->inode.rr)) { tmp->inode.rr = in_node->inode.rr; in_node->inode.rr = NULL; } if (in_node->inode.rr) free(in_node->inode.rr); free(in_node); count--; } /* file wasn't in list, add it */ else { tmp->next = in_node; in_node->next = NULL; } /* list is empty */ } else { iso->in_list = in_node; in_node->next = NULL; } } s_offs += cnt1; } return count;}/** * Process the path table for a joliet secondary volume descriptor. * This will load each * of the directories in the table pointed to by he SVD. * * @param fs File system to process * @param svd Pointer to the secondary volume descriptor * @param count Current count of inodes * @returns updated count of inodes or -1 on error */static intiso9660_load_inodes_pt_joliet(TSK_FS_INFO * fs, iso9660_svd * svd, int count){ TSK_OFF_T pt_offs; /* offset of where we are in path table */ size_t pt_len; /* bytes left in path table */ // get the location of the path table pt_offs = (TSK_OFF_T) (tsk_getu32(fs->endian, svd->pt_loc_m) * fs->block_size); pt_len = tsk_getu32(fs->endian, svd->pt_size_m); while (pt_len > 0) { char utf16_buf[ISO9660_MAXNAMLEN_JOL + 1]; // UTF-16 name from img char utf8buf[2 * ISO9660_MAXNAMLEN_JOL + 1]; // UTF-8 version of name int readlen; TSK_OFF_T extent; /* offset of extent for current directory */ path_table_rec dir; int retVal; ssize_t cnt; UTF16 *name16; UTF8 *name8; // read the next entry cnt = tsk_fs_read(fs, pt_offs, (char *) &dir, (int) sizeof(dir)); if (cnt != sizeof(dir)) { if (cnt >= 0) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_READ; } snprintf(tsk_errstr2, TSK_ERRSTR_L, "iso9660_load_inodes_pt"); return -1; } pt_len -= cnt; pt_offs += (TSK_OFF_T) cnt; readlen = dir.len_di; if (dir.len_di > ISO9660_MAXNAMLEN_JOL) readlen = ISO9660_MAXNAMLEN_JOL; /* get UCS-2 filename for the entry */ cnt = tsk_fs_read(fs, pt_offs, (char *) utf16_buf, readlen); if (cnt != dir.len_di) { if (cnt >= 0) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_READ; } snprintf(tsk_errstr2, TSK_ERRSTR_L, "iso_find_inodes"); return -1; } pt_len -= cnt; pt_offs += (TSK_OFF_T) cnt; // ISO stores UTF-16 in BE -- convert to local if we need to if (fs->endian & TSK_LIT_ENDIAN) { int i; for (i = 0; i < cnt; i += 2) { char t = utf16_buf[i]; utf16_buf[i] = utf16_buf[i + 1]; utf16_buf[i] = t; } } name16 = (UTF16 *) utf16_buf; name8 = (UTF8 *) utf8buf; retVal = tsk_UTF16toUTF8(fs->endian, (const UTF16 **) &name16, (UTF16 *) ((uintptr_t) & utf16_buf[cnt + 1]), &name8, (UTF8 *) ((uintptr_t) & utf8buf[2 * ISO9660_MAXNAMLEN_JOL]), TSKlenientConversion); if (retVal != TSKconversionOK) { if (tsk_verbose) tsk_fprintf(stderr, "fsstat: Error converting Joliet name to UTF8: %d", retVal); utf8buf[0] = '\0'; } *name8 = '\0'; /* padding byte is there if strlen(file name) is odd */ if (dir.len_di % 2) { pt_len--; pt_offs++; } extent = (TSK_OFF_T) (tsk_getu32(fs->endian, dir.ext_loc) * fs->block_size); count = iso9660_load_inodes_dir(fs, extent, count, ISO9660_CTYPE_UTF16, utf8buf); if (count == -1) { return -1; } } return count;}/** * Proces the path table and identify the directories that are listed. The contents of each directory will also * be processed. The result will be that the list of inodes in the image will be loaded in ISO_INFO. * * @param iso File system to analyze and store results in * @returns -1 on error or count of inodes found. */static intiso9660_load_inodes_pt(ISO_INFO * iso){ TSK_FS_INFO *fs = (TSK_FS_INFO *) & iso->fs_info; int count = 0; iso9660_svd_node *s; iso9660_pvd_node *p; char fn[ISO9660_MAXNAMLEN_STD + 1]; /* store current directory name */ path_table_rec dir; TSK_OFF_T pt_offs; /* offset of where we are in path table */ size_t pt_len; /* bytes left in path table */ TSK_OFF_T extent; /* offset of extent for current directory */ ssize_t cnt; if (tsk_verbose) tsk_fprintf(stderr, "iso9660_load_inodes_pt: iso: %lu\n", (uintptr_t) iso); /* initialize in case repeatedly called */ iso9660_inode_list_free(fs); iso->in_list = NULL; /* The secondary volume descriptor table will contain the * longer / unicode files, so we process it first to give them * a higher priority */ for (s = iso->svd; s != NULL; s = s->next) { /* Check if this is Joliet -- there are three possible signatures */ if ((s->svd.esc_seq[0] == 0x25) && (s->svd.esc_seq[1] == 0x2F) && ((s->svd.esc_seq[2] == 0x40) || (s->svd.esc_seq[2] == 0x43) || (s->svd.esc_seq[2] == 0x45))) { count = iso9660_load_inodes_pt_joliet(fs, &(s->svd), count); if (count == -1) { return -1; } } } /* Now look for unique files in the primary descriptors */ for (p = iso->pvd; p != NULL; p = p->next) { pt_offs = (TSK_OFF_T) (tsk_getu32(fs->endian, p->pvd.pt_loc_m) * fs->block_size); pt_len = tsk_getu32(fs->endian, p->pvd.pt_size_m); while (pt_len > 0) { int readlen; /* get next dir... */ cnt = tsk_fs_read(fs, pt_offs, (char *) &dir, sizeof(dir)); if (cnt != sizeof(dir)) { if (cnt >= 0) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_READ; } snprintf(tsk_errstr2, TSK_ERRSTR_L, "iso_find_inodes"); return -1; } pt_len -= cnt; pt_offs += (TSK_OFF_T) cnt; readlen = dir.len_di; if (readlen > ISO9660_MAXNAMLEN_STD) readlen = ISO9660_MAXNAMLEN_STD; /* get directory name, this is the only chance */ cnt = tsk_fs_read(fs, pt_offs, fn, readlen); if (cnt != readlen) { if (cnt >= 0) { tsk_error_reset(); tsk_errno = TSK_ERR_FS_READ; } snprintf(tsk_errstr2, TSK_ERRSTR_L, "iso_find_inodes"); return -1; } fn[cnt] = '\0'; pt_len -= cnt; pt_offs += (TSK_OFF_T) cnt; /* padding byte is there if strlen(file name) is odd */ if (dir.len_di % 2) { pt_len--; pt_offs++; } extent = (TSK_OFF_T) (tsk_getu32(fs->endian, dir.ext_loc) * fs->block_size); count = iso9660_load_inodes_dir(fs, extent, count, ISO9660_CTYPE_ASCII, fn); if (count == -1) { return -1; } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -