Skip to content

Commit

Permalink
fixed issue 2954703 re: missing file in ISO9660
Browse files Browse the repository at this point in the history
  • Loading branch information
bcarrier committed Feb 19, 2010
1 parent 5587dbb commit 27e8fb2
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 64 deletions.
7 changes: 7 additions & 0 deletions NEWS.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Numbers refer to SourceForge.net tracker IDs:
http://sourceforge.net/tracker/?group_id=55685

---------------- VERSION 3.1.1 --------------

Bug Fixes
- 2954703: ISO9660 missing files because duplicate files
had same starting block.


---------------- VERSION 3.1.0 --------------

New Features and Changes
Expand Down
5 changes: 5 additions & 0 deletions tsk3/fs/fs_dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ tsk_fs_dir_add(TSK_FS_DIR * a_fs_dir, const TSK_FS_NAME * a_fs_name)
if ((a_fs_name->meta_addr == a_fs_dir->names[i].meta_addr) &&
(strcmp(a_fs_name->name, a_fs_dir->names[i].name) == 0)) {

if (tsk_verbose)
tsk_fprintf(stderr,
"tsk_fs_dir_add: removing duplicate entry: %s (%"
PRIuINUM ")\n", a_fs_name->name, a_fs_name->meta_addr);

/* We do not check type because then we cannot detect NTFS orphan file
* duplicates that are added as "-/r" while a similar entry exists as "r/r"
(a_fs_name->type == a_fs_dir->names[i].type)) { */
Expand Down
108 changes: 67 additions & 41 deletions tsk3/fs/iso9660.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@


/* free all memory used by inode linked list */
void
static void
iso9660_inode_list_free(TSK_FS_INFO * fs)
{
ISO_INFO *iso = (ISO_INFO *) fs;
Expand All @@ -93,7 +93,7 @@ iso9660_inode_list_free(TSK_FS_INFO * fs)
* @param hFile File handle to print details to (or NULL for no printing)
* @returns NULL on error
*/
rockridge_ext *
static rockridge_ext *
parse_susp(TSK_FS_INFO * fs, char *buf, int count, FILE * hFile)
{
rockridge_ext *rr;
Expand Down Expand Up @@ -341,7 +341,30 @@ parse_susp(TSK_FS_INFO * fs, char *buf, int count, FILE * hFile)
return rr;
}

/* get directory entries from current directory and add them to the inode list.

///////////////////////////////////////////////////////////////////////////
// The following functions are responsible for loading all of the file metadata into memory.
// The process is that the Path table is processed first. It contains an entry for each
// directory. That info is then used to locate the directory contents and those contents
// are then processed.
//
// Files do not have a corresponding metadata entry, so we assign them based
// on the order that they are loaded.
///////////////////////////////////////////////////////////////////////////


/* XXX Instead of loading all of the file metadata, we could instead save a mapping
* between inode number and the byte offset of the metadata (and any other data
* needed for fast lookups).
*/

/** \internal
* Process the contents of a directory and load the
* information about files in that directory into ISO_INFO. This is called
* by the methods that process the path table (which contains pointers to the
* various directories). The results in ISO_INFO are used to identify the
* inode address of files found from dent_walk and for file lookups.
*
* Type: ISO9660_TYPE_PVD for primary volume descriptor, ISO9660_TYPE_SVD for
* supplementary volume descriptor (do Joliet utf-8 conversion).
*
Expand All @@ -353,8 +376,7 @@ parse_susp(TSK_FS_INFO * fs, char *buf, int count, FILE * hFile)
*
* @returns total number of files or -1 on error
*/

int
static int
iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
int ctype, char *a_fn)
{
Expand Down Expand Up @@ -456,8 +478,8 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
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]),
(UTF8 *) ((uintptr_t) & in_node->inode.
fn[ISO9660_MAXNAMLEN_STD]),
TSKlenientConversion);
if (retVal != TSKconversionOK) {
if (tsk_verbose)
Expand Down Expand Up @@ -548,39 +570,40 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int count,
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--;
iso9660_inode_node *tmp, *prev_tmp;

for (tmp = iso->in_list; tmp; tmp = tmp->next) {
/* if it already exists, get rid of the new one.
* It may already exist from a previous volume descriptor. */
if ((in_node->offset == tmp->offset)
&& (in_node->size == tmp->size)
&& (in_node->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);

if (tsk_verbose)
tsk_fprintf(stderr,
"iso9660_load_inodes_dir: Removing duplicate entry for: %s\n",
in_node->inode.fn);
free(in_node);
in_node = NULL;
count--;
break;
}
prev_tmp = tmp;
}
/* file wasn't in list, add it */
else {
tmp->next = in_node;

// add it to the end (if we didn't get rid of it above)
if (in_node) {
prev_tmp->next = in_node;
in_node->next = NULL;
}

/* list is empty */
}
else {
iso->in_list = in_node;
Expand All @@ -595,9 +618,10 @@ iso9660_load_inodes_dir(TSK_FS_INFO * fs, TSK_OFF_T a_offs, int 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.
* Process the path table for a joliet secondary volume descriptor
* and load all of the files pointed to it.
* The path table contains an entry for each directory. This code
* then locates each of the diretories and proceses the contents.
*
* @param fs File system to process
* @param svd Pointer to the secondary volume descriptor
Expand Down Expand Up @@ -629,7 +653,7 @@ iso9660_load_inodes_pt_joliet(TSK_FS_INFO * fs, iso9660_svd * svd,
UTF16 *name16;
UTF8 *name8;

// read the next entry
// Read the path table entry
cnt = tsk_fs_read(fs, pt_offs, (char *) &dir, (int) sizeof(dir));
if (cnt != sizeof(dir)) {
if (cnt >= 0) {
Expand Down Expand Up @@ -695,6 +719,7 @@ iso9660_load_inodes_pt_joliet(TSK_FS_INFO * fs, iso9660_svd * svd,
(TSK_OFF_T) (tsk_getu32(fs->endian,
dir.ext_loc) * fs->block_size);

// process the directory contents
count =
iso9660_load_inodes_dir(fs, extent, count,
ISO9660_CTYPE_UTF16, utf8buf);
Expand All @@ -707,8 +732,8 @@ iso9660_load_inodes_pt_joliet(TSK_FS_INFO * fs, iso9660_svd * svd,
}

/**
* 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.
* Proces the path table and the directories that are listed in it.
* The files in each directory will be stored in ISO_INFO.
*
* @param iso File system to analyze and store results in
* @returns -1 on error or count of inodes found.
Expand Down Expand Up @@ -763,7 +788,7 @@ iso9660_load_inodes_pt(ISO_INFO * iso)
while (pt_len > 0) {
int readlen;

/* get next dir... */
/* get next path table entry... */
cnt = tsk_fs_read(fs, pt_offs, (char *) &dir, sizeof(dir));
if (cnt != sizeof(dir)) {
if (cnt >= 0) {
Expand Down Expand Up @@ -805,6 +830,7 @@ iso9660_load_inodes_pt(ISO_INFO * iso)
(TSK_OFF_T) (tsk_getu32(fs->endian,
dir.ext_loc) * fs->block_size);

// process the directory contents
count =
iso9660_load_inodes_dir(fs, extent, count,
ISO9660_CTYPE_ASCII, fn);
Expand Down
52 changes: 33 additions & 19 deletions tsk3/fs/iso9660_dent.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,18 @@



uint8_t
/** \internal
* process the data from inside of a directory and load the corresponding
* file data into a TSK_FS_DIR structure.
*
* @param a_fs File system
* @param a_fs_dir Structore to store file names into
* @param buf Buffer that contains the directory content
* @param a_length Number of bytes in buffer
* @param a_addr The metadata address for the directory being processed
* @returns TSK_ERR on error and TSK_OK otherwise
*/
static uint8_t
iso9660_proc_dir(TSK_FS_INFO * a_fs, TSK_FS_DIR * a_fs_dir, char *buf,
size_t a_length, TSK_INUM_T a_addr)
{
Expand Down Expand Up @@ -132,33 +143,36 @@ iso9660_proc_dir(TSK_FS_INFO * a_fs, TSK_FS_DIR * a_fs_dir, char *buf,
if ((dd->entry_len) && (buf_idx + dd->entry_len < a_length)) {
int i;

// find the corresponding entry in the inode/file list
in = iso->in_list;
while ((in)
&& (tsk_getu32(a_fs->endian,
in->inode.dr.ext_loc_m) != tsk_getu32(a_fs->endian,
dd->ext_loc_m))) {
in = in->next;
/* We need to find the data in the pre-processed list because that
* contains the meta data address that TSK assigned to this file.
* We find the entry by looking for one
* that starts with the same block and has the same size. We used to
* not use the size, but we found an image
* that had a file with 0 bytes with the same starting block as another
* file. */
for (in = iso->in_list; in; in = in->next) {
if ((tsk_getu32(a_fs->endian,
in->inode.dr.ext_loc_m) ==
tsk_getu32(a_fs->endian, dd->ext_loc_m))
&& (in->size == tsk_getu32(a_fs->endian,
dd->data_len_m)))
break;
}

// we may have not found it because we are reading corrupt data...
if ((!in)
|| (tsk_getu32(a_fs->endian,
in->inode.dr.ext_loc_m) != tsk_getu32(a_fs->endian,
dd->ext_loc_m))) {
if (!in) {
buf_idx++;
continue;
}

// copy the data in fs_name for loading
fs_name->meta_addr = in->inum;
strncpy(fs_name->name, in->inode.fn, ISO9660_MAXNAMLEN);

/* Clean up name */
i = 0;
while (fs_name->name[i] != '\0') {
for (i = 0; fs_name->name[i] != '\0'; i++) {
if (TSK_IS_CNTRL(fs_name->name[i]))
fs_name->name[i] = '^';
i++;
}

if (dd->flags & ISO9660_FLAG_DIR)
Expand All @@ -175,24 +189,23 @@ iso9660_proc_dir(TSK_FS_INFO * a_fs, TSK_FS_DIR * a_fs_dir, char *buf,
* directory. The contents are block aligned. So, we
* scan ahead until we get either a non-zero entry or the block boundary */
else {

while (buf_idx < a_length - sizeof(iso9660_dentry)) {
for (; buf_idx < a_length - sizeof(iso9660_dentry); buf_idx++) {
if (buf[buf_idx] != 0) {
dd = (iso9660_dentry *) & buf[buf_idx];
if ((dd->entry_len)
&& (buf_idx + dd->entry_len < a_length))
break;
}

if (buf_idx % a_fs->block_size == 0)
break;

buf_idx++;
}
}
}

free(buf);
tsk_fs_name_free(fs_name);

return TSK_OK;
}

Expand Down Expand Up @@ -279,6 +292,7 @@ iso9660_dir_open_meta(TSK_FS_INFO * a_fs, TSK_FS_DIR ** a_fs_dir,
return TSK_ERR;
}

// process the contents
retval = iso9660_proc_dir(a_fs, fs_dir, buf, length, a_addr);

return retval;
Expand Down
7 changes: 3 additions & 4 deletions tsk3/fs/tsk_iso9660.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,6 @@ typedef struct {

/** \internal
* Internally used structure to hold basic inode information.
*
*/
typedef struct {
iso9660_dentry dr; /* directory record */
Expand All @@ -365,9 +364,9 @@ typedef struct {
/* inode linked list node */
typedef struct iso9660_inode_node {
iso9660_inode inode;
TSK_OFF_T offset; /* byte offset of inode into disk */
TSK_INUM_T inum; /* identifier of inode */
int size; /* kludge: used to flag fifos, etc */
TSK_OFF_T offset; /* byte offset of first block of file on disk */
TSK_INUM_T inum; /* identifier of inode (assigned by TSK) */
int size; /* number of bytes in file */
int ea_size; /* length of ext attributes */
struct iso9660_inode_node *next;
} iso9660_inode_node;
Expand Down

0 comments on commit 27e8fb2

Please sign in to comment.