Skip to content

Commit 2bf96e1

Browse files
committed
Unsquash-4: update to dynamically read directory table
Originally when Unsquashfs was written it decompressed the entire filesystem, and wrote it out to disk. As such it made sense to read and decompress the entire directory table at start-up. Since then new options have been added to Unsquashfs which can significantly limit the amount of the filesystem written to disk, e.g. extract files, and more recently exclude files and depth limiting (-max option). So it no longer makes sense to read and decompress the entire directory table at start-up, when much of it may never be referenced. It just adds unnecessary overhead. Signed-off-by: Phillip Lougher <phillip@squashfs.org.uk>
1 parent 227c10c commit 2bf96e1

File tree

1 file changed

+20
-22
lines changed

1 file changed

+20
-22
lines changed

squashfs-tools/unsquash-4.c

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929

3030
static struct squashfs_fragment_entry *fragment_table;
3131
static unsigned int *id_table;
32-
static char *directory_table;
3332
static squashfs_operations ops;
3433

3534
static void read_block_list(unsigned int *block_list, long long start,
@@ -330,8 +329,7 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
330329
__attribute__((aligned));
331330
struct squashfs_dir_entry *dire = (struct squashfs_dir_entry *) buffer;
332331
long long start;
333-
long long bytes;
334-
int dir_count, size;
332+
int bytes = 0, dir_count, size, res;
335333
struct dir_ent *new_dir;
336334
struct dir *dir;
337335

@@ -363,17 +361,15 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
363361
return dir;
364362

365363
start = sBlk.s.directory_table_start + (*i)->start;
366-
bytes = lookup_entry(directory_table_hash, start);
367-
368-
if(bytes == -1)
369-
EXIT_UNSQUASH("squashfs_opendir: directory block %lld not "
370-
"found!\n", start);
371-
372-
bytes += (*i)->offset;
364+
offset = (*i)->offset;
373365
size = (*i)->data + bytes - 3;
374366

375367
while(bytes < size) {
376-
SQUASHFS_SWAP_DIR_HEADER(directory_table + bytes, &dirh);
368+
res = read_directory_data(&dirh, &start, &offset, sizeof(dirh));
369+
if(res == FALSE)
370+
goto corrupted;
371+
372+
SQUASHFS_INSWAP_DIR_HEADER(&dirh);
377373

378374
dir_count = dirh.count + 1;
379375
TRACE("squashfs_opendir: Read directory header @ byte position "
@@ -387,7 +383,11 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
387383
}
388384

389385
while(dir_count--) {
390-
SQUASHFS_SWAP_DIR_ENTRY(directory_table + bytes, dire);
386+
res = read_directory_data(dire, &start, &offset, sizeof(*dire));
387+
if(res == FALSE)
388+
goto corrupted;
389+
390+
SQUASHFS_INSWAP_DIR_ENTRY(dire);
391391

392392
bytes += sizeof(*dire);
393393

@@ -397,8 +397,11 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
397397
goto corrupted;
398398
}
399399

400-
memcpy(dire->name, directory_table + bytes,
401-
dire->size + 1);
400+
res = read_directory_data(dire->name, &start, &offset,
401+
dire->size + 1);
402+
if(res == FALSE)
403+
goto corrupted;
404+
402405
dire->name[dire->size + 1] = '\0';
403406

404407
/* check name for invalid characters (i.e /, ., ..) */
@@ -410,13 +413,15 @@ static struct dir *squashfs_opendir(unsigned int block_start, unsigned int offse
410413
TRACE("squashfs_opendir: directory entry %s, inode "
411414
"%d:%d, type %d\n", dire->name,
412415
dirh.start_block, dire->offset, dire->type);
416+
413417
if((dir->dir_count % DIR_ENT_SIZE) == 0) {
414418
new_dir = realloc(dir->dirs, (dir->dir_count +
415419
DIR_ENT_SIZE) * sizeof(struct dir_ent));
416420
if(new_dir == NULL)
417421
MEM_ERROR();
418422
dir->dirs = new_dir;
419423
}
424+
420425
strcpy(dir->dirs[dir->dir_count].name, dire->name);
421426
dir->dirs[dir->dir_count].start_block =
422427
dirh.start_block;
@@ -633,19 +638,12 @@ static int read_filesystem_tables()
633638
}
634639
}
635640

636-
/* Read directory table */
637-
638-
/* Sanity check super block contents */
641+
/* Sanity check super block directory table values */
639642
if(sBlk.s.directory_table_start > table_start) {
640643
ERROR("read_filesystem_tables: directory table start too large in super block\n");
641644
goto corrupted;
642645
}
643646

644-
directory_table = read_directory_table(sBlk.s.directory_table_start,
645-
table_start);
646-
if(directory_table == NULL)
647-
goto corrupted;
648-
649647
/* Sanity check super block inode table values */
650648
if(sBlk.s.inode_table_start >= sBlk.s.directory_table_start) {
651649
ERROR("read_filesystem_tables: inode table start too large in super block\n");

0 commit comments

Comments
 (0)