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:
parent
eae67f894f
commit
1da546647c
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user