Add hard-link support: keep a hashtable that maps inodes for

regular files on the source filesystem to the offset of the first
data block on the target filesystem.  Don't allocate blocks for a
file a second time (i.e., if it is already present in the hashtable).
Avoid writing the blocks of a file twice (use the FS_WRITTEN flag
in fsinode->flags for this purpose).
This commit is contained in:
dyoung 2005-10-30 09:27:49 +00:00
parent eae67f894f
commit 1da546647c
3 changed files with 91 additions and 31 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cd9660.c,v 1.7 2005/10/30 06:45:46 dyoung Exp $ */
/* $NetBSD: cd9660.c,v 1.8 2005/10/30 09:27:49 dyoung Exp $ */
/*
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
@ -101,7 +101,7 @@
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: cd9660.c,v 1.7 2005/10/30 06:45:46 dyoung Exp $");
__RCSID("$NetBSD: cd9660.c,v 1.8 2005/10/30 09:27:49 dyoung Exp $");
#endif /* !__lint */
#include <string.h>
@ -200,6 +200,8 @@ int cd9660_defaults_set = 0;
static void
cd9660_set_defaults(void)
{
int i;
/*Fix the sector size for now, though the spec allows for other sizes*/
diskStructure.sectorSize = 2048;
@ -247,6 +249,8 @@ cd9660_set_defaults(void)
diskStructure.is_bootable = 0;
TAILQ_INIT(&diskStructure.boot_images);
LIST_INIT(&diskStructure.boot_entries);
for (i = 0; i < CD9660_INODE_HASH_SIZE; i++)
SLIST_INIT(&diskStructure.inode_hash[i]);
}
void
@ -1776,6 +1780,42 @@ cd9660_populate_dot_records(cd9660node *node)
cd9660_compute_record_size(node->dot_dot_record);
}
static struct cd9660_inode *
cd9660_inode_lookup(iso9660_disk *disk, uint32_t ino)
{
struct cd9660_inode *in;
struct cd9660_inode_head *head;
head = &disk->inode_hash[CD9660_INODE_HASH(ino)];
SLIST_FOREACH(in, head, in_link) {
if (in->in_ino == ino)
break;
else if (in->in_ino > ino)
return NULL;
}
return in;
}
static void
cd9660_inode_insert(iso9660_disk *disk, struct cd9660_inode *in)
{
struct cd9660_inode *iter_in, *last_in = NULL;
struct cd9660_inode_head *head;
head = &disk->inode_hash[CD9660_INODE_HASH(in->in_ino)];
SLIST_FOREACH(iter_in, head, in_link) {
assert(iter_in->in_ino != in->in_ino);
if (iter_in->in_ino > in->in_ino)
break;
last_in = iter_in;
}
if (last_in == NULL)
SLIST_INSERT_HEAD(head, in, in_link);
else
SLIST_INSERT_AFTER(last_in, in, in_link);
}
/*
* @param struct cd9660node *node The node
* @param int The offset (in bytes) - SHOULD align to the beginning of a sector
@ -1793,6 +1833,7 @@ cd9660_compute_offsets(cd9660node *node, int startOffset)
int used_bytes = 0;
int current_sector_usage = 0;
cd9660node *child;
struct cd9660_inode *in;
int r;
assert(node != NULL);
@ -1869,23 +1910,31 @@ cd9660_compute_offsets(cd9660node *node, int startOffset)
child->fileRecordSize =
cd9660_compute_record_size(child);
/* For 0 byte files */
if (child->fileDataLength == 0)
child->fileSectorsUsed = 0;
else {
child->fileSectorsUsed =
CD9660_BLOCKS(
diskStructure.sectorSize,
child->fileDataLength);
}
child->fileSectorsUsed =
CD9660_BLOCKS(diskStructure.sectorSize,
child->fileDataLength);
child->fileDataSector =
CD9660_BLOCKS(diskStructure.sectorSize,
used_bytes + startOffset);
in = cd9660_inode_lookup(&diskStructure,
child->node->inode->st.st_ino);
if (in != NULL) {
INODE_WARNX(("%s: already allocated inode %d"
" (%" PRIu32 ") data sectors", __func__,
(int)child->node->inode->st.st_ino,
in->in_ino));
} else if ((in = calloc(1, sizeof(*in))) == NULL)
err(EXIT_FAILURE, "%s: calloc", __func__);
else {
in->in_ino = child->node->inode->st.st_ino;
in->in_data_sector =
CD9660_BLOCKS(diskStructure.sectorSize,
used_bytes + startOffset);
cd9660_inode_insert(&diskStructure, in);
used_bytes += child->fileSectorsUsed *
diskStructure.sectorSize;
}
child->fileDataSector = in->in_data_sector;
cd9660_bothendian_dword(child->fileDataSector,
child->isoDirRecord->extent);
used_bytes += child->fileSectorsUsed *
diskStructure.sectorSize;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: cd9660.h,v 1.7 2005/10/30 07:33:57 dyoung Exp $ */
/* $NetBSD: cd9660.h,v 1.8 2005/10/30 09:27:49 dyoung Exp $ */
/*
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
@ -57,6 +57,11 @@
#include "cd9660/iso_rrip.h"
#include "cd9660/cd9660_eltorito.h"
#ifdef DEBUG
#define INODE_WARNX(__x) warnx __x
#else /* DEBUG */
#define INODE_WARNX(__x)
#endif /* DEBUG */
#define CD9660MAXPATH 4096
@ -127,7 +132,7 @@ typedef struct {
#define CD9660_TYPE_DOTDOT 0x08
#define CD9660_TYPE_VIRTUAL 0x80
#define CD9660_HASH_SIZE 512
#define CD9660_INODE_HASH_SIZE 1024
#define CD9660_END_PADDING 150
@ -212,16 +217,13 @@ typedef struct _cd9660node {
TAILQ_HEAD(susp_linked_list, ISO_SUSP_ATTRIBUTES) head;
} cd9660node;
#if 0
struct cd9660hash_node {
cd9660node *thenode;
LIST_ENTRY(cd9660hash_node) ll_struct;
struct cd9660_inode {
uint32_t in_ino;
int in_data_sector;
SLIST_ENTRY(cd9660_inode) in_link;
};
struct cd9660hash_table {
LIST_HEAD(node_hash_table,cd9660_node_hash) node_hash[CD9660_HASH_SIZE];
};
#endif
#define CD9660_INODE_HASH(__inode) ((__inode) % CD9660_INODE_HASH_SIZE)
typedef struct _path_table_entry
{
@ -247,7 +249,9 @@ typedef struct _iso9660_disk {
volume_descriptor *firstVolumeDescriptor;
cd9660node *rootNode;
/*struct cd9660hash_table name_hash;*/
SLIST_HEAD(cd9660_inode_head,
cd9660_inode) inode_hash[CD9660_INODE_HASH_SIZE];
const char *rootFilesystemPath;

View File

@ -1,4 +1,4 @@
/* $NetBSD: cd9660_write.c,v 1.4 2005/10/30 07:40:45 dyoung Exp $ */
/* $NetBSD: cd9660_write.c,v 1.5 2005/10/30 09:27:49 dyoung Exp $ */
/*
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
@ -37,7 +37,7 @@
#include <sys/cdefs.h>
#if defined(__RCSID) && !defined(__lint)
__RCSID("$NetBSD: cd9660_write.c,v 1.4 2005/10/30 07:40:45 dyoung Exp $");
__RCSID("$NetBSD: cd9660_write.c,v 1.5 2005/10/30 09:27:49 dyoung Exp $");
#endif /* !__lint */
static int cd9660_write_volume_descriptors(FILE *);
@ -277,8 +277,15 @@ cd9660_write_file(FILE *fd, cd9660node *writenode)
if ((writenode->level != 0) &&
!(writenode->node->type & S_IFDIR)) {
/* Only attempt to write files that have length */
if (writenode->fileDataLength > 0) {
fsinode *inode = writenode->node->inode;
/* Only attempt to write unwritten files that have length. */
if ((inode->flags & FI_WRITTEN) != 0) {
INODE_WARNX(("%s: skipping written inode %d", __func__,
(int)inode->st.st_ino));
} else if (writenode->fileDataLength > 0) {
INODE_WARNX(("%s: writing inode %d", __func__,
(int)inode->st.st_ino));
inode->flags |= FI_WRITTEN;
cd9660_compute_full_filename(writenode,
temp_file_name, 0);
ret = cd9660_copy_file(fd, writenode->fileDataSector,