Home | History | Annotate | Line # | Download | only in cd9660
cd9660_write.c revision 1.6
      1  1.6  dyoung /*	$NetBSD: cd9660_write.c,v 1.6 2005/10/31 08:29:19 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.6  dyoung __RCSID("$NetBSD: cd9660_write.c,v 1.6 2005/10/31 08:29:19 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.4  dyoung 	if ((fd = fopen(image, "w+")) == NULL) {
     67  1.4  dyoung 		err(EXIT_FAILURE, "%s: Can't open `%s' for writing", __func__,
     68  1.4  dyoung 		    image);
     69  1.4  dyoung 	}
     70  1.1    fvdl 
     71  1.1    fvdl 	if (diskStructure.verbose_level > 0)
     72  1.1    fvdl 		printf("Writing image\n");
     73  1.1    fvdl 
     74  1.1    fvdl 	/* Write the volume descriptors */
     75  1.1    fvdl 	status = cd9660_write_volume_descriptors(fd);
     76  1.1    fvdl 	if (status == 0) {
     77  1.4  dyoung 		warnx("%s: Error writing volume descriptors to image",
     78  1.4  dyoung 		    __func__);
     79  1.1    fvdl 		goto cleanup_bad_image;
     80  1.1    fvdl 	}
     81  1.3  dyoung 
     82  1.1    fvdl 	if (diskStructure.verbose_level > 0)
     83  1.1    fvdl 		printf("Volume descriptors written\n");
     84  1.3  dyoung 
     85  1.1    fvdl 	/*
     86  1.1    fvdl 	 * Write the path tables: there are actually four, but right
     87  1.1    fvdl 	 * now we are only concearned with two.
     88  1.1    fvdl 	 */
     89  1.1    fvdl 	status = cd9660_write_path_tables(fd);
     90  1.1    fvdl 	if (status == 0) {
     91  1.4  dyoung 		warnx("%s: Error writing path tables to image", __func__);
     92  1.1    fvdl 		goto cleanup_bad_image;
     93  1.1    fvdl 	}
     94  1.3  dyoung 
     95  1.1    fvdl 	if (diskStructure.verbose_level > 0)
     96  1.1    fvdl 		printf("Path tables written\n");
     97  1.3  dyoung 
     98  1.1    fvdl 	/* Write the directories and files */
     99  1.1    fvdl 	status = cd9660_write_file(fd, diskStructure.rootNode);
    100  1.1    fvdl 	if (status == 0) {
    101  1.4  dyoung 		warnx("%s: Error writing files to image", __func__);
    102  1.1    fvdl 		goto cleanup_bad_image;
    103  1.1    fvdl 	}
    104  1.1    fvdl 
    105  1.1    fvdl 	if (diskStructure.is_bootable) {
    106  1.1    fvdl 		cd9660_write_boot(fd);
    107  1.1    fvdl 	}
    108  1.1    fvdl 
    109  1.1    fvdl 	/* Write padding bits. This is temporary */
    110  1.1    fvdl 	memset(buf, 0, 2048);
    111  1.1    fvdl 	cd9660_write_filedata(fd, diskStructure.totalSectors - 1, buf, 1);
    112  1.3  dyoung 
    113  1.1    fvdl 	if (diskStructure.verbose_level > 0)
    114  1.1    fvdl 		printf("Files written\n");
    115  1.1    fvdl 	fclose(fd);
    116  1.3  dyoung 
    117  1.1    fvdl 	if (diskStructure.verbose_level > 0)
    118  1.1    fvdl 		printf("Image closed\n");
    119  1.1    fvdl 	return 1;
    120  1.1    fvdl 
    121  1.1    fvdl cleanup_bad_image:
    122  1.1    fvdl 	fclose(fd);
    123  1.1    fvdl 	if (!diskStructure.keep_bad_images)
    124  1.1    fvdl 		unlink(image);
    125  1.1    fvdl 	if (diskStructure.verbose_level > 0)
    126  1.1    fvdl 		printf("Bad image cleaned up\n");
    127  1.1    fvdl 	return 0;
    128  1.1    fvdl }
    129  1.1    fvdl 
    130  1.1    fvdl static int
    131  1.1    fvdl cd9660_write_volume_descriptors(FILE *fd)
    132  1.1    fvdl {
    133  1.1    fvdl 	volume_descriptor *vd_temp = diskStructure.firstVolumeDescriptor;
    134  1.1    fvdl 	int pos;
    135  1.1    fvdl 
    136  1.1    fvdl 	while (vd_temp != NULL) {
    137  1.1    fvdl 		pos = vd_temp->sector*diskStructure.sectorSize;
    138  1.1    fvdl 		cd9660_write_filedata(fd, vd_temp->sector,
    139  1.1    fvdl 		    vd_temp->volumeDescriptorData, 1);
    140  1.1    fvdl 		vd_temp = vd_temp->next;
    141  1.1    fvdl 	}
    142  1.1    fvdl 	return 1;
    143  1.1    fvdl }
    144  1.1    fvdl 
    145  1.1    fvdl /*
    146  1.1    fvdl  * Write out an individual path table
    147  1.1    fvdl  * Used just to keep redundant code to a minimum
    148  1.1    fvdl  * @param FILE *fd Valid file pointer
    149  1.1    fvdl  * @param int Sector to start writing path table to
    150  1.1    fvdl  * @param int Endian mode : BIG_ENDIAN or LITTLE_ENDIAN
    151  1.1    fvdl  * @returns int 1 on success, 0 on failure
    152  1.1    fvdl  */
    153  1.1    fvdl static int
    154  1.1    fvdl cd9660_write_path_table(FILE *fd, int sector, int mode)
    155  1.1    fvdl {
    156  1.1    fvdl 	int path_table_sectors = CD9660_BLOCKS(diskStructure.sectorSize,
    157  1.1    fvdl 	    diskStructure.pathTableLength);
    158  1.1    fvdl 	unsigned char *buffer;
    159  1.1    fvdl 	unsigned char *buffer_head;
    160  1.1    fvdl 	int len;
    161  1.1    fvdl 	path_table_entry temp_entry;
    162  1.1    fvdl 	cd9660node *ptcur;
    163  1.1    fvdl 
    164  1.1    fvdl 	buffer = malloc(diskStructure.sectorSize * path_table_sectors);
    165  1.1    fvdl 	if (buffer == NULL) {
    166  1.4  dyoung 		warnx("%s: Memory allocation error allocating buffer",
    167  1.4  dyoung 		    __func__);
    168  1.1    fvdl 		return 0;
    169  1.1    fvdl 	}
    170  1.1    fvdl 	buffer_head = buffer;
    171  1.1    fvdl 	memset(buffer, 0, diskStructure.sectorSize * path_table_sectors);
    172  1.1    fvdl 
    173  1.1    fvdl 	ptcur = diskStructure.rootNode;
    174  1.3  dyoung 
    175  1.1    fvdl 	while (ptcur != NULL) {
    176  1.1    fvdl 		memset(&temp_entry, 0, sizeof(path_table_entry));
    177  1.1    fvdl 		temp_entry.length[0] = ptcur->isoDirRecord->name_len[0];
    178  1.1    fvdl 		temp_entry.extended_attribute_length[0] =
    179  1.1    fvdl 		    ptcur->isoDirRecord->ext_attr_length[0];
    180  1.1    fvdl 		memcpy(temp_entry.name, ptcur->isoDirRecord->name,
    181  1.1    fvdl 		    temp_entry.length[0] + 1);
    182  1.1    fvdl 
    183  1.1    fvdl 		/* round up */
    184  1.1    fvdl 		len = temp_entry.length[0] + 8 + (temp_entry.length[0] & 0x01);
    185  1.1    fvdl 
    186  1.1    fvdl                 /* todo: function pointers instead */
    187  1.1    fvdl 		if (mode == LITTLE_ENDIAN) {
    188  1.1    fvdl 			cd9660_731(ptcur->fileDataSector,
    189  1.1    fvdl 			    temp_entry.first_sector);
    190  1.1    fvdl 			cd9660_721((ptcur->parent == NULL ?
    191  1.1    fvdl 				1 : ptcur->parent->ptnumber),
    192  1.1    fvdl 			    temp_entry.parent_number);
    193  1.1    fvdl 		} else {
    194  1.1    fvdl 			cd9660_732(ptcur->fileDataSector,
    195  1.1    fvdl 			    temp_entry.first_sector);
    196  1.1    fvdl 			cd9660_722((ptcur->parent == NULL ?
    197  1.1    fvdl 				1 : ptcur->parent->ptnumber),
    198  1.1    fvdl 			    temp_entry.parent_number);
    199  1.1    fvdl 		}
    200  1.3  dyoung 
    201  1.1    fvdl 
    202  1.1    fvdl 		memcpy(buffer, &temp_entry, len);
    203  1.1    fvdl 		buffer += len;
    204  1.3  dyoung 
    205  1.1    fvdl 		ptcur = ptcur->ptnext;
    206  1.1    fvdl 	}
    207  1.3  dyoung 
    208  1.1    fvdl 	return cd9660_write_filedata(fd, sector, buffer_head,
    209  1.1    fvdl 	    path_table_sectors);
    210  1.1    fvdl }
    211  1.1    fvdl 
    212  1.1    fvdl 
    213  1.1    fvdl /*
    214  1.1    fvdl  * Write out the path tables to disk
    215  1.1    fvdl  * Each file descriptor should be pointed to by the PVD, so we know which
    216  1.1    fvdl  * sector to copy them to. One thing to watch out for: the only path tables
    217  1.1    fvdl  * stored are in the endian mode that the application is compiled for. So,
    218  1.1    fvdl  * the first thing to do is write out that path table, then to write the one
    219  1.1    fvdl  * in the other endian mode requires to convert the endianness of each entry
    220  1.1    fvdl  * in the table. The best way to do this would be to create a temporary
    221  1.1    fvdl  * path_table_entry structure, then for each path table entry, copy it to
    222  1.1    fvdl  * the temporary entry, translate, then copy that to disk.
    223  1.1    fvdl  *
    224  1.1    fvdl  * @param FILE* Valid file descriptor
    225  1.1    fvdl  * @returns int 0 on failure, 1 on success
    226  1.1    fvdl  */
    227  1.1    fvdl static int
    228  1.1    fvdl cd9660_write_path_tables(FILE *fd)
    229  1.1    fvdl {
    230  1.1    fvdl 	if (cd9660_write_path_table(fd,
    231  1.1    fvdl 	    diskStructure.primaryLittleEndianTableSector, LITTLE_ENDIAN) == 0)
    232  1.1    fvdl 		return 0;
    233  1.1    fvdl 
    234  1.1    fvdl 	if (cd9660_write_path_table(fd,
    235  1.1    fvdl 	    diskStructure.primaryBigEndianTableSector, BIG_ENDIAN) == 0)
    236  1.1    fvdl 		return 0;
    237  1.1    fvdl 
    238  1.1    fvdl 	/* @TODO: handle remaining two path tables */
    239  1.1    fvdl 	return 1;
    240  1.1    fvdl }
    241  1.1    fvdl 
    242  1.1    fvdl /*
    243  1.1    fvdl  * Write a file to disk
    244  1.1    fvdl  * Writes a file, its directory record, and its data to disk
    245  1.1    fvdl  * This file is designed to be called RECURSIVELY, so initially call it
    246  1.1    fvdl  * with the root node. All of the records should store what sector the
    247  1.1    fvdl  * file goes in, so no computation should be  necessary.
    248  1.1    fvdl  *
    249  1.1    fvdl  * @param int fd Valid file descriptor
    250  1.1    fvdl  * @param struct cd9660node* writenode Pointer to the file to be written
    251  1.1    fvdl  * @returns int 0 on failure, 1 on success
    252  1.1    fvdl  */
    253  1.1    fvdl static int
    254  1.1    fvdl cd9660_write_file(FILE *fd, cd9660node *writenode)
    255  1.1    fvdl {
    256  1.1    fvdl 	char *buf;
    257  1.1    fvdl 	char *temp_file_name;
    258  1.1    fvdl 	int ret;
    259  1.1    fvdl 	int working_sector;
    260  1.1    fvdl 	int cur_sector_offset;
    261  1.1    fvdl 	int written;
    262  1.1    fvdl 	iso_directory_record_cd9660 temp_record;
    263  1.1    fvdl 	cd9660node *temp;
    264  1.1    fvdl 	int ca = 0;
    265  1.1    fvdl 
    266  1.1    fvdl 	/* Todo : clean up variables */
    267  1.3  dyoung 
    268  1.1    fvdl 	temp_file_name = malloc(CD9660MAXPATH + 1);
    269  1.1    fvdl 	if (temp_file_name == NULL)
    270  1.4  dyoung 		err(EXIT_FAILURE, "%s: malloc", __func__);
    271  1.1    fvdl 
    272  1.1    fvdl 	memset(temp_file_name, 0, CD9660MAXPATH + 1);
    273  1.1    fvdl 
    274  1.1    fvdl 	buf = malloc(diskStructure.sectorSize);
    275  1.1    fvdl 	if (buf == NULL)
    276  1.4  dyoung 		err(EXIT_FAILURE, "%s: malloc", __func__);
    277  1.1    fvdl 
    278  1.1    fvdl 	if ((writenode->level != 0) &&
    279  1.1    fvdl 	    !(writenode->node->type & S_IFDIR)) {
    280  1.5  dyoung 		fsinode *inode = writenode->node->inode;
    281  1.5  dyoung 		/* Only attempt to write unwritten files that have length. */
    282  1.5  dyoung 		if ((inode->flags & FI_WRITTEN) != 0) {
    283  1.5  dyoung 			INODE_WARNX(("%s: skipping written inode %d", __func__,
    284  1.5  dyoung 			    (int)inode->st.st_ino));
    285  1.5  dyoung 		} else if (writenode->fileDataLength > 0) {
    286  1.6  dyoung 			INODE_WARNX(("%s: writing inode %d blocks at %" PRIu32,
    287  1.6  dyoung 			    __func__, (int)inode->st.st_ino, inode->ino));
    288  1.5  dyoung 			inode->flags |= FI_WRITTEN;
    289  1.1    fvdl 			cd9660_compute_full_filename(writenode,
    290  1.1    fvdl 			    temp_file_name, 0);
    291  1.1    fvdl 			ret = cd9660_copy_file(fd, writenode->fileDataSector,
    292  1.1    fvdl 			    temp_file_name);
    293  1.1    fvdl 			if (ret == 0) {
    294  1.1    fvdl 				free(temp_file_name);
    295  1.1    fvdl 				return 0;
    296  1.1    fvdl 			}
    297  1.1    fvdl 		}
    298  1.1    fvdl 	} else {
    299  1.1    fvdl 		/*
    300  1.1    fvdl 		 * Here is a new revelation that ECMA didnt explain
    301  1.1    fvdl 		 * (at least not well).
    302  1.1    fvdl 		 * ALL . and .. records store the name "\0" and "\1"
    303  1.1    fvdl 		 * resepctively. So, for each directory, we have to
    304  1.1    fvdl 		 * make a new node.
    305  1.1    fvdl 		 *
    306  1.1    fvdl 		 * This is where it gets kinda messy, since we have to
    307  1.1    fvdl 		 * be careful of sector boundaries
    308  1.1    fvdl 		 */
    309  1.1    fvdl 		cur_sector_offset = 0;
    310  1.1    fvdl 		working_sector = writenode->fileDataSector;
    311  1.1    fvdl 		fseek(fd, working_sector * diskStructure.sectorSize, SEEK_SET);
    312  1.3  dyoung 
    313  1.1    fvdl 		/*
    314  1.1    fvdl 		 * Now loop over children, writing out their directory
    315  1.1    fvdl 		 * records - beware of sector boundaries
    316  1.1    fvdl 	 	 */
    317  1.2  dyoung 		TAILQ_FOREACH(temp, &writenode->cn_children, cn_next_child) {
    318  1.1    fvdl 			/*
    319  1.1    fvdl 			 * Copy the temporary record and adjust its size
    320  1.1    fvdl 			 * if necessary
    321  1.1    fvdl 			 */
    322  1.1    fvdl 			memcpy(&temp_record, temp->isoDirRecord,
    323  1.1    fvdl 			    sizeof(iso_directory_record_cd9660));
    324  1.1    fvdl 
    325  1.1    fvdl 			temp_record.length[0] =
    326  1.1    fvdl 			    cd9660_compute_record_size(temp);
    327  1.3  dyoung 
    328  1.1    fvdl 			if (temp_record.length[0] + cur_sector_offset >=
    329  1.1    fvdl 			    diskStructure.sectorSize) {
    330  1.1    fvdl 				cur_sector_offset = 0;
    331  1.1    fvdl 				working_sector++;
    332  1.1    fvdl 
    333  1.1    fvdl 				/* Seek to the next sector. */
    334  1.1    fvdl 				fseek(fd,
    335  1.1    fvdl 				    working_sector * diskStructure.sectorSize,
    336  1.1    fvdl 				    SEEK_SET);
    337  1.1    fvdl 			}
    338  1.3  dyoung 
    339  1.2  dyoung 			written = fwrite(&temp_record, 1, temp_record.length[0],
    340  1.2  dyoung 			    fd);
    341  1.1    fvdl 			ca = 0;
    342  1.1    fvdl 			if (diskStructure.rock_ridge_enabled) {
    343  1.1    fvdl 				ca = cd9660_write_rr(fd, temp,
    344  1.1    fvdl 				    cur_sector_offset, working_sector);
    345  1.1    fvdl 			}
    346  1.3  dyoung 
    347  1.1    fvdl 			if (ferror(fd)) {
    348  1.4  dyoung 				warnx("%s: write error", __func__);
    349  1.1    fvdl 				free(temp_file_name);
    350  1.1    fvdl 				return 0;
    351  1.1    fvdl 			}
    352  1.1    fvdl 			cur_sector_offset += temp_record.length[0];
    353  1.1    fvdl 
    354  1.1    fvdl 			/*
    355  1.1    fvdl 			 * If we had to go the the continuation area,
    356  1.1    fvdl 			 * head back to where we should be.
    357  1.1    fvdl 			 */
    358  1.1    fvdl 			if (ca) {
    359  1.1    fvdl 				fseek(fd,
    360  1.1    fvdl 				    working_sector * diskStructure.sectorSize +
    361  1.1    fvdl 					cur_sector_offset,
    362  1.1    fvdl 				    SEEK_SET);
    363  1.1    fvdl 			}
    364  1.1    fvdl 		}
    365  1.3  dyoung 
    366  1.1    fvdl 		/*
    367  1.2  dyoung 		 * Recurse on children.
    368  1.1    fvdl 		 */
    369  1.2  dyoung 		TAILQ_FOREACH(temp, &writenode->cn_children, cn_next_child) {
    370  1.2  dyoung 			if ((ret = cd9660_write_file(fd, temp)) == 0) {
    371  1.1    fvdl 				free(temp_file_name);
    372  1.1    fvdl 				return 0;
    373  1.1    fvdl 			}
    374  1.1    fvdl 		}
    375  1.1    fvdl 	}
    376  1.1    fvdl 	free(temp_file_name);
    377  1.1    fvdl 	return 1;
    378  1.1    fvdl }
    379  1.1    fvdl 
    380  1.1    fvdl /*
    381  1.1    fvdl  * Wrapper function to write a buffer (one sector) to disk.
    382  1.1    fvdl  * Seeks and writes the buffer.
    383  1.1    fvdl  * NOTE: You dont NEED to use this function, but it might make your
    384  1.1    fvdl  * life easier if you have to write things that align to a sector
    385  1.1    fvdl  * (such as volume descriptors).
    386  1.1    fvdl  *
    387  1.1    fvdl  * @param int fd Valid file descriptor
    388  1.1    fvdl  * @param int sector Sector number to write to
    389  1.1    fvdl  * @param const unsigned char* Buffer to write. This should be the
    390  1.1    fvdl  *                             size of a sector, and if only a portion
    391  1.1    fvdl  *                             is written, the rest should be set to 0.
    392  1.1    fvdl  */
    393  1.1    fvdl static int
    394  1.1    fvdl cd9660_write_filedata(FILE *fd, int sector, const unsigned char *buf,
    395  1.1    fvdl 		      int numsecs)
    396  1.1    fvdl {
    397  1.1    fvdl 	off_t curpos;
    398  1.1    fvdl 	size_t success;
    399  1.1    fvdl 
    400  1.1    fvdl 	curpos = ftello(fd);
    401  1.3  dyoung 
    402  1.1    fvdl 	fseek(fd, sector * diskStructure.sectorSize, SEEK_SET);
    403  1.1    fvdl 
    404  1.1    fvdl 	success = fwrite(buf, diskStructure.sectorSize * numsecs, 1, fd);
    405  1.1    fvdl 
    406  1.1    fvdl 	fseek(fd, curpos, SEEK_SET);
    407  1.1    fvdl 
    408  1.1    fvdl 	if (success == 1)
    409  1.1    fvdl 		success = diskStructure.sectorSize * numsecs;
    410  1.1    fvdl 	return success;
    411  1.1    fvdl }
    412  1.1    fvdl 
    413  1.1    fvdl #if 0
    414  1.1    fvdl static int
    415  1.1    fvdl cd9660_write_buffered(FILE *fd, int offset, int buff_len,
    416  1.1    fvdl 		      const unsigned char* buffer)
    417  1.1    fvdl {
    418  1.1    fvdl 	static int working_sector = -1;
    419  1.1    fvdl 	static char buf[2048];
    420  1.3  dyoung 
    421  1.1    fvdl 	return 0;
    422  1.1    fvdl }
    423  1.1    fvdl #endif
    424  1.1    fvdl 
    425  1.1    fvdl int
    426  1.1    fvdl cd9660_copy_file(FILE *fd, int start_sector, const char *filename)
    427  1.1    fvdl {
    428  1.1    fvdl 	FILE *rf;
    429  1.1    fvdl 	int bytes_read;
    430  1.1    fvdl 	int sector = start_sector;
    431  1.1    fvdl 	int buf_size = diskStructure.sectorSize;
    432  1.1    fvdl 	char *buf;
    433  1.1    fvdl 
    434  1.1    fvdl 	buf = malloc(buf_size);
    435  1.1    fvdl 	if (buf == NULL)
    436  1.4  dyoung 		err(EXIT_FAILURE, "%s: malloc", __func__);
    437  1.3  dyoung 
    438  1.1    fvdl 	if ((rf = fopen(filename, "rb")) == NULL) {
    439  1.4  dyoung 		warn("%s: cannot open %s", __func__, filename);
    440  1.3  dyoung 		return 0;
    441  1.1    fvdl 	}
    442  1.1    fvdl 
    443  1.1    fvdl 	if (diskStructure.verbose_level > 1)
    444  1.1    fvdl 		printf("Writing file: %s\n",filename);
    445  1.3  dyoung 
    446  1.1    fvdl 	fseek(fd, start_sector * diskStructure.sectorSize, SEEK_SET);
    447  1.3  dyoung 
    448  1.1    fvdl 	while (!feof(rf)) {
    449  1.1    fvdl 		bytes_read = fread(buf,1,buf_size,rf);
    450  1.1    fvdl 		if (ferror(rf)) {
    451  1.4  dyoung 			warn("%s: fread", __func__);
    452  1.3  dyoung 			return 0;
    453  1.1    fvdl 		}
    454  1.3  dyoung 
    455  1.1    fvdl 		fwrite(buf,1,bytes_read,fd);
    456  1.1    fvdl 		if (ferror(fd)) {
    457  1.4  dyoung 			warn("%s: fwrite", __func__);
    458  1.3  dyoung 			return 0;
    459  1.1    fvdl 		}
    460  1.1    fvdl 		sector++;
    461  1.1    fvdl 	}
    462  1.3  dyoung 
    463  1.1    fvdl 	fclose(rf);
    464  1.1    fvdl 	free(buf);
    465  1.1    fvdl 	return 1;
    466  1.1    fvdl }
    467  1.1    fvdl 
    468  1.1    fvdl static int
    469  1.1    fvdl cd9660_write_rr(FILE *fd, cd9660node *writenode, int offset, int sector)
    470  1.1    fvdl {
    471  1.1    fvdl 	int in_ca = 0;
    472  1.1    fvdl 	struct ISO_SUSP_ATTRIBUTES *myattr;
    473  1.1    fvdl 
    474  1.1    fvdl 	offset += writenode->isoDirRecord->length[0];
    475  1.1    fvdl 
    476  1.1    fvdl 	/* Offset now points at the end of the record */
    477  1.2  dyoung 	TAILQ_FOREACH(myattr, &writenode->head, rr_ll) {
    478  1.3  dyoung 		fseek(fd,
    479  1.1    fvdl 		    in_ca ? offset : sector*diskStructure.sectorSize + offset,
    480  1.1    fvdl 		    SEEK_SET);
    481  1.1    fvdl 		fwrite(&(myattr->attr), CD9660_SUSP_ENTRY_SIZE(myattr), 1, fd);
    482  1.1    fvdl 
    483  1.1    fvdl 		offset += CD9660_SUSP_ENTRY_SIZE(myattr);
    484  1.1    fvdl 		if (!in_ca) {
    485  1.1    fvdl 			if ((myattr->susp_type == SUSP_TYPE_SUSP) &&
    486  1.1    fvdl 			    (myattr->entry_type == SUSP_ENTRY_SUSP_CE)) {
    487  1.1    fvdl 				/*
    488  1.1    fvdl 				 * Point the offset to the start of this
    489  1.1    fvdl 				 * record's CE area
    490  1.1    fvdl 				 */
    491  1.1    fvdl 				offset = (diskStructure.
    492  1.3  dyoung 					  susp_continuation_area_start_sector *
    493  1.1    fvdl 					    diskStructure.sectorSize)
    494  1.1    fvdl 					+ writenode->susp_entry_ce_start;
    495  1.1    fvdl 				in_ca = 1;
    496  1.1    fvdl 			}
    497  1.1    fvdl 		}
    498  1.1    fvdl 	}
    499  1.1    fvdl 
    500  1.1    fvdl 	return in_ca;
    501  1.1    fvdl }
    502