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