15978408cSSascha Wildner /* $NetBSD: cd9660_write.c,v 1.14 2011/01/04 09:48:21 wiz Exp $ */
25978408cSSascha Wildner
35978408cSSascha Wildner /*-
45978408cSSascha Wildner * SPDX-License-Identifier: BSD-2-Clause-NetBSD
55978408cSSascha Wildner *
65978408cSSascha Wildner * Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
75978408cSSascha Wildner * Perez-Rathke and Ram Vedam. All rights reserved.
85978408cSSascha Wildner *
95978408cSSascha Wildner * This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
105978408cSSascha Wildner * Alan Perez-Rathke and Ram Vedam.
115978408cSSascha Wildner *
125978408cSSascha Wildner * Redistribution and use in source and binary forms, with or
135978408cSSascha Wildner * without modification, are permitted provided that the following
145978408cSSascha Wildner * conditions are met:
155978408cSSascha Wildner * 1. Redistributions of source code must retain the above copyright
165978408cSSascha Wildner * notice, this list of conditions and the following disclaimer.
175978408cSSascha Wildner * 2. Redistributions in binary form must reproduce the above
185978408cSSascha Wildner * copyright notice, this list of conditions and the following
195978408cSSascha Wildner * disclaimer in the documentation and/or other materials provided
205978408cSSascha Wildner * with the distribution.
215978408cSSascha Wildner *
225978408cSSascha Wildner * THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
235978408cSSascha Wildner * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
245978408cSSascha Wildner * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
255978408cSSascha Wildner * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
265978408cSSascha Wildner * DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
275978408cSSascha Wildner * GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
285978408cSSascha Wildner * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
295978408cSSascha Wildner * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
305978408cSSascha Wildner * USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
315978408cSSascha Wildner * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
325978408cSSascha Wildner * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
335978408cSSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
345978408cSSascha Wildner * OF SUCH DAMAGE.
35811c2036SSascha Wildner *
36811c2036SSascha Wildner * $FreeBSD: head/usr.sbin/makefs/cd9660/cd9660_write.c 326276 2017-11-27 15:37:16Z pfg $
375978408cSSascha Wildner */
385978408cSSascha Wildner
395978408cSSascha Wildner #include "cd9660.h"
405978408cSSascha Wildner #include "iso9660_rrip.h"
415978408cSSascha Wildner
425978408cSSascha Wildner #include <util.h>
435978408cSSascha Wildner
445978408cSSascha Wildner static int cd9660_write_volume_descriptors(iso9660_disk *, FILE *);
455978408cSSascha Wildner static int cd9660_write_path_table(iso9660_disk *, FILE *, off_t, int);
465978408cSSascha Wildner static int cd9660_write_path_tables(iso9660_disk *, FILE *);
475978408cSSascha Wildner static int cd9660_write_file(iso9660_disk *, FILE *, cd9660node *);
485978408cSSascha Wildner static int cd9660_write_filedata(iso9660_disk *, FILE *, off_t,
495978408cSSascha Wildner const unsigned char *, int);
505978408cSSascha Wildner #if 0
515978408cSSascha Wildner static int cd9660_write_buffered(FILE *, off_t, int, const unsigned char *);
525978408cSSascha Wildner #endif
535978408cSSascha Wildner static void cd9660_write_rr(iso9660_disk *, FILE *, cd9660node *, off_t, off_t);
545978408cSSascha Wildner
555978408cSSascha Wildner /*
565978408cSSascha Wildner * Write the image
575978408cSSascha Wildner * Writes the entire image
585978408cSSascha Wildner * @param const char* The filename for the image
595978408cSSascha Wildner * @returns int 1 on success, 0 on failure
605978408cSSascha Wildner */
615978408cSSascha Wildner int
cd9660_write_image(iso9660_disk * diskStructure,const char * image)625978408cSSascha Wildner cd9660_write_image(iso9660_disk *diskStructure, const char* image)
635978408cSSascha Wildner {
645978408cSSascha Wildner FILE *fd;
655978408cSSascha Wildner int status;
665978408cSSascha Wildner char buf[CD9660_SECTOR_SIZE];
675978408cSSascha Wildner
685978408cSSascha Wildner if ((fd = fopen(image, "w+")) == NULL) {
695978408cSSascha Wildner err(EXIT_FAILURE, "%s: Can't open `%s' for writing", __func__,
705978408cSSascha Wildner image);
715978408cSSascha Wildner }
725978408cSSascha Wildner
735978408cSSascha Wildner if (diskStructure->verbose_level > 0)
745978408cSSascha Wildner printf("Writing image\n");
755978408cSSascha Wildner
765978408cSSascha Wildner if (diskStructure->has_generic_bootimage) {
775978408cSSascha Wildner status = cd9660_copy_file(diskStructure, fd, 0,
785978408cSSascha Wildner diskStructure->generic_bootimage);
795978408cSSascha Wildner if (status == 0) {
805978408cSSascha Wildner warnx("%s: Error writing generic boot image",
815978408cSSascha Wildner __func__);
825978408cSSascha Wildner goto cleanup_bad_image;
835978408cSSascha Wildner }
845978408cSSascha Wildner }
855978408cSSascha Wildner
865978408cSSascha Wildner /* Write the volume descriptors */
875978408cSSascha Wildner status = cd9660_write_volume_descriptors(diskStructure, fd);
885978408cSSascha Wildner if (status == 0) {
895978408cSSascha Wildner warnx("%s: Error writing volume descriptors to image",
905978408cSSascha Wildner __func__);
915978408cSSascha Wildner goto cleanup_bad_image;
925978408cSSascha Wildner }
935978408cSSascha Wildner
945978408cSSascha Wildner if (diskStructure->verbose_level > 0)
955978408cSSascha Wildner printf("Volume descriptors written\n");
965978408cSSascha Wildner
975978408cSSascha Wildner /*
985978408cSSascha Wildner * Write the path tables: there are actually four, but right
99*2946f173STomohiro Kusumi * now we are only concerned with two.
1005978408cSSascha Wildner */
1015978408cSSascha Wildner status = cd9660_write_path_tables(diskStructure, fd);
1025978408cSSascha Wildner if (status == 0) {
1035978408cSSascha Wildner warnx("%s: Error writing path tables to image", __func__);
1045978408cSSascha Wildner goto cleanup_bad_image;
1055978408cSSascha Wildner }
1065978408cSSascha Wildner
1075978408cSSascha Wildner if (diskStructure->verbose_level > 0)
1085978408cSSascha Wildner printf("Path tables written\n");
1095978408cSSascha Wildner
1105978408cSSascha Wildner /* Write the directories and files */
1115978408cSSascha Wildner status = cd9660_write_file(diskStructure, fd, diskStructure->rootNode);
1125978408cSSascha Wildner if (status == 0) {
1135978408cSSascha Wildner warnx("%s: Error writing files to image", __func__);
1145978408cSSascha Wildner goto cleanup_bad_image;
1155978408cSSascha Wildner }
1165978408cSSascha Wildner
1175978408cSSascha Wildner if (diskStructure->is_bootable) {
1185978408cSSascha Wildner cd9660_write_boot(diskStructure, fd);
1195978408cSSascha Wildner }
1205978408cSSascha Wildner
1215978408cSSascha Wildner /* Write padding bits. This is temporary */
1225978408cSSascha Wildner memset(buf, 0, CD9660_SECTOR_SIZE);
1235978408cSSascha Wildner cd9660_write_filedata(diskStructure, fd,
1245978408cSSascha Wildner diskStructure->totalSectors - 1, buf, 1);
1255978408cSSascha Wildner
1265978408cSSascha Wildner if (diskStructure->verbose_level > 0)
1275978408cSSascha Wildner printf("Files written\n");
1285978408cSSascha Wildner fclose(fd);
1295978408cSSascha Wildner
1305978408cSSascha Wildner if (diskStructure->verbose_level > 0)
1315978408cSSascha Wildner printf("Image closed\n");
1325978408cSSascha Wildner return 1;
1335978408cSSascha Wildner
1345978408cSSascha Wildner cleanup_bad_image:
1355978408cSSascha Wildner fclose(fd);
1365978408cSSascha Wildner if (!diskStructure->keep_bad_images)
1375978408cSSascha Wildner unlink(image);
1385978408cSSascha Wildner if (diskStructure->verbose_level > 0)
1395978408cSSascha Wildner printf("Bad image cleaned up\n");
1405978408cSSascha Wildner return 0;
1415978408cSSascha Wildner }
1425978408cSSascha Wildner
1435978408cSSascha Wildner static int
cd9660_write_volume_descriptors(iso9660_disk * diskStructure,FILE * fd)1445978408cSSascha Wildner cd9660_write_volume_descriptors(iso9660_disk *diskStructure, FILE *fd)
1455978408cSSascha Wildner {
1465978408cSSascha Wildner volume_descriptor *vd_temp = diskStructure->firstVolumeDescriptor;
1475978408cSSascha Wildner
1485978408cSSascha Wildner while (vd_temp != NULL) {
1495978408cSSascha Wildner cd9660_write_filedata(diskStructure, fd, vd_temp->sector,
1505978408cSSascha Wildner vd_temp->volumeDescriptorData, 1);
1515978408cSSascha Wildner vd_temp = vd_temp->next;
1525978408cSSascha Wildner }
1535978408cSSascha Wildner return 1;
1545978408cSSascha Wildner }
1555978408cSSascha Wildner
1565978408cSSascha Wildner /*
1575978408cSSascha Wildner * Write out an individual path table
1585978408cSSascha Wildner * Used just to keep redundant code to a minimum
1595978408cSSascha Wildner * @param FILE *fd Valid file pointer
1605978408cSSascha Wildner * @param int Sector to start writing path table to
1615978408cSSascha Wildner * @param int Endian mode : BIG_ENDIAN or LITTLE_ENDIAN
1625978408cSSascha Wildner * @returns int 1 on success, 0 on failure
1635978408cSSascha Wildner */
1645978408cSSascha Wildner static int
cd9660_write_path_table(iso9660_disk * diskStructure,FILE * fd,off_t sector,int mode)1655978408cSSascha Wildner cd9660_write_path_table(iso9660_disk *diskStructure, FILE *fd, off_t sector,
1665978408cSSascha Wildner int mode)
1675978408cSSascha Wildner {
1685978408cSSascha Wildner int path_table_sectors = CD9660_BLOCKS(diskStructure->sectorSize,
1695978408cSSascha Wildner diskStructure->pathTableLength);
1705978408cSSascha Wildner unsigned char *buffer;
1715978408cSSascha Wildner unsigned char *buffer_head;
1725978408cSSascha Wildner int len, ret;
1735978408cSSascha Wildner path_table_entry temp_entry;
1745978408cSSascha Wildner cd9660node *ptcur;
1755978408cSSascha Wildner
1765978408cSSascha Wildner buffer = ecalloc(path_table_sectors, diskStructure->sectorSize);
1775978408cSSascha Wildner buffer_head = buffer;
1785978408cSSascha Wildner
1795978408cSSascha Wildner ptcur = diskStructure->rootNode;
1805978408cSSascha Wildner
1815978408cSSascha Wildner while (ptcur != NULL) {
1825978408cSSascha Wildner memset(&temp_entry, 0, sizeof(path_table_entry));
1835978408cSSascha Wildner temp_entry.length[0] = ptcur->isoDirRecord->name_len[0];
1845978408cSSascha Wildner temp_entry.extended_attribute_length[0] =
1855978408cSSascha Wildner ptcur->isoDirRecord->ext_attr_length[0];
1865978408cSSascha Wildner memcpy(temp_entry.name, ptcur->isoDirRecord->name,
1875978408cSSascha Wildner temp_entry.length[0] + 1);
1885978408cSSascha Wildner
1895978408cSSascha Wildner /* round up */
1905978408cSSascha Wildner len = temp_entry.length[0] + 8 + (temp_entry.length[0] & 0x01);
1915978408cSSascha Wildner
1925978408cSSascha Wildner /* todo: function pointers instead */
1935978408cSSascha Wildner if (mode == LITTLE_ENDIAN) {
1945978408cSSascha Wildner cd9660_731(ptcur->fileDataSector,
1955978408cSSascha Wildner temp_entry.first_sector);
1965978408cSSascha Wildner cd9660_721((ptcur->parent == NULL ?
1975978408cSSascha Wildner 1 : ptcur->parent->ptnumber),
1985978408cSSascha Wildner temp_entry.parent_number);
1995978408cSSascha Wildner } else {
2005978408cSSascha Wildner cd9660_732(ptcur->fileDataSector,
2015978408cSSascha Wildner temp_entry.first_sector);
2025978408cSSascha Wildner cd9660_722((ptcur->parent == NULL ?
2035978408cSSascha Wildner 1 : ptcur->parent->ptnumber),
2045978408cSSascha Wildner temp_entry.parent_number);
2055978408cSSascha Wildner }
2065978408cSSascha Wildner
2075978408cSSascha Wildner
2085978408cSSascha Wildner memcpy(buffer, &temp_entry, len);
2095978408cSSascha Wildner buffer += len;
2105978408cSSascha Wildner
2115978408cSSascha Wildner ptcur = ptcur->ptnext;
2125978408cSSascha Wildner }
2135978408cSSascha Wildner
2145978408cSSascha Wildner ret = cd9660_write_filedata(diskStructure, fd, sector, buffer_head,
2155978408cSSascha Wildner path_table_sectors);
2165978408cSSascha Wildner free(buffer_head);
2175978408cSSascha Wildner return ret;
2185978408cSSascha Wildner }
2195978408cSSascha Wildner
2205978408cSSascha Wildner
2215978408cSSascha Wildner /*
2225978408cSSascha Wildner * Write out the path tables to disk
2235978408cSSascha Wildner * Each file descriptor should be pointed to by the PVD, so we know which
2245978408cSSascha Wildner * sector to copy them to. One thing to watch out for: the only path tables
2255978408cSSascha Wildner * stored are in the endian mode that the application is compiled for. So,
2265978408cSSascha Wildner * the first thing to do is write out that path table, then to write the one
2275978408cSSascha Wildner * in the other endian mode requires to convert the endianness of each entry
2285978408cSSascha Wildner * in the table. The best way to do this would be to create a temporary
2295978408cSSascha Wildner * path_table_entry structure, then for each path table entry, copy it to
2305978408cSSascha Wildner * the temporary entry, translate, then copy that to disk.
2315978408cSSascha Wildner *
2325978408cSSascha Wildner * @param FILE* Valid file descriptor
2335978408cSSascha Wildner * @returns int 0 on failure, 1 on success
2345978408cSSascha Wildner */
2355978408cSSascha Wildner static int
cd9660_write_path_tables(iso9660_disk * diskStructure,FILE * fd)2365978408cSSascha Wildner cd9660_write_path_tables(iso9660_disk *diskStructure, FILE *fd)
2375978408cSSascha Wildner {
2385978408cSSascha Wildner if (cd9660_write_path_table(diskStructure, fd,
2395978408cSSascha Wildner diskStructure->primaryLittleEndianTableSector, LITTLE_ENDIAN) == 0)
2405978408cSSascha Wildner return 0;
2415978408cSSascha Wildner
2425978408cSSascha Wildner if (cd9660_write_path_table(diskStructure, fd,
2435978408cSSascha Wildner diskStructure->primaryBigEndianTableSector, BIG_ENDIAN) == 0)
2445978408cSSascha Wildner return 0;
2455978408cSSascha Wildner
2465978408cSSascha Wildner /* @TODO: handle remaining two path tables */
2475978408cSSascha Wildner return 1;
2485978408cSSascha Wildner }
2495978408cSSascha Wildner
2505978408cSSascha Wildner /*
2515978408cSSascha Wildner * Write a file to disk
2525978408cSSascha Wildner * Writes a file, its directory record, and its data to disk
2535978408cSSascha Wildner * This file is designed to be called RECURSIVELY, so initially call it
2545978408cSSascha Wildner * with the root node. All of the records should store what sector the
2555978408cSSascha Wildner * file goes in, so no computation should be necessary.
2565978408cSSascha Wildner *
2575978408cSSascha Wildner * @param int fd Valid file descriptor
2585978408cSSascha Wildner * @param struct cd9660node* writenode Pointer to the file to be written
2595978408cSSascha Wildner * @returns int 0 on failure, 1 on success
2605978408cSSascha Wildner */
2615978408cSSascha Wildner static int
cd9660_write_file(iso9660_disk * diskStructure,FILE * fd,cd9660node * writenode)2625978408cSSascha Wildner cd9660_write_file(iso9660_disk *diskStructure, FILE *fd, cd9660node *writenode)
2635978408cSSascha Wildner {
2645978408cSSascha Wildner char *buf;
2655978408cSSascha Wildner char *temp_file_name;
2665978408cSSascha Wildner int ret;
2675978408cSSascha Wildner off_t working_sector;
2685978408cSSascha Wildner int cur_sector_offset;
2695978408cSSascha Wildner iso_directory_record_cd9660 temp_record;
2705978408cSSascha Wildner cd9660node *temp;
2715978408cSSascha Wildner int rv = 0;
2725978408cSSascha Wildner
2735978408cSSascha Wildner /* Todo : clean up variables */
2745978408cSSascha Wildner
2755978408cSSascha Wildner temp_file_name = ecalloc(CD9660MAXPATH + 1, 1);
2765978408cSSascha Wildner buf = emalloc(diskStructure->sectorSize);
2775978408cSSascha Wildner if ((writenode->level != 0) &&
2785978408cSSascha Wildner !(writenode->node->type & S_IFDIR)) {
2795978408cSSascha Wildner fsinode *inode = writenode->node->inode;
2805978408cSSascha Wildner /* Only attempt to write unwritten files that have length. */
2815978408cSSascha Wildner if ((inode->flags & FI_WRITTEN) != 0) {
2825978408cSSascha Wildner INODE_WARNX(("%s: skipping written inode %d", __func__,
2835978408cSSascha Wildner (int)inode->st.st_ino));
2845978408cSSascha Wildner } else if (writenode->fileDataLength > 0) {
2855978408cSSascha Wildner INODE_WARNX(("%s: writing inode %d blocks at %" PRIu32,
2865978408cSSascha Wildner __func__, (int)inode->st.st_ino, inode->ino));
2875978408cSSascha Wildner inode->flags |= FI_WRITTEN;
2885978408cSSascha Wildner if (writenode->node->contents == NULL)
2895978408cSSascha Wildner cd9660_compute_full_filename(writenode,
2905978408cSSascha Wildner temp_file_name);
2915978408cSSascha Wildner ret = cd9660_copy_file(diskStructure, fd,
2925978408cSSascha Wildner writenode->fileDataSector,
2935978408cSSascha Wildner (writenode->node->contents != NULL) ?
2945978408cSSascha Wildner writenode->node->contents : temp_file_name);
2955978408cSSascha Wildner if (ret == 0)
2965978408cSSascha Wildner goto out;
2975978408cSSascha Wildner }
2985978408cSSascha Wildner } else {
2995978408cSSascha Wildner /*
3005978408cSSascha Wildner * Here is a new revelation that ECMA didn't explain
3015978408cSSascha Wildner * (at least not well).
3025978408cSSascha Wildner * ALL . and .. records store the name "\0" and "\1"
3035978408cSSascha Wildner * respectively. So, for each directory, we have to
3045978408cSSascha Wildner * make a new node.
3055978408cSSascha Wildner *
3065978408cSSascha Wildner * This is where it gets kinda messy, since we have to
3075978408cSSascha Wildner * be careful of sector boundaries
3085978408cSSascha Wildner */
3095978408cSSascha Wildner cur_sector_offset = 0;
3105978408cSSascha Wildner working_sector = writenode->fileDataSector;
3115978408cSSascha Wildner if (fseeko(fd, working_sector * diskStructure->sectorSize,
3125978408cSSascha Wildner SEEK_SET) == -1)
3135978408cSSascha Wildner err(1, "fseeko");
3145978408cSSascha Wildner
3155978408cSSascha Wildner /*
3165978408cSSascha Wildner * Now loop over children, writing out their directory
3175978408cSSascha Wildner * records - beware of sector boundaries
3185978408cSSascha Wildner */
3195978408cSSascha Wildner TAILQ_FOREACH(temp, &writenode->cn_children, cn_next_child) {
3205978408cSSascha Wildner /*
3215978408cSSascha Wildner * Copy the temporary record and adjust its size
3225978408cSSascha Wildner * if necessary
3235978408cSSascha Wildner */
3245978408cSSascha Wildner memcpy(&temp_record, temp->isoDirRecord,
3255978408cSSascha Wildner sizeof(iso_directory_record_cd9660));
3265978408cSSascha Wildner
3275978408cSSascha Wildner temp_record.length[0] =
3285978408cSSascha Wildner cd9660_compute_record_size(diskStructure, temp);
3295978408cSSascha Wildner
3305978408cSSascha Wildner if (temp_record.length[0] + cur_sector_offset >=
3315978408cSSascha Wildner diskStructure->sectorSize) {
3325978408cSSascha Wildner cur_sector_offset = 0;
3335978408cSSascha Wildner working_sector++;
3345978408cSSascha Wildner
3355978408cSSascha Wildner /* Seek to the next sector. */
3365978408cSSascha Wildner if (fseeko(fd, working_sector *
3375978408cSSascha Wildner diskStructure->sectorSize, SEEK_SET) == -1)
3385978408cSSascha Wildner err(1, "fseeko");
3395978408cSSascha Wildner }
3405978408cSSascha Wildner /* Write out the basic ISO directory record */
3415978408cSSascha Wildner (void)fwrite(&temp_record, 1,
3425978408cSSascha Wildner temp->isoDirRecord->length[0], fd);
3435978408cSSascha Wildner if (diskStructure->rock_ridge_enabled) {
3445978408cSSascha Wildner cd9660_write_rr(diskStructure, fd, temp,
3455978408cSSascha Wildner cur_sector_offset, working_sector);
3465978408cSSascha Wildner }
3475978408cSSascha Wildner if (fseeko(fd, working_sector *
3485978408cSSascha Wildner diskStructure->sectorSize + cur_sector_offset +
3495978408cSSascha Wildner temp_record.length[0] - temp->su_tail_size,
3505978408cSSascha Wildner SEEK_SET) == -1)
3515978408cSSascha Wildner err(1, "fseeko");
3525978408cSSascha Wildner if (temp->su_tail_size > 0)
3535978408cSSascha Wildner fwrite(temp->su_tail_data, 1,
3545978408cSSascha Wildner temp->su_tail_size, fd);
3555978408cSSascha Wildner if (ferror(fd)) {
3565978408cSSascha Wildner warnx("%s: write error", __func__);
3575978408cSSascha Wildner goto out;
3585978408cSSascha Wildner }
3595978408cSSascha Wildner cur_sector_offset += temp_record.length[0];
3605978408cSSascha Wildner
3615978408cSSascha Wildner }
3625978408cSSascha Wildner
3635978408cSSascha Wildner /*
3645978408cSSascha Wildner * Recurse on children.
3655978408cSSascha Wildner */
3665978408cSSascha Wildner TAILQ_FOREACH(temp, &writenode->cn_children, cn_next_child) {
3675978408cSSascha Wildner if ((ret = cd9660_write_file(diskStructure, fd, temp)) == 0)
3685978408cSSascha Wildner goto out;
3695978408cSSascha Wildner }
3705978408cSSascha Wildner }
3715978408cSSascha Wildner rv = 1;
3725978408cSSascha Wildner out:
3735978408cSSascha Wildner free(temp_file_name);
3745978408cSSascha Wildner free(buf);
3755978408cSSascha Wildner return rv;
3765978408cSSascha Wildner }
3775978408cSSascha Wildner
3785978408cSSascha Wildner /*
3795978408cSSascha Wildner * Wrapper function to write a buffer (one sector) to disk.
3805978408cSSascha Wildner * Seeks and writes the buffer.
3815978408cSSascha Wildner * NOTE: You dont NEED to use this function, but it might make your
3825978408cSSascha Wildner * life easier if you have to write things that align to a sector
3835978408cSSascha Wildner * (such as volume descriptors).
3845978408cSSascha Wildner *
3855978408cSSascha Wildner * @param int fd Valid file descriptor
3865978408cSSascha Wildner * @param int sector Sector number to write to
3875978408cSSascha Wildner * @param const unsigned char* Buffer to write. This should be the
3885978408cSSascha Wildner * size of a sector, and if only a portion
3895978408cSSascha Wildner * is written, the rest should be set to 0.
3905978408cSSascha Wildner */
3915978408cSSascha Wildner static int
cd9660_write_filedata(iso9660_disk * diskStructure,FILE * fd,off_t sector,const unsigned char * buf,int numsecs)3925978408cSSascha Wildner cd9660_write_filedata(iso9660_disk *diskStructure, FILE *fd, off_t sector,
3935978408cSSascha Wildner const unsigned char *buf, int numsecs)
3945978408cSSascha Wildner {
3955978408cSSascha Wildner off_t curpos;
3965978408cSSascha Wildner size_t success;
3975978408cSSascha Wildner
3985978408cSSascha Wildner curpos = ftello(fd);
3995978408cSSascha Wildner
4005978408cSSascha Wildner if (fseeko(fd, sector * diskStructure->sectorSize, SEEK_SET) == -1)
4015978408cSSascha Wildner err(1, "fseeko");
4025978408cSSascha Wildner
4035978408cSSascha Wildner success = fwrite(buf, diskStructure->sectorSize * numsecs, 1, fd);
4045978408cSSascha Wildner
4055978408cSSascha Wildner if (fseeko(fd, curpos, SEEK_SET) == -1)
4065978408cSSascha Wildner err(1, "fseeko");
4075978408cSSascha Wildner
4085978408cSSascha Wildner if (success == 1)
4095978408cSSascha Wildner success = diskStructure->sectorSize * numsecs;
4105978408cSSascha Wildner return success;
4115978408cSSascha Wildner }
4125978408cSSascha Wildner
4135978408cSSascha Wildner #if 0
4145978408cSSascha Wildner static int
4155978408cSSascha Wildner cd9660_write_buffered(FILE *fd, off_t offset, int buff_len,
4165978408cSSascha Wildner const unsigned char* buffer)
4175978408cSSascha Wildner {
4185978408cSSascha Wildner static int working_sector = -1;
4195978408cSSascha Wildner static char buf[CD9660_SECTOR_SIZE];
4205978408cSSascha Wildner
4215978408cSSascha Wildner return 0;
4225978408cSSascha Wildner }
4235978408cSSascha Wildner #endif
4245978408cSSascha Wildner
4255978408cSSascha Wildner int
cd9660_copy_file(iso9660_disk * diskStructure,FILE * fd,off_t start_sector,const char * filename)4265978408cSSascha Wildner cd9660_copy_file(iso9660_disk *diskStructure, FILE *fd, off_t start_sector,
4275978408cSSascha Wildner const char *filename)
4285978408cSSascha Wildner {
4295978408cSSascha Wildner FILE *rf;
4305978408cSSascha Wildner int bytes_read;
4315978408cSSascha Wildner off_t sector = start_sector;
4325978408cSSascha Wildner int buf_size = diskStructure->sectorSize;
4335978408cSSascha Wildner char *buf;
4345978408cSSascha Wildner
4355978408cSSascha Wildner buf = emalloc(buf_size);
4365978408cSSascha Wildner if ((rf = fopen(filename, "rb")) == NULL) {
4375978408cSSascha Wildner warn("%s: cannot open %s", __func__, filename);
4385978408cSSascha Wildner free(buf);
4395978408cSSascha Wildner return 0;
4405978408cSSascha Wildner }
4415978408cSSascha Wildner
4425978408cSSascha Wildner if (diskStructure->verbose_level > 1)
4435978408cSSascha Wildner printf("Writing file: %s\n",filename);
4445978408cSSascha Wildner
4455978408cSSascha Wildner if (fseeko(fd, start_sector * diskStructure->sectorSize, SEEK_SET) == -1)
4465978408cSSascha Wildner err(1, "fseeko");
4475978408cSSascha Wildner
4485978408cSSascha Wildner while (!feof(rf)) {
4495978408cSSascha Wildner bytes_read = fread(buf,1,buf_size,rf);
4505978408cSSascha Wildner if (ferror(rf)) {
4515978408cSSascha Wildner warn("%s: fread", __func__);
4525978408cSSascha Wildner free(buf);
4535978408cSSascha Wildner (void)fclose(rf);
4545978408cSSascha Wildner return 0;
4555978408cSSascha Wildner }
4565978408cSSascha Wildner
4575978408cSSascha Wildner fwrite(buf,1,bytes_read,fd);
4585978408cSSascha Wildner if (ferror(fd)) {
4595978408cSSascha Wildner warn("%s: fwrite", __func__);
4605978408cSSascha Wildner free(buf);
4615978408cSSascha Wildner (void)fclose(rf);
4625978408cSSascha Wildner return 0;
4635978408cSSascha Wildner }
4645978408cSSascha Wildner sector++;
4655978408cSSascha Wildner }
4665978408cSSascha Wildner
4675978408cSSascha Wildner fclose(rf);
4685978408cSSascha Wildner free(buf);
4695978408cSSascha Wildner return 1;
4705978408cSSascha Wildner }
4715978408cSSascha Wildner
4725978408cSSascha Wildner static void
cd9660_write_rr(iso9660_disk * diskStructure,FILE * fd,cd9660node * writenode,off_t offset,off_t sector)4735978408cSSascha Wildner cd9660_write_rr(iso9660_disk *diskStructure, FILE *fd, cd9660node *writenode,
4745978408cSSascha Wildner off_t offset, off_t sector)
4755978408cSSascha Wildner {
4765978408cSSascha Wildner int in_ca = 0;
4775978408cSSascha Wildner struct ISO_SUSP_ATTRIBUTES *myattr;
4785978408cSSascha Wildner
4795978408cSSascha Wildner offset += writenode->isoDirRecord->length[0];
4805978408cSSascha Wildner if (fseeko(fd, sector * diskStructure->sectorSize + offset, SEEK_SET) ==
4815978408cSSascha Wildner -1)
4825978408cSSascha Wildner err(1, "fseeko");
4835978408cSSascha Wildner /* Offset now points at the end of the record */
4845978408cSSascha Wildner TAILQ_FOREACH(myattr, &writenode->head, rr_ll) {
4855978408cSSascha Wildner fwrite(&(myattr->attr), CD9660_SUSP_ENTRY_SIZE(myattr), 1, fd);
4865978408cSSascha Wildner
4875978408cSSascha Wildner if (!in_ca) {
4885978408cSSascha Wildner offset += CD9660_SUSP_ENTRY_SIZE(myattr);
4895978408cSSascha Wildner if (myattr->last_in_suf) {
4905978408cSSascha Wildner /*
4915978408cSSascha Wildner * Point the offset to the start of this
4925978408cSSascha Wildner * record's CE area
4935978408cSSascha Wildner */
4945978408cSSascha Wildner if (fseeko(fd, ((off_t)diskStructure->
4955978408cSSascha Wildner susp_continuation_area_start_sector *
4965978408cSSascha Wildner diskStructure->sectorSize)
4975978408cSSascha Wildner + writenode->susp_entry_ce_start,
4985978408cSSascha Wildner SEEK_SET) == -1)
4995978408cSSascha Wildner err(1, "fseeko");
5005978408cSSascha Wildner in_ca = 1;
5015978408cSSascha Wildner }
5025978408cSSascha Wildner }
5035978408cSSascha Wildner }
5045978408cSSascha Wildner
5055978408cSSascha Wildner /*
5065978408cSSascha Wildner * If we had to go to the continuation area, head back to
5075978408cSSascha Wildner * where we should be.
5085978408cSSascha Wildner */
5095978408cSSascha Wildner if (in_ca)
5105978408cSSascha Wildner if (fseeko(fd, sector * diskStructure->sectorSize + offset,
5115978408cSSascha Wildner SEEK_SET) == -1)
5125978408cSSascha Wildner err(1, "fseeko");
5135978408cSSascha Wildner }
514