Home | History | Annotate | Line # | Download | only in cd9660
cd9660_write.c revision 1.3
      1  1.3  dyoung /*	$NetBSD: cd9660_write.c,v 1.3 2005/10/30 03:10:28 dyoung Exp $	*/
      2  1.1    fvdl 
      3  1.1    fvdl /*
      4  1.1    fvdl  * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
      5  1.1    fvdl  * Perez-Rathke and Ram Vedam.  All rights reserved.
      6  1.1    fvdl  *
      7  1.1    fvdl  * This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
      8  1.1    fvdl  * Alan Perez-Rathke and Ram Vedam.
      9  1.1    fvdl  *
     10  1.1    fvdl  * Redistribution and use in source and binary forms, with or
     11  1.1    fvdl  * without modification, are permitted provided that the following
     12  1.1    fvdl  * conditions are met:
     13  1.1    fvdl  * 1. Redistributions of source code must retain the above copyright
     14  1.1    fvdl  *    notice, this list of conditions and the following disclaimer.
     15  1.1    fvdl  * 2. Redistributions in binary form must reproduce the above
     16  1.1    fvdl  *    copyright notice, this list of conditions and the following
     17  1.1    fvdl  *    disclaimer in the documentation and/or other materials provided
     18  1.1    fvdl  *    with the distribution.
     19  1.1    fvdl  *
     20  1.1    fvdl  * THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
     21  1.1    fvdl  * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
     22  1.1    fvdl  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  1.3  dyoung  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     24  1.1    fvdl  * DISCLAIMED.  IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
     25  1.1    fvdl  * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
     26  1.1    fvdl  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27  1.1    fvdl  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
     28  1.1    fvdl  * USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     29  1.1    fvdl  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     30  1.1    fvdl  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31  1.1    fvdl  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
     32  1.1    fvdl  * OF SUCH DAMAGE.
     33  1.1    fvdl  */
     34  1.1    fvdl 
     35  1.1    fvdl #include "cd9660.h"
     36  1.1    fvdl #include "iso9660_rrip.h"
     37  1.1    fvdl 
     38  1.1    fvdl #include <sys/cdefs.h>
     39  1.1    fvdl #if defined(__RCSID) && !defined(__lint)
     40  1.3  dyoung __RCSID("$NetBSD: cd9660_write.c,v 1.3 2005/10/30 03:10:28 dyoung Exp $");
     41  1.1    fvdl #endif  /* !__lint */
     42  1.1    fvdl 
     43  1.1    fvdl static int cd9660_write_volume_descriptors(FILE *);
     44  1.1    fvdl static int cd9660_write_path_table(FILE *, int, int);
     45  1.1    fvdl static int cd9660_write_path_tables(FILE *);
     46  1.1    fvdl static int cd9660_write_file(FILE *, cd9660node *);
     47  1.1    fvdl static int cd9660_write_filedata(FILE *, int, const unsigned char *, int);
     48  1.1    fvdl #if 0
     49  1.1    fvdl static int cd9660_write_buffered(FILE *, int, int, const unsigned char*);
     50  1.1    fvdl #endif
     51  1.1    fvdl static int cd9660_write_rr(FILE *, cd9660node *, int, int);
     52  1.1    fvdl 
     53  1.1    fvdl /*
     54  1.1    fvdl  * Write the image
     55  1.1    fvdl  * Writes the entire image
     56  1.1    fvdl  * @param const char* The filename for the image
     57  1.1    fvdl  * @returns int 1 on success, 0 on failure
     58  1.1    fvdl  */
     59  1.3  dyoung int
     60  1.1    fvdl cd9660_write_image(const char* image)
     61  1.1    fvdl {
     62  1.1    fvdl 	FILE *fd;
     63  1.1    fvdl 	int status;
     64  1.1    fvdl 	char buf[2048];
     65  1.3  dyoung 
     66  1.1    fvdl 	if ((fd = fopen(image, "w+")) == NULL)
     67  1.1    fvdl 		err(1, "Error: Can't open `%s' for writing", image);
     68  1.1    fvdl 
     69  1.1    fvdl 	if (diskStructure.verbose_level > 0)
     70  1.1    fvdl 		printf("Writing image\n");
     71  1.1    fvdl 
     72  1.1    fvdl 	/* Write the volume descriptors */
     73  1.1    fvdl 	status = cd9660_write_volume_descriptors(fd);
     74  1.1    fvdl 	if (status == 0) {
     75  1.1    fvdl 		warnx("cd9660_write_image: Error writing volume "
     76  1.1    fvdl 		       "descriptors to image");
     77  1.1    fvdl 		goto cleanup_bad_image;
     78  1.1    fvdl 	}
     79  1.3  dyoung 
     80  1.1    fvdl 	if (diskStructure.verbose_level > 0)
     81  1.1    fvdl 		printf("Volume descriptors written\n");
     82  1.3  dyoung 
     83  1.1    fvdl 	/*
     84  1.1    fvdl 	 * Write the path tables: there are actually four, but right
     85  1.1    fvdl 	 * now we are only concearned with two.
     86  1.1    fvdl 	 */
     87  1.1    fvdl 	status = cd9660_write_path_tables(fd);
     88  1.1    fvdl 	if (status == 0) {
     89  1.1    fvdl 		warnx("cd9660_write_image: Error writing path tables to image");
     90  1.1    fvdl 		goto cleanup_bad_image;
     91  1.1    fvdl 	}
     92  1.3  dyoung 
     93  1.1    fvdl 	if (diskStructure.verbose_level > 0)
     94  1.1    fvdl 		printf("Path tables written\n");
     95  1.3  dyoung 
     96  1.1    fvdl 	/* Write the directories and files */
     97  1.1    fvdl 	status = cd9660_write_file(fd, diskStructure.rootNode);
     98  1.1    fvdl 	if (status == 0) {
     99  1.1    fvdl 		warnx("cd9660_write_image: Error writing files to image");
    100  1.1    fvdl 		goto cleanup_bad_image;
    101  1.1    fvdl 	}
    102  1.1    fvdl 
    103  1.1    fvdl 	if (diskStructure.is_bootable) {
    104  1.1    fvdl 		cd9660_write_boot(fd);
    105  1.1    fvdl 	}
    106  1.1    fvdl 
    107  1.1    fvdl 	/* Write padding bits. This is temporary */
    108  1.1    fvdl 	memset(buf, 0, 2048);
    109  1.1    fvdl 	cd9660_write_filedata(fd, diskStructure.totalSectors - 1, buf, 1);
    110  1.3  dyoung 
    111  1.1    fvdl 	if (diskStructure.verbose_level > 0)
    112  1.1    fvdl 		printf("Files written\n");
    113  1.1    fvdl 	fclose(fd);
    114  1.3  dyoung 
    115  1.1    fvdl 	if (diskStructure.verbose_level > 0)
    116  1.1    fvdl 		printf("Image closed\n");
    117  1.1    fvdl 	return 1;
    118  1.1    fvdl 
    119  1.1    fvdl cleanup_bad_image:
    120  1.1    fvdl 	fclose(fd);
    121  1.1    fvdl 	if (!diskStructure.keep_bad_images)
    122  1.1    fvdl 		unlink(image);
    123  1.1    fvdl 	if (diskStructure.verbose_level > 0)
    124  1.1    fvdl 		printf("Bad image cleaned up\n");
    125  1.1    fvdl 	return 0;
    126  1.1    fvdl }
    127  1.1    fvdl 
    128  1.1    fvdl static int
    129  1.1    fvdl cd9660_write_volume_descriptors(FILE *fd)
    130  1.1    fvdl {
    131  1.1    fvdl 	volume_descriptor *vd_temp = diskStructure.firstVolumeDescriptor;
    132  1.1    fvdl 	int pos;
    133  1.1    fvdl 
    134  1.1    fvdl 	while (vd_temp != NULL) {
    135  1.1    fvdl 		pos = vd_temp->sector*diskStructure.sectorSize;
    136  1.1    fvdl 		cd9660_write_filedata(fd, vd_temp->sector,
    137  1.1    fvdl 		    vd_temp->volumeDescriptorData, 1);
    138  1.1    fvdl 		vd_temp = vd_temp->next;
    139  1.1    fvdl 	}
    140  1.1    fvdl 	return 1;
    141  1.1    fvdl }
    142  1.1    fvdl 
    143  1.1    fvdl /*
    144  1.1    fvdl  * Write out an individual path table
    145  1.1    fvdl  * Used just to keep redundant code to a minimum
    146  1.1    fvdl  * @param FILE *fd Valid file pointer
    147  1.1    fvdl  * @param int Sector to start writing path table to
    148  1.1    fvdl  * @param int Endian mode : BIG_ENDIAN or LITTLE_ENDIAN
    149  1.1    fvdl  * @returns int 1 on success, 0 on failure
    150  1.1    fvdl  */
    151  1.1    fvdl static int
    152  1.1    fvdl cd9660_write_path_table(FILE *fd, int sector, int mode)
    153  1.1    fvdl {
    154  1.1    fvdl 	int path_table_sectors = CD9660_BLOCKS(diskStructure.sectorSize,
    155  1.1    fvdl 	    diskStructure.pathTableLength);
    156  1.1    fvdl 	unsigned char *buffer;
    157  1.1    fvdl 	unsigned char *buffer_head;
    158  1.1    fvdl 	int len;
    159  1.1    fvdl 	path_table_entry temp_entry;
    160  1.1    fvdl 	cd9660node *ptcur;
    161  1.1    fvdl 
    162  1.1    fvdl 	buffer = malloc(diskStructure.sectorSize * path_table_sectors);
    163  1.1    fvdl 	if (buffer == NULL) {
    164  1.1    fvdl 		warnx("cd9660_write_path_table: Memory allocation error "
    165  1.1    fvdl 		      "allocating buffer");
    166  1.1    fvdl 		return 0;
    167  1.1    fvdl 	}
    168  1.1    fvdl 	buffer_head = buffer;
    169  1.1    fvdl 	memset(buffer, 0, diskStructure.sectorSize * path_table_sectors);
    170  1.1    fvdl 
    171  1.1    fvdl 	ptcur = diskStructure.rootNode;
    172  1.3  dyoung 
    173  1.1    fvdl 	while (ptcur != NULL) {
    174  1.1    fvdl 		memset(&temp_entry, 0, sizeof(path_table_entry));
    175  1.1    fvdl 		temp_entry.length[0] = ptcur->isoDirRecord->name_len[0];
    176  1.1    fvdl 		temp_entry.extended_attribute_length[0] =
    177  1.1    fvdl 		    ptcur->isoDirRecord->ext_attr_length[0];
    178  1.1    fvdl 		memcpy(temp_entry.name, ptcur->isoDirRecord->name,
    179  1.1    fvdl 		    temp_entry.length[0] + 1);
    180  1.1    fvdl 
    181  1.1    fvdl 		/* round up */
    182  1.1    fvdl 		len = temp_entry.length[0] + 8 + (temp_entry.length[0] & 0x01);
    183  1.1    fvdl 
    184  1.1    fvdl                 /* todo: function pointers instead */
    185  1.1    fvdl 		if (mode == LITTLE_ENDIAN) {
    186  1.1    fvdl 			cd9660_731(ptcur->fileDataSector,
    187  1.1    fvdl 			    temp_entry.first_sector);
    188  1.1    fvdl 			cd9660_721((ptcur->parent == NULL ?
    189  1.1    fvdl 				1 : ptcur->parent->ptnumber),
    190  1.1    fvdl 			    temp_entry.parent_number);
    191  1.1    fvdl 		} else {
    192  1.1    fvdl 			cd9660_732(ptcur->fileDataSector,
    193  1.1    fvdl 			    temp_entry.first_sector);
    194  1.1    fvdl 			cd9660_722((ptcur->parent == NULL ?
    195  1.1    fvdl 				1 : ptcur->parent->ptnumber),
    196  1.1    fvdl 			    temp_entry.parent_number);
    197  1.1    fvdl 		}
    198  1.3  dyoung 
    199  1.1    fvdl 
    200  1.1    fvdl 		memcpy(buffer, &temp_entry, len);
    201  1.1    fvdl 		buffer += len;
    202  1.3  dyoung 
    203  1.1    fvdl 		ptcur = ptcur->ptnext;
    204  1.1    fvdl 	}
    205  1.3  dyoung 
    206  1.1    fvdl 	return cd9660_write_filedata(fd, sector, buffer_head,
    207  1.1    fvdl 	    path_table_sectors);
    208  1.1    fvdl }
    209  1.1    fvdl 
    210  1.1    fvdl 
    211  1.1    fvdl /*
    212  1.1    fvdl  * Write out the path tables to disk
    213  1.1    fvdl  * Each file descriptor should be pointed to by the PVD, so we know which
    214  1.1    fvdl  * sector to copy them to. One thing to watch out for: the only path tables
    215  1.1    fvdl  * stored are in the endian mode that the application is compiled for. So,
    216  1.1    fvdl  * the first thing to do is write out that path table, then to write the one
    217  1.1    fvdl  * in the other endian mode requires to convert the endianness of each entry
    218  1.1    fvdl  * in the table. The best way to do this would be to create a temporary
    219  1.1    fvdl  * path_table_entry structure, then for each path table entry, copy it to
    220  1.1    fvdl  * the temporary entry, translate, then copy that to disk.
    221  1.1    fvdl  *
    222  1.1    fvdl  * @param FILE* Valid file descriptor
    223  1.1    fvdl  * @returns int 0 on failure, 1 on success
    224  1.1    fvdl  */
    225  1.1    fvdl static int
    226  1.1    fvdl cd9660_write_path_tables(FILE *fd)
    227  1.1    fvdl {
    228  1.1    fvdl 	if (cd9660_write_path_table(fd,
    229  1.1    fvdl 	    diskStructure.primaryLittleEndianTableSector, LITTLE_ENDIAN) == 0)
    230  1.1    fvdl 		return 0;
    231  1.1    fvdl 
    232  1.1    fvdl 	if (cd9660_write_path_table(fd,
    233  1.1    fvdl 	    diskStructure.primaryBigEndianTableSector, BIG_ENDIAN) == 0)
    234  1.1    fvdl 		return 0;
    235  1.1    fvdl 
    236  1.1    fvdl 	/* @TODO: handle remaining two path tables */
    237  1.1    fvdl 	return 1;
    238  1.1    fvdl }
    239  1.1    fvdl 
    240  1.1    fvdl /*
    241  1.1    fvdl  * Write a file to disk
    242  1.1    fvdl  * Writes a file, its directory record, and its data to disk
    243  1.1    fvdl  * This file is designed to be called RECURSIVELY, so initially call it
    244  1.1    fvdl  * with the root node. All of the records should store what sector the
    245  1.1    fvdl  * file goes in, so no computation should be  necessary.
    246  1.1    fvdl  *
    247  1.1    fvdl  * @param int fd Valid file descriptor
    248  1.1    fvdl  * @param struct cd9660node* writenode Pointer to the file to be written
    249  1.1    fvdl  * @returns int 0 on failure, 1 on success
    250  1.1    fvdl  */
    251  1.1    fvdl static int
    252  1.1    fvdl cd9660_write_file(FILE *fd, cd9660node *writenode)
    253  1.1    fvdl {
    254  1.1    fvdl 	char *buf;
    255  1.1    fvdl 	char *temp_file_name;
    256  1.1    fvdl 	int ret;
    257  1.1    fvdl 	int working_sector;
    258  1.1    fvdl 	int cur_sector_offset;
    259  1.1    fvdl 	int written;
    260  1.1    fvdl 	iso_directory_record_cd9660 temp_record;
    261  1.1    fvdl 	cd9660node *temp;
    262  1.1    fvdl 	int ca = 0;
    263  1.1    fvdl 
    264  1.1    fvdl 	/* Todo : clean up variables */
    265  1.3  dyoung 
    266  1.1    fvdl 	temp_file_name = malloc(CD9660MAXPATH + 1);
    267  1.1    fvdl 	if (temp_file_name == NULL)
    268  1.1    fvdl 		errx(1, "cd9660_write_file: failed to allocate filename space");
    269  1.1    fvdl 
    270  1.1    fvdl 	memset(temp_file_name, 0, CD9660MAXPATH + 1);
    271  1.1    fvdl 
    272  1.1    fvdl 	buf = malloc(diskStructure.sectorSize);
    273  1.1    fvdl 	if (buf == NULL)
    274  1.1    fvdl 		errx(1, "cd9660_write_file: Failed to allocate buffer memory");
    275  1.1    fvdl 
    276  1.1    fvdl 	if ((writenode->level != 0) &&
    277  1.1    fvdl 	    !(writenode->node->type & S_IFDIR)) {
    278  1.1    fvdl 		/* Only attempt to write files that have length */
    279  1.1    fvdl 		if (writenode->fileDataLength > 0) {
    280  1.1    fvdl 			cd9660_compute_full_filename(writenode,
    281  1.1    fvdl 			    temp_file_name, 0);
    282  1.1    fvdl 			ret = cd9660_copy_file(fd, writenode->fileDataSector,
    283  1.1    fvdl 			    temp_file_name);
    284  1.1    fvdl 			if (ret == 0) {
    285  1.1    fvdl 				free(temp_file_name);
    286  1.1    fvdl 				return 0;
    287  1.1    fvdl 			}
    288  1.1    fvdl 		}
    289  1.1    fvdl 	} else {
    290  1.1    fvdl 		/*
    291  1.1    fvdl 		 * Here is a new revelation that ECMA didnt explain
    292  1.1    fvdl 		 * (at least not well).
    293  1.1    fvdl 		 * ALL . and .. records store the name "\0" and "\1"
    294  1.1    fvdl 		 * resepctively. So, for each directory, we have to
    295  1.1    fvdl 		 * make a new node.
    296  1.1    fvdl 		 *
    297  1.1    fvdl 		 * This is where it gets kinda messy, since we have to
    298  1.1    fvdl 		 * be careful of sector boundaries
    299  1.1    fvdl 		 */
    300  1.1    fvdl 		cur_sector_offset = 0;
    301  1.1    fvdl 		working_sector = writenode->fileDataSector;
    302  1.1    fvdl 		fseek(fd, working_sector * diskStructure.sectorSize, SEEK_SET);
    303  1.3  dyoung 
    304  1.1    fvdl 		/*
    305  1.1    fvdl 		 * Now loop over children, writing out their directory
    306  1.1    fvdl 		 * records - beware of sector boundaries
    307  1.1    fvdl 	 	 */
    308  1.2  dyoung 		TAILQ_FOREACH(temp, &writenode->cn_children, cn_next_child) {
    309  1.1    fvdl 			/*
    310  1.1    fvdl 			 * Copy the temporary record and adjust its size
    311  1.1    fvdl 			 * if necessary
    312  1.1    fvdl 			 */
    313  1.1    fvdl 			memcpy(&temp_record, temp->isoDirRecord,
    314  1.1    fvdl 			    sizeof(iso_directory_record_cd9660));
    315  1.1    fvdl 
    316  1.1    fvdl 			temp_record.length[0] =
    317  1.1    fvdl 			    cd9660_compute_record_size(temp);
    318  1.3  dyoung 
    319  1.1    fvdl 			if (temp_record.length[0] + cur_sector_offset >=
    320  1.1    fvdl 			    diskStructure.sectorSize) {
    321  1.1    fvdl 				cur_sector_offset = 0;
    322  1.1    fvdl 				working_sector++;
    323  1.1    fvdl 
    324  1.1    fvdl 				/* Seek to the next sector. */
    325  1.1    fvdl 				fseek(fd,
    326  1.1    fvdl 				    working_sector * diskStructure.sectorSize,
    327  1.1    fvdl 				    SEEK_SET);
    328  1.1    fvdl 			}
    329  1.3  dyoung 
    330  1.2  dyoung 			written = fwrite(&temp_record, 1, temp_record.length[0],
    331  1.2  dyoung 			    fd);
    332  1.1    fvdl 			ca = 0;
    333  1.1    fvdl 			if (diskStructure.rock_ridge_enabled) {
    334  1.1    fvdl 				ca = cd9660_write_rr(fd, temp,
    335  1.1    fvdl 				    cur_sector_offset, working_sector);
    336  1.1    fvdl 			}
    337  1.3  dyoung 
    338  1.1    fvdl 			if (ferror(fd)) {
    339  1.1    fvdl 				warnx("Write error at %i", __LINE__);
    340  1.1    fvdl 				free(temp_file_name);
    341  1.1    fvdl 				return 0;
    342  1.1    fvdl 			}
    343  1.1    fvdl 			cur_sector_offset += temp_record.length[0];
    344  1.1    fvdl 
    345  1.1    fvdl 			/*
    346  1.1    fvdl 			 * If we had to go the the continuation area,
    347  1.1    fvdl 			 * head back to where we should be.
    348  1.1    fvdl 			 */
    349  1.1    fvdl 			if (ca) {
    350  1.1    fvdl 				fseek(fd,
    351  1.1    fvdl 				    working_sector * diskStructure.sectorSize +
    352  1.1    fvdl 					cur_sector_offset,
    353  1.1    fvdl 				    SEEK_SET);
    354  1.1    fvdl 			}
    355  1.1    fvdl 		}
    356  1.3  dyoung 
    357  1.1    fvdl 		/*
    358  1.2  dyoung 		 * Recurse on children.
    359  1.1    fvdl 		 */
    360  1.2  dyoung 		TAILQ_FOREACH(temp, &writenode->cn_children, cn_next_child) {
    361  1.2  dyoung 			if ((ret = cd9660_write_file(fd, temp)) == 0) {
    362  1.1    fvdl 				free(temp_file_name);
    363  1.1    fvdl 				return 0;
    364  1.1    fvdl 			}
    365  1.1    fvdl 		}
    366  1.1    fvdl 	}
    367  1.1    fvdl 	free(temp_file_name);
    368  1.1    fvdl 	return 1;
    369  1.1    fvdl }
    370  1.1    fvdl 
    371  1.1    fvdl /*
    372  1.1    fvdl  * Wrapper function to write a buffer (one sector) to disk.
    373  1.1    fvdl  * Seeks and writes the buffer.
    374  1.1    fvdl  * NOTE: You dont NEED to use this function, but it might make your
    375  1.1    fvdl  * life easier if you have to write things that align to a sector
    376  1.1    fvdl  * (such as volume descriptors).
    377  1.1    fvdl  *
    378  1.1    fvdl  * @param int fd Valid file descriptor
    379  1.1    fvdl  * @param int sector Sector number to write to
    380  1.1    fvdl  * @param const unsigned char* Buffer to write. This should be the
    381  1.1    fvdl  *                             size of a sector, and if only a portion
    382  1.1    fvdl  *                             is written, the rest should be set to 0.
    383  1.1    fvdl  */
    384  1.1    fvdl static int
    385  1.1    fvdl cd9660_write_filedata(FILE *fd, int sector, const unsigned char *buf,
    386  1.1    fvdl 		      int numsecs)
    387  1.1    fvdl {
    388  1.1    fvdl 	off_t curpos;
    389  1.1    fvdl 	size_t success;
    390  1.1    fvdl 
    391  1.1    fvdl 	curpos = ftello(fd);
    392  1.3  dyoung 
    393  1.1    fvdl 	fseek(fd, sector * diskStructure.sectorSize, SEEK_SET);
    394  1.1    fvdl 
    395  1.1    fvdl 	success = fwrite(buf, diskStructure.sectorSize * numsecs, 1, fd);
    396  1.1    fvdl 
    397  1.1    fvdl 	fseek(fd, curpos, SEEK_SET);
    398  1.1    fvdl 
    399  1.1    fvdl 	if (success == 1)
    400  1.1    fvdl 		success = diskStructure.sectorSize * numsecs;
    401  1.1    fvdl 	return success;
    402  1.1    fvdl }
    403  1.1    fvdl 
    404  1.1    fvdl #if 0
    405  1.1    fvdl static int
    406  1.1    fvdl cd9660_write_buffered(FILE *fd, int offset, int buff_len,
    407  1.1    fvdl 		      const unsigned char* buffer)
    408  1.1    fvdl {
    409  1.1    fvdl 	static int working_sector = -1;
    410  1.1    fvdl 	static char buf[2048];
    411  1.3  dyoung 
    412  1.1    fvdl 	return 0;
    413  1.1    fvdl }
    414  1.1    fvdl #endif
    415  1.1    fvdl 
    416  1.1    fvdl int
    417  1.1    fvdl cd9660_copy_file(FILE *fd, int start_sector, const char *filename)
    418  1.1    fvdl {
    419  1.1    fvdl 	FILE *rf;
    420  1.1    fvdl 	int bytes_read;
    421  1.1    fvdl 	int sector = start_sector;
    422  1.1    fvdl 	int buf_size = diskStructure.sectorSize;
    423  1.1    fvdl 	char *buf;
    424  1.1    fvdl 
    425  1.1    fvdl 	buf = malloc(buf_size);
    426  1.1    fvdl 	if (buf == NULL)
    427  1.1    fvdl 		errx(1, "cd9660_copy_file: memory allocation error "
    428  1.1    fvdl 			"allocating buffer");
    429  1.3  dyoung 
    430  1.1    fvdl 	if ((rf = fopen(filename, "rb")) == NULL) {
    431  1.1    fvdl 		warnx("Cant open file %s",filename);
    432  1.3  dyoung 		return 0;
    433  1.1    fvdl 	}
    434  1.1    fvdl 
    435  1.1    fvdl 	if (diskStructure.verbose_level > 1)
    436  1.1    fvdl 		printf("Writing file: %s\n",filename);
    437  1.3  dyoung 
    438  1.1    fvdl 	fseek(fd, start_sector * diskStructure.sectorSize, SEEK_SET);
    439  1.3  dyoung 
    440  1.1    fvdl 	while (!feof(rf)) {
    441  1.1    fvdl 		bytes_read = fread(buf,1,buf_size,rf);
    442  1.1    fvdl 		if (ferror(rf)) {
    443  1.1    fvdl 			warnx("cd9660_write_file: File read error");
    444  1.3  dyoung 			return 0;
    445  1.1    fvdl 		}
    446  1.3  dyoung 
    447  1.1    fvdl 		fwrite(buf,1,bytes_read,fd);
    448  1.1    fvdl 		if (ferror(fd)) {
    449  1.1    fvdl 			warnx("cd9660_write_file: File write error");
    450  1.3  dyoung 			return 0;
    451  1.1    fvdl 		}
    452  1.1    fvdl 		sector++;
    453  1.1    fvdl 	}
    454  1.3  dyoung 
    455  1.1    fvdl 	fclose(rf);
    456  1.1    fvdl 	free(buf);
    457  1.1    fvdl 	return 1;
    458  1.1    fvdl }
    459  1.1    fvdl 
    460  1.1    fvdl static int
    461  1.1    fvdl cd9660_write_rr(FILE *fd, cd9660node *writenode, int offset, int sector)
    462  1.1    fvdl {
    463  1.1    fvdl 	int in_ca = 0;
    464  1.1    fvdl 	struct ISO_SUSP_ATTRIBUTES *myattr;
    465  1.1    fvdl 
    466  1.1    fvdl 	offset += writenode->isoDirRecord->length[0];
    467  1.1    fvdl 
    468  1.1    fvdl 	/* Offset now points at the end of the record */
    469  1.2  dyoung 	TAILQ_FOREACH(myattr, &writenode->head, rr_ll) {
    470  1.3  dyoung 		fseek(fd,
    471  1.1    fvdl 		    in_ca ? offset : sector*diskStructure.sectorSize + offset,
    472  1.1    fvdl 		    SEEK_SET);
    473  1.1    fvdl 		fwrite(&(myattr->attr), CD9660_SUSP_ENTRY_SIZE(myattr), 1, fd);
    474  1.1    fvdl 
    475  1.1    fvdl 		offset += CD9660_SUSP_ENTRY_SIZE(myattr);
    476  1.1    fvdl 		if (!in_ca) {
    477  1.1    fvdl 			if ((myattr->susp_type == SUSP_TYPE_SUSP) &&
    478  1.1    fvdl 			    (myattr->entry_type == SUSP_ENTRY_SUSP_CE)) {
    479  1.1    fvdl 				/*
    480  1.1    fvdl 				 * Point the offset to the start of this
    481  1.1    fvdl 				 * record's CE area
    482  1.1    fvdl 				 */
    483  1.1    fvdl 				offset = (diskStructure.
    484  1.3  dyoung 					  susp_continuation_area_start_sector *
    485  1.1    fvdl 					    diskStructure.sectorSize)
    486  1.1    fvdl 					+ writenode->susp_entry_ce_start;
    487  1.1    fvdl 				in_ca = 1;
    488  1.1    fvdl 			}
    489  1.1    fvdl 		}
    490  1.1    fvdl 	}
    491  1.1    fvdl 
    492  1.1    fvdl 	return in_ca;
    493  1.1    fvdl }
    494