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