Sync with the latest version from NetBSD. It notably addds ISO9660 support.
Submitted by: bapt
This commit is contained in:
parent
96a6480a53
commit
01a0f8531a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=214921
@ -1,22 +1,23 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= makefs
|
||||
|
||||
CFLAGS+=-I${.CURDIR}
|
||||
|
||||
SRCS= cd9660.c ffs.c \
|
||||
getid.c \
|
||||
makefs.c \
|
||||
walk.c
|
||||
MAN= makefs.8
|
||||
|
||||
WARNS?= 2
|
||||
|
||||
CFLAGS+=-I${.CURDIR}
|
||||
SRCS= ffs.c getid.c makefs.c walk.c
|
||||
.include "${.CURDIR}/cd9660/Makefile.inc"
|
||||
.include "${.CURDIR}/ffs/Makefile.inc"
|
||||
.include "${.CURDIR}/compat/Makefile.inc"
|
||||
|
||||
.PATH: ${.CURDIR}/ffs
|
||||
CFLAGS+=-I${.CURDIR}/ffs
|
||||
CFLAGS+=-DHAVE_STRUCT_STAT_ST_FLAGS=1
|
||||
CFLAGS+=-DHAVE_STRUCT_STAT_ST_GEN=1
|
||||
SRCS+= buf.c ffs_alloc.c ffs_balloc.c ffs_bswap.c ffs_subr.c mkfs.c ufs_bmap.c
|
||||
|
||||
.PATH: ${.CURDIR}/compat
|
||||
CFLAGS+=-I${.CURDIR}/compat
|
||||
SRCS+= pwcache.c strsuftoll.c
|
||||
|
||||
.PATH: ${.CURDIR}/../mtree
|
||||
CFLAGS+=-I${.CURDIR}/../mtree
|
||||
|
2154
usr.sbin/makefs/cd9660.c
Normal file
2154
usr.sbin/makefs/cd9660.c
Normal file
File diff suppressed because it is too large
Load Diff
364
usr.sbin/makefs/cd9660.h
Normal file
364
usr.sbin/makefs/cd9660.h
Normal file
@ -0,0 +1,364 @@
|
||||
/* $NetBSD: cd9660.h,v 1.15 2010/10/27 18:51:34 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
|
||||
* Perez-Rathke and Ram Vedam. All rights reserved.
|
||||
*
|
||||
* This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
|
||||
* Alan Perez-Rathke and Ram Vedam.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MAKEFS_CD9660_H
|
||||
#define _MAKEFS_CD9660_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <limits.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "makefs.h"
|
||||
#include "iso.h"
|
||||
#include "iso_rrip.h"
|
||||
#include "cd9660/cd9660_eltorito.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define INODE_WARNX(__x) warnx __x
|
||||
#else /* DEBUG */
|
||||
#define INODE_WARNX(__x)
|
||||
#endif /* DEBUG */
|
||||
|
||||
#define CD9660MAXPATH 4096
|
||||
|
||||
#define ISO_STRING_FILTER_NONE = 0x00
|
||||
#define ISO_STRING_FILTER_DCHARS = 0x01
|
||||
#define ISO_STRING_FILTER_ACHARS = 0x02
|
||||
|
||||
/*
|
||||
Extended preferences type, in the spirit of what makefs gives us (only ints)
|
||||
*/
|
||||
typedef struct {
|
||||
const char *shortName; /* Short option */
|
||||
const char *name; /* option name */
|
||||
char *value; /* where to stuff the value */
|
||||
int minLength; /* minimum for value */
|
||||
int maxLength; /* maximum for value */
|
||||
const char *desc; /* option description */
|
||||
int filterFlags;
|
||||
} string_option_t;
|
||||
|
||||
/******** STRUCTURES **********/
|
||||
|
||||
/*Defaults*/
|
||||
#define ISO_DEFAULT_VOLUMEID "MAKEFS_CD9660_IMAGE"
|
||||
#define ISO_DEFAULT_APPID "MAKEFS"
|
||||
#define ISO_DEFAULT_PUBLISHER "MAKEFS"
|
||||
#define ISO_DEFAULT_PREPARER "MAKEFS"
|
||||
|
||||
#define ISO_VOLUME_DESCRIPTOR_STANDARD_ID "CD001"
|
||||
#define ISO_VOLUME_DESCRIPTOR_BOOT 0
|
||||
#define ISO_VOLUME_DESCRIPTOR_PVD 1
|
||||
#define ISO_VOLUME_DESCRIPTOR_TERMINATOR 255
|
||||
|
||||
/*30 for name and extension, as well as version number and padding bit*/
|
||||
#define ISO_FILENAME_MAXLENGTH_BEFORE_VERSION 30
|
||||
#define ISO_FILENAME_MAXLENGTH 36
|
||||
#define ISO_FILENAME_MAXLENGTH_WITH_PADDING 37
|
||||
|
||||
#define ISO_FLAG_CLEAR 0x00
|
||||
#define ISO_FLAG_HIDDEN 0x01
|
||||
#define ISO_FLAG_DIRECTORY 0x02
|
||||
#define ISO_FLAG_ASSOCIATED 0x04
|
||||
#define ISO_FLAG_PERMISSIONS 0x08
|
||||
#define ISO_FLAG_RESERVED5 0x10
|
||||
#define ISO_FLAG_RESERVED6 0x20
|
||||
#define ISO_FLAG_FINAL_RECORD 0x40
|
||||
|
||||
#define ISO_PATHTABLE_ENTRY_BASESIZE 8
|
||||
|
||||
#define ISO_RRIP_DEFAULT_MOVE_DIR_NAME "RR_MOVED"
|
||||
#define RRIP_DEFAULT_MOVE_DIR_NAME ".rr_moved"
|
||||
|
||||
#define CD9660_BLOCKS(__sector_size, __bytes) \
|
||||
howmany((__bytes), (__sector_size))
|
||||
|
||||
#define CD9660_MEM_ALLOC_ERROR(_F) \
|
||||
err(EXIT_FAILURE, "%s, %s l. %d", _F, __FILE__, __LINE__)
|
||||
|
||||
#define CD9660_IS_COMMAND_ARG_DUAL(var,short,long)\
|
||||
(strcmp((var),(short)) == 0) || (strcmp((var),(long))==0)
|
||||
|
||||
#define CD9660_IS_COMMAND_ARG(var,arg)\
|
||||
(strcmp((var),(arg)) == 0)
|
||||
|
||||
#define CD9660_TYPE_FILE 0x01
|
||||
#define CD9660_TYPE_DIR 0x02
|
||||
#define CD9660_TYPE_DOT 0x04
|
||||
#define CD9660_TYPE_DOTDOT 0x08
|
||||
#define CD9660_TYPE_VIRTUAL 0x80
|
||||
|
||||
#define CD9660_INODE_HASH_SIZE 1024
|
||||
#define CD9660_SECTOR_SIZE 2048
|
||||
|
||||
#define CD9660_END_PADDING 150
|
||||
|
||||
/* Slight modification of the ISO structure in iso.h */
|
||||
typedef struct _iso_directory_record_cd9660 {
|
||||
u_char length [ISODCL (1, 1)]; /* 711 */
|
||||
u_char ext_attr_length [ISODCL (2, 2)]; /* 711 */
|
||||
u_char extent [ISODCL (3, 10)]; /* 733 */
|
||||
u_char size [ISODCL (11, 18)]; /* 733 */
|
||||
u_char date [ISODCL (19, 25)]; /* 7 by 711 */
|
||||
u_char flags [ISODCL (26, 26)];
|
||||
u_char file_unit_size [ISODCL (27, 27)]; /* 711 */
|
||||
u_char interleave [ISODCL (28, 28)]; /* 711 */
|
||||
u_char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
|
||||
u_char name_len [ISODCL (33, 33)]; /* 711 */
|
||||
char name [ISO_FILENAME_MAXLENGTH_WITH_PADDING];
|
||||
} iso_directory_record_cd9660;
|
||||
|
||||
/* TODO: Lots of optimization of this structure */
|
||||
typedef struct _cd9660node {
|
||||
u_char type;/* Used internally */
|
||||
/* Tree structure */
|
||||
struct _cd9660node *parent; /* parent (NULL if root) */
|
||||
TAILQ_HEAD(cd9660_children_head, _cd9660node) cn_children;
|
||||
TAILQ_ENTRY(_cd9660node) cn_next_child;
|
||||
|
||||
struct _cd9660node *dot_record; /* For directories, used mainly in RRIP */
|
||||
struct _cd9660node *dot_dot_record;
|
||||
|
||||
fsnode *node; /* pointer to fsnode */
|
||||
struct _iso_directory_record_cd9660 *isoDirRecord;
|
||||
struct iso_extended_attributes *isoExtAttributes;
|
||||
|
||||
/***** SIZE CALCULATION *****/
|
||||
/*already stored in isoDirRecord, but this is an int version, and will be
|
||||
copied to isoDirRecord on writing*/
|
||||
uint32_t fileDataSector;
|
||||
|
||||
/*
|
||||
* same thing, though some notes:
|
||||
* If a file, this is the file size
|
||||
* If a directory, this is the size of all its children's
|
||||
* directory records
|
||||
* plus necessary padding
|
||||
*/
|
||||
int64_t fileDataLength;
|
||||
|
||||
int64_t fileSectorsUsed;
|
||||
int fileRecordSize;/*copy of a variable, int for quicker calculations*/
|
||||
|
||||
/* Old name, used for renaming - needs to be optimized but low priority */
|
||||
char o_name [ISO_FILENAME_MAXLENGTH_WITH_PADDING];
|
||||
|
||||
/***** SPACE RESERVED FOR EXTENSIONS *****/
|
||||
/* For memory efficiency's sake - we should move this to a separate struct
|
||||
and point to null if not needed */
|
||||
/* For Rock Ridge */
|
||||
struct _cd9660node *rr_real_parent, *rr_relocated;
|
||||
|
||||
int64_t susp_entry_size;
|
||||
int64_t susp_dot_entry_size;
|
||||
int64_t susp_dot_dot_entry_size;
|
||||
|
||||
/* Continuation area stuff */
|
||||
int64_t susp_entry_ce_start;
|
||||
int64_t susp_dot_ce_start;
|
||||
int64_t susp_dot_dot_ce_start;
|
||||
|
||||
int64_t susp_entry_ce_length;
|
||||
int64_t susp_dot_ce_length;
|
||||
int64_t susp_dot_dot_ce_length;
|
||||
|
||||
/* Data to put at the end of the System Use field */
|
||||
int64_t su_tail_size;
|
||||
char *su_tail_data;
|
||||
|
||||
/*** PATH TABLE STUFF ***/
|
||||
int level; /*depth*/
|
||||
int ptnumber;
|
||||
struct _cd9660node *ptnext, *ptprev, *ptlast;
|
||||
|
||||
/* SUSP entries */
|
||||
TAILQ_HEAD(susp_linked_list, ISO_SUSP_ATTRIBUTES) head;
|
||||
} cd9660node;
|
||||
|
||||
typedef struct _path_table_entry
|
||||
{
|
||||
u_char length[ISODCL (1, 1)];
|
||||
u_char extended_attribute_length[ISODCL (2, 2)];
|
||||
u_char first_sector[ISODCL (3, 6)];
|
||||
u_char parent_number[ISODCL (7, 8)];
|
||||
u_char name[ISO_FILENAME_MAXLENGTH_WITH_PADDING];
|
||||
} path_table_entry;
|
||||
|
||||
typedef struct _volume_descriptor
|
||||
{
|
||||
u_char *volumeDescriptorData; /*ALWAYS 2048 bytes long*/
|
||||
int64_t sector;
|
||||
struct _volume_descriptor *next;
|
||||
} volume_descriptor;
|
||||
|
||||
typedef struct _iso9660_disk {
|
||||
int sectorSize;
|
||||
struct iso_primary_descriptor primaryDescriptor;
|
||||
struct iso_supplementary_descriptor supplementaryDescriptor;
|
||||
|
||||
volume_descriptor *firstVolumeDescriptor;
|
||||
|
||||
cd9660node *rootNode;
|
||||
|
||||
const char *rootFilesystemPath;
|
||||
|
||||
/* Important sector numbers here */
|
||||
/* primaryDescriptor.type_l_path_table*/
|
||||
int64_t primaryBigEndianTableSector;
|
||||
|
||||
/* primaryDescriptor.type_m_path_table*/
|
||||
int64_t primaryLittleEndianTableSector;
|
||||
|
||||
/* primaryDescriptor.opt_type_l_path_table*/
|
||||
int64_t secondaryBigEndianTableSector;
|
||||
|
||||
/* primaryDescriptor.opt_type_m_path_table*/
|
||||
int64_t secondaryLittleEndianTableSector;
|
||||
|
||||
/* primaryDescriptor.path_table_size*/
|
||||
int pathTableLength;
|
||||
int64_t dataFirstSector;
|
||||
|
||||
int64_t totalSectors;
|
||||
/* OPTIONS GO HERE */
|
||||
int isoLevel;
|
||||
|
||||
int include_padding_areas;
|
||||
|
||||
int follow_sym_links;
|
||||
int verbose_level;
|
||||
int displayHelp;
|
||||
int keep_bad_images;
|
||||
|
||||
/* SUSP options and variables */
|
||||
int64_t susp_continuation_area_start_sector;
|
||||
int64_t susp_continuation_area_size;
|
||||
int64_t susp_continuation_area_current_free;
|
||||
|
||||
int rock_ridge_enabled;
|
||||
/* Other Rock Ridge Variables */
|
||||
char *rock_ridge_renamed_dir_name;
|
||||
int rock_ridge_move_count;
|
||||
cd9660node *rr_moved_dir;
|
||||
|
||||
int archimedes_enabled;
|
||||
|
||||
/* Spec breaking options */
|
||||
u_char allow_deep_trees;
|
||||
u_char allow_start_dot;
|
||||
u_char allow_max_name; /* Allow 37 char filenames*/
|
||||
u_char allow_illegal_chars; /* ~, !, # */
|
||||
u_char allow_lowercase;
|
||||
u_char allow_multidot;
|
||||
u_char omit_trailing_period;
|
||||
|
||||
/* BOOT INFORMATION HERE */
|
||||
int has_generic_bootimage; /* Default to 0 */
|
||||
char *generic_bootimage;
|
||||
|
||||
int is_bootable;/* Default to 0 */
|
||||
int64_t boot_catalog_sector;
|
||||
boot_volume_descriptor *boot_descriptor;
|
||||
char * boot_image_directory;
|
||||
|
||||
TAILQ_HEAD(boot_image_list,cd9660_boot_image) boot_images;
|
||||
int image_serialno;
|
||||
LIST_HEAD(boot_catalog_entries,boot_catalog_entry) boot_entries;
|
||||
|
||||
} iso9660_disk;
|
||||
|
||||
/******** GLOBAL VARIABLES ***********/
|
||||
extern iso9660_disk diskStructure;
|
||||
|
||||
/************ FUNCTIONS **************/
|
||||
int cd9660_valid_a_chars(const char *);
|
||||
int cd9660_valid_d_chars(const char *);
|
||||
void cd9660_uppercase_characters(char *, int);
|
||||
|
||||
/* ISO Data Types */
|
||||
void cd9660_721(uint16_t, unsigned char *);
|
||||
void cd9660_731(uint32_t, unsigned char *);
|
||||
void cd9660_722(uint16_t, unsigned char *);
|
||||
void cd9660_732(uint32_t, unsigned char *);
|
||||
void cd9660_bothendian_dword(uint32_t dw, unsigned char *);
|
||||
void cd9660_bothendian_word(uint16_t dw, unsigned char *);
|
||||
void cd9660_set_date(char *, time_t);
|
||||
void cd9660_time_8426(unsigned char *, time_t);
|
||||
void cd9660_time_915(unsigned char *, time_t);
|
||||
|
||||
/*** Boot Functions ***/
|
||||
int cd9660_write_generic_bootimage(FILE *);
|
||||
int cd9660_add_generic_bootimage(const char *);
|
||||
int cd9660_write_boot(FILE *);
|
||||
int cd9660_add_boot_disk(const char *);
|
||||
int cd9660_eltorito_add_boot_option(const char *, const char *);
|
||||
int cd9660_setup_boot(int);
|
||||
int cd9660_setup_boot_volume_descriptor(volume_descriptor *);
|
||||
|
||||
|
||||
/*** Write Functions ***/
|
||||
int cd9660_write_image(const char *image);
|
||||
int cd9660_copy_file(FILE *, off_t, const char *);
|
||||
|
||||
void cd9660_compute_full_filename(cd9660node *, char *, int);
|
||||
int cd9660_compute_record_size(cd9660node *);
|
||||
|
||||
/* Debugging functions */
|
||||
void debug_print_tree(cd9660node *,int);
|
||||
void debug_print_path_tree(cd9660node *);
|
||||
void debug_print_volume_descriptor_information(void);
|
||||
void debug_dump_to_xml_ptentry(path_table_entry *,int, int);
|
||||
void debug_dump_to_xml_path_table(FILE *, off_t, int, int);
|
||||
void debug_dump_to_xml(FILE *);
|
||||
int debug_get_encoded_number(unsigned char *, int);
|
||||
void debug_dump_integer(const char *, char *,int);
|
||||
void debug_dump_string(const char *,unsigned char *,int);
|
||||
void debug_dump_directory_record_9_1(unsigned char *);
|
||||
void debug_dump_to_xml_volume_descriptor(unsigned char *,int);
|
||||
|
||||
void cd9660_pad_string_spaces(char *, int);
|
||||
|
||||
#endif
|
9
usr.sbin/makefs/cd9660/Makefile.inc
Normal file
9
usr.sbin/makefs/cd9660/Makefile.inc
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
.PATH: ${.CURDIR}/cd9660 ${.CURDIR}/../../sys/fs/cd9660/
|
||||
|
||||
CFLAGS+=-I${.CURDIR}/../../sys/fs/cd9660/
|
||||
|
||||
SRCS+= cd9660_strings.c cd9660_debug.c cd9660_eltorito.c \
|
||||
cd9660_write.c cd9660_conversion.c iso9660_rrip.c cd9660_archimedes.c
|
126
usr.sbin/makefs/cd9660/cd9660_archimedes.c
Normal file
126
usr.sbin/makefs/cd9660/cd9660_archimedes.c
Normal file
@ -0,0 +1,126 @@
|
||||
/* $NetBSD: cd9660_archimedes.c,v 1.1 2009/01/10 22:06:29 bjh21 Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2009 Ben Harris
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* cd9660_archimedes.c - support for RISC OS "ARCHIMEDES" extension
|
||||
*
|
||||
* RISC OS CDFS looks for a special block at the end of the System Use
|
||||
* Field for each file. If present, this contains the RISC OS load
|
||||
* and exec address (used to hold the file timestamp and type), the
|
||||
* file attributes, and a flag indicating whether the first character
|
||||
* of the filename should be replaced with '!' (since many special
|
||||
* RISC OS filenames do).
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "makefs.h"
|
||||
#include "cd9660.h"
|
||||
#include "cd9660_archimedes.h"
|
||||
|
||||
/*
|
||||
* Convert a Unix time_t (non-leap seconds since 1970-01-01) to a RISC
|
||||
* OS time (non-leap(?) centiseconds since 1900-01-01(?)).
|
||||
*/
|
||||
|
||||
static u_int64_t
|
||||
riscos_date(time_t unixtime)
|
||||
{
|
||||
u_int64_t base;
|
||||
|
||||
base = 31536000ULL * 70 + 86400 * 17;
|
||||
return (((u_int64_t)unixtime) + base)*100;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add "ARCHIMEDES" metadata to a node if that seems appropriate.
|
||||
*
|
||||
* We touch regular files with names matching /,[0-9a-f]{3}$/ and
|
||||
* directories matching /^!/.
|
||||
*/
|
||||
static void
|
||||
archimedes_convert_node(cd9660node *node)
|
||||
{
|
||||
struct ISO_ARCHIMEDES *arc;
|
||||
size_t len;
|
||||
int type = -1;
|
||||
uint64_t stamp;
|
||||
|
||||
if (node->su_tail_data != NULL)
|
||||
/* Something else already has the tail. */
|
||||
return;
|
||||
|
||||
len = strlen(node->node->name);
|
||||
if (len < 1) return;
|
||||
|
||||
if (len >= 4 && node->node->name[len-4] == ',')
|
||||
/* XXX should support ,xxx and ,lxa */
|
||||
type = strtoul(node->node->name + len - 3, NULL, 16);
|
||||
if (type == -1 && node->node->name[0] != '!')
|
||||
return;
|
||||
if (type == -1) type = 0;
|
||||
|
||||
assert(sizeof(struct ISO_ARCHIMEDES) == 32);
|
||||
if ((arc = calloc(1, sizeof(struct ISO_ARCHIMEDES))) == NULL) {
|
||||
CD9660_MEM_ALLOC_ERROR("archimedes_convert_node");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
stamp = riscos_date(node->node->inode->st.st_mtime);
|
||||
|
||||
memcpy(arc->magic, "ARCHIMEDES", 10);
|
||||
cd9660_731(0xfff00000 | (type << 8) | (stamp >> 32), arc->loadaddr);
|
||||
cd9660_731(stamp & 0x00ffffffffULL, arc->execaddr);
|
||||
arc->ro_attr = RO_ACCESS_UR | RO_ACCESS_OR;
|
||||
arc->cdfs_attr = node->node->name[0] == '!' ? CDFS_PLING : 0;
|
||||
node->su_tail_data = (void *)arc;
|
||||
node->su_tail_size = sizeof(*arc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add "ARCHIMEDES" metadata to an entire tree recursively.
|
||||
*/
|
||||
void
|
||||
archimedes_convert_tree(cd9660node *node)
|
||||
{
|
||||
cd9660node *cn;
|
||||
|
||||
assert(node != NULL);
|
||||
|
||||
archimedes_convert_node(node);
|
||||
|
||||
/* Recurse on children. */
|
||||
TAILQ_FOREACH(cn, &node->cn_children, cn_next_child)
|
||||
archimedes_convert_tree(cn);
|
||||
}
|
50
usr.sbin/makefs/cd9660/cd9660_archimedes.h
Normal file
50
usr.sbin/makefs/cd9660/cd9660_archimedes.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* $NetBSD: cd9660_archimedes.h,v 1.1 2009/01/10 22:06:29 bjh21 Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2009 Ben Harris
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* cd9660_archimedes.c - support for RISC OS "ARCHIMEDES" extension
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
struct ISO_ARCHIMEDES {
|
||||
char magic[10]; /* "ARCHIMEDES" */
|
||||
unsigned char loadaddr[4]; /* Load address, little-endian */
|
||||
unsigned char execaddr[4]; /* Exec address, little-endian */
|
||||
unsigned char ro_attr; /* RISC OS attributes */
|
||||
#define RO_ACCESS_UR 0x01 /* Owner read */
|
||||
#define RO_ACCESS_UW 0x02 /* Owner write */
|
||||
#define RO_ACCESS_L 0x04 /* Locked */
|
||||
#define RO_ACCESS_OR 0x10 /* Public read */
|
||||
#define RO_ACCESS_OW 0x20 /* Public write */
|
||||
unsigned char cdfs_attr; /* Extra attributes for CDFS */
|
||||
#define CDFS_PLING 0x01 /* Filename begins with '!' */
|
||||
char reserved[12];
|
||||
};
|
||||
|
||||
extern void archimedes_convert_tree(cd9660node *);
|
202
usr.sbin/makefs/cd9660/cd9660_conversion.c
Normal file
202
usr.sbin/makefs/cd9660/cd9660_conversion.c
Normal file
@ -0,0 +1,202 @@
|
||||
/* $NetBSD: cd9660_conversion.c,v 1.4 2007/03/14 14:11:17 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
|
||||
* Perez-Rathke and Ram Vedam. All rights reserved.
|
||||
*
|
||||
* This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
|
||||
* Alan Perez-Rathke and Ram Vedam.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "cd9660.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/endian.h>
|
||||
|
||||
static char cd9660_compute_gm_offset(time_t);
|
||||
|
||||
#if 0
|
||||
static inline int
|
||||
cd9660_pad_even(length)
|
||||
int length;
|
||||
{
|
||||
return length + (length & 0x01);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These can probably be implemented using a macro
|
||||
*/
|
||||
|
||||
/* Little endian */
|
||||
void
|
||||
cd9660_721(uint16_t w, unsigned char *twochar)
|
||||
{
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
w = bswap16(w);
|
||||
#endif
|
||||
memcpy(twochar,&w,2);
|
||||
}
|
||||
|
||||
void
|
||||
cd9660_731(uint32_t w, unsigned char *fourchar)
|
||||
{
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
w = bswap32(w);
|
||||
#endif
|
||||
memcpy(fourchar,&w,4);
|
||||
}
|
||||
|
||||
/* Big endian */
|
||||
void
|
||||
cd9660_722(uint16_t w, unsigned char *twochar)
|
||||
{
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
w = bswap16(w);
|
||||
#endif
|
||||
memcpy(twochar,&w,2);
|
||||
}
|
||||
|
||||
void
|
||||
cd9660_732(uint32_t w, unsigned char *fourchar)
|
||||
{
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
w = bswap32(w);
|
||||
#endif
|
||||
memcpy(fourchar,&w,4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a dword into a double endian string of eight characters
|
||||
* @param int The double word to convert
|
||||
* @param char* The string to write the both endian double word to - It is assumed this is allocated and at least
|
||||
* eight characters long
|
||||
*/
|
||||
void
|
||||
cd9660_bothendian_dword(uint32_t dw, unsigned char *eightchar)
|
||||
{
|
||||
uint32_t le, be;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
le = dw;
|
||||
be = bswap32(dw);
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
be = dw;
|
||||
le = bswap32(dw);
|
||||
#endif
|
||||
memcpy(eightchar, &le, 4);
|
||||
memcpy((eightchar+4), &be, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a word into a double endian string of four characters
|
||||
* @param int The word to convert
|
||||
* @param char* The string to write the both endian word to - It is assumed this is allocated and at least
|
||||
* four characters long
|
||||
*/
|
||||
void
|
||||
cd9660_bothendian_word(uint16_t dw, unsigned char *fourchar)
|
||||
{
|
||||
uint16_t le, be;
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
le = dw;
|
||||
be = bswap16(dw);
|
||||
#endif
|
||||
#if BYTE_ORDER == BIG_ENDIAN
|
||||
be = dw;
|
||||
le = bswap16(dw);
|
||||
#endif
|
||||
memcpy(fourchar, &le, 2);
|
||||
memcpy((fourchar+2), &be, 2);
|
||||
}
|
||||
|
||||
void
|
||||
cd9660_pad_string_spaces(char *str, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i ++) {
|
||||
if (str[i] == '\0')
|
||||
str[i] = 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
static char
|
||||
cd9660_compute_gm_offset(time_t tim)
|
||||
{
|
||||
struct tm t, gm;
|
||||
|
||||
(void)localtime_r(&tim, &t);
|
||||
(void)gmtime_r(&tim, &gm);
|
||||
gm.tm_year -= t.tm_year;
|
||||
gm.tm_yday -= t.tm_yday;
|
||||
gm.tm_hour -= t.tm_hour;
|
||||
gm.tm_min -= t.tm_min;
|
||||
if (gm.tm_year < 0)
|
||||
gm.tm_yday = -1;
|
||||
else if (gm.tm_year > 0)
|
||||
gm.tm_yday = 1;
|
||||
|
||||
return (char)(-(gm.tm_min + 60* (24 * gm.tm_yday + gm.tm_hour)) / 15);
|
||||
}
|
||||
|
||||
/* Long dates: 17 characters */
|
||||
void
|
||||
cd9660_time_8426(unsigned char *buf, time_t tim)
|
||||
{
|
||||
struct tm t;
|
||||
char temp[18];
|
||||
|
||||
(void)localtime_r(&tim, &t);
|
||||
(void)snprintf(temp, sizeof(temp), "%04i%02i%02i%02i%02i%02i%02i",
|
||||
1900+(int)t.tm_year,
|
||||
(int)t.tm_mon+1,
|
||||
(int)t.tm_mday,
|
||||
(int)t.tm_hour,
|
||||
(int)t.tm_min,
|
||||
(int)t.tm_sec,
|
||||
0);
|
||||
(void)memcpy(buf, temp, 16);
|
||||
buf[16] = cd9660_compute_gm_offset(tim);
|
||||
}
|
||||
|
||||
/* Short dates: 7 characters */
|
||||
void
|
||||
cd9660_time_915(unsigned char *buf, time_t tim)
|
||||
{
|
||||
struct tm t;
|
||||
|
||||
(void)localtime_r(&tim, &t);
|
||||
buf[0] = t.tm_year;
|
||||
buf[1] = t.tm_mon+1;
|
||||
buf[2] = t.tm_mday;
|
||||
buf[3] = t.tm_hour;
|
||||
buf[4] = t.tm_min;
|
||||
buf[5] = t.tm_sec;
|
||||
buf[6] = cd9660_compute_gm_offset(tim);
|
||||
}
|
488
usr.sbin/makefs/cd9660/cd9660_debug.c
Normal file
488
usr.sbin/makefs/cd9660/cd9660_debug.c
Normal file
@ -0,0 +1,488 @@
|
||||
/* $NetBSD: cd9660_debug.c,v 1.11 2010/10/27 18:51:35 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
|
||||
* Perez-Rathke and Ram Vedam. All rights reserved.
|
||||
*
|
||||
* This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
|
||||
* Alan Perez-Rathke and Ram Vedam.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include "makefs.h"
|
||||
#include "cd9660.h"
|
||||
#include "iso9660_rrip.h"
|
||||
|
||||
static void debug_print_susp_attrs(cd9660node *, int);
|
||||
static void debug_dump_to_xml_padded_hex_output(const char *, unsigned char *,
|
||||
int);
|
||||
|
||||
static inline void
|
||||
print_n_tabs(int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i <= n; i ++)
|
||||
printf("\t");
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
debug_print_rrip_info(n)
|
||||
cd9660node *n;
|
||||
{
|
||||
struct ISO_SUSP_ATTRIBUTES *t;
|
||||
TAILQ_FOREACH(t, &node->head, rr_ll) {
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
debug_print_susp_attrs(cd9660node *n, int indent)
|
||||
{
|
||||
struct ISO_SUSP_ATTRIBUTES *t;
|
||||
|
||||
TAILQ_FOREACH(t, &n->head, rr_ll) {
|
||||
print_n_tabs(indent);
|
||||
printf("-");
|
||||
printf("%c%c: L:%i",t->attr.su_entry.SP.h.type[0],
|
||||
t->attr.su_entry.SP.h.type[1],
|
||||
(int)t->attr.su_entry.SP.h.length[0]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
debug_print_tree(cd9660node *node, int level)
|
||||
{
|
||||
#if !HAVE_NBTOOL_CONFIG_H
|
||||
cd9660node *cn;
|
||||
|
||||
print_n_tabs(level);
|
||||
if (node->type & CD9660_TYPE_DOT) {
|
||||
printf(". (%i)\n",
|
||||
isonum_733(node->isoDirRecord->extent));
|
||||
} else if (node->type & CD9660_TYPE_DOTDOT) {
|
||||
printf("..(%i)\n",
|
||||
isonum_733(node->isoDirRecord->extent));
|
||||
} else if (node->isoDirRecord->name[0]=='\0') {
|
||||
printf("(ROOT) (%" PRIu32 " to %" PRId64 ")\n",
|
||||
node->fileDataSector,
|
||||
node->fileDataSector +
|
||||
node->fileSectorsUsed - 1);
|
||||
} else {
|
||||
printf("%s (%s) (%" PRIu32 " to %" PRId64 ")\n",
|
||||
node->isoDirRecord->name,
|
||||
(node->isoDirRecord->flags[0]
|
||||
& ISO_FLAG_DIRECTORY) ? "DIR" : "FILE",
|
||||
node->fileDataSector,
|
||||
(node->fileSectorsUsed == 0) ?
|
||||
node->fileDataSector :
|
||||
node->fileDataSector
|
||||
+ node->fileSectorsUsed - 1);
|
||||
}
|
||||
if (diskStructure.rock_ridge_enabled)
|
||||
debug_print_susp_attrs(node, level + 1);
|
||||
TAILQ_FOREACH(cn, &node->cn_children, cn_next_child)
|
||||
debug_print_tree(cn, level + 1);
|
||||
#else
|
||||
printf("Sorry, debugging is not supported in host-tools mode.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
debug_print_path_tree(cd9660node *n)
|
||||
{
|
||||
cd9660node *iterator = n;
|
||||
|
||||
/* Only display this message when called with the root node */
|
||||
if (n->parent == NULL)
|
||||
printf("debug_print_path_table: Dumping path table contents\n");
|
||||
|
||||
while (iterator != NULL) {
|
||||
if (iterator->isoDirRecord->name[0] == '\0')
|
||||
printf("0) (ROOT)\n");
|
||||
else
|
||||
printf("%i) %s\n", iterator->level,
|
||||
iterator->isoDirRecord->name);
|
||||
|
||||
iterator = iterator->ptnext;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
debug_print_volume_descriptor_information(void)
|
||||
{
|
||||
volume_descriptor *tmp = diskStructure.firstVolumeDescriptor;
|
||||
char temp[CD9660_SECTOR_SIZE];
|
||||
|
||||
printf("==Listing Volume Descriptors==\n");
|
||||
|
||||
while (tmp != NULL) {
|
||||
memset(temp, 0, CD9660_SECTOR_SIZE);
|
||||
memcpy(temp, tmp->volumeDescriptorData + 1, 5);
|
||||
printf("Volume descriptor in sector %" PRId64
|
||||
": type %i, ID %s\n",
|
||||
tmp->sector, tmp->volumeDescriptorData[0], temp);
|
||||
switch(tmp->volumeDescriptorData[0]) {
|
||||
case 0:/*boot record*/
|
||||
break;
|
||||
|
||||
case 1: /* PVD */
|
||||
break;
|
||||
|
||||
case 2: /* SVD */
|
||||
break;
|
||||
|
||||
case 3: /* Volume Partition Descriptor */
|
||||
break;
|
||||
|
||||
case 255: /* terminator */
|
||||
break;
|
||||
}
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
printf("==Done Listing Volume Descriptors==\n");
|
||||
}
|
||||
|
||||
void
|
||||
debug_dump_to_xml_ptentry(path_table_entry *pttemp, int num, int mode)
|
||||
{
|
||||
printf("<ptentry num=\"%i\">\n" ,num);
|
||||
printf("<length>%i</length>\n", pttemp->length[0]);
|
||||
printf("<extended_attribute_length>%i</extended_attribute_length>\n",
|
||||
pttemp->extended_attribute_length[0]);
|
||||
printf("<parent_number>%i</parent_number>\n",
|
||||
debug_get_encoded_number(pttemp->parent_number,mode));
|
||||
debug_dump_to_xml_padded_hex_output("name",
|
||||
pttemp->name, pttemp->length[0]);
|
||||
printf("</ptentry>\n");
|
||||
}
|
||||
|
||||
void
|
||||
debug_dump_to_xml_path_table(FILE *fd, off_t sector, int size, int mode)
|
||||
{
|
||||
path_table_entry pttemp;
|
||||
int t = 0;
|
||||
int n = 0;
|
||||
|
||||
if (fseeko(fd, CD9660_SECTOR_SIZE * sector, SEEK_SET) == -1)
|
||||
err(1, "fseeko");
|
||||
|
||||
while (t < size) {
|
||||
/* Read fixed data first */
|
||||
fread(&pttemp, 1, 8, fd);
|
||||
t += 8;
|
||||
/* Read variable */
|
||||
fread(((unsigned char*)&pttemp) + 8, 1, pttemp.length[0], fd);
|
||||
t += pttemp.length[0];
|
||||
debug_dump_to_xml_ptentry(&pttemp, n, mode);
|
||||
n++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* XML Debug output functions
|
||||
* Dump hierarchy of CD, as well as volume info, to XML
|
||||
* Can be used later to diff against a standard,
|
||||
* or just provide easy to read detailed debug output
|
||||
*/
|
||||
void
|
||||
debug_dump_to_xml(FILE *fd)
|
||||
{
|
||||
unsigned char buf[CD9660_SECTOR_SIZE];
|
||||
off_t sector;
|
||||
int t, t2;
|
||||
struct iso_primary_descriptor primaryVD;
|
||||
struct _boot_volume_descriptor bootVD;
|
||||
|
||||
printf("<cd9660dump>\n");
|
||||
|
||||
/* Display Volume Descriptors */
|
||||
sector = 16;
|
||||
do {
|
||||
if (fseeko(fd, CD9660_SECTOR_SIZE * sector, SEEK_SET) == -1)
|
||||
err(1, "fseeko");
|
||||
fread(buf, 1, CD9660_SECTOR_SIZE, fd);
|
||||
t = (int)((unsigned char)buf[0]);
|
||||
switch (t) {
|
||||
case 0:
|
||||
memcpy(&bootVD, buf, CD9660_SECTOR_SIZE);
|
||||
break;
|
||||
case 1:
|
||||
memcpy(&primaryVD, buf, CD9660_SECTOR_SIZE);
|
||||
break;
|
||||
}
|
||||
debug_dump_to_xml_volume_descriptor(buf, sector);
|
||||
sector++;
|
||||
} while (t != 255);
|
||||
|
||||
t = debug_get_encoded_number((u_char *)primaryVD.type_l_path_table,
|
||||
731);
|
||||
t2 = debug_get_encoded_number((u_char *)primaryVD.path_table_size, 733);
|
||||
printf("Path table 1 located at sector %i and is %i bytes long\n",
|
||||
t,t2);
|
||||
debug_dump_to_xml_path_table(fd, t, t2, 721);
|
||||
|
||||
t = debug_get_encoded_number((u_char *)primaryVD.type_m_path_table,
|
||||
731);
|
||||
debug_dump_to_xml_path_table(fd, t, t2, 722);
|
||||
|
||||
printf("</cd9660dump>\n");
|
||||
}
|
||||
|
||||
static void
|
||||
debug_dump_to_xml_padded_hex_output(const char *element, unsigned char *buf,
|
||||
int len)
|
||||
{
|
||||
int i;
|
||||
int t;
|
||||
|
||||
printf("<%s>",element);
|
||||
for (i = 0; i < len; i++) {
|
||||
t = (unsigned char)buf[i];
|
||||
if (t >= 32 && t < 127)
|
||||
printf("%c",t);
|
||||
}
|
||||
printf("</%s>\n",element);
|
||||
|
||||
printf("<%s:hex>",element);
|
||||
for (i = 0; i < len; i++) {
|
||||
t = (unsigned char)buf[i];
|
||||
printf(" %x",t);
|
||||
}
|
||||
printf("</%s:hex>\n",element);
|
||||
}
|
||||
|
||||
int
|
||||
debug_get_encoded_number(unsigned char* buf, int mode)
|
||||
{
|
||||
#if !HAVE_NBTOOL_CONFIG_H
|
||||
switch (mode) {
|
||||
/* 711: Single bite */
|
||||
case 711:
|
||||
return isonum_711(buf);
|
||||
|
||||
/* 712: Single signed byte */
|
||||
case 712:
|
||||
return isonum_712((signed char *)buf);
|
||||
|
||||
/* 721: 16 bit LE */
|
||||
case 721:
|
||||
return isonum_721(buf);
|
||||
|
||||
/* 731: 32 bit LE */
|
||||
case 731:
|
||||
return isonum_731(buf);
|
||||
|
||||
/* 722: 16 bit BE */
|
||||
case 722:
|
||||
return isonum_722(buf);
|
||||
|
||||
/* 732: 32 bit BE */
|
||||
case 732:
|
||||
return isonum_732(buf);
|
||||
|
||||
/* 723: 16 bit bothE */
|
||||
case 723:
|
||||
return isonum_723(buf);
|
||||
|
||||
/* 733: 32 bit bothE */
|
||||
case 733:
|
||||
return isonum_733(buf);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
debug_dump_integer(const char *element, char* buf, int mode)
|
||||
{
|
||||
printf("<%s>%i</%s>\n", element,
|
||||
debug_get_encoded_number((unsigned char *)buf, mode), element);
|
||||
}
|
||||
|
||||
void
|
||||
debug_dump_string(const char *element __unused, unsigned char *buf __unused, int len __unused)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
debug_dump_directory_record_9_1(unsigned char* buf)
|
||||
{
|
||||
printf("<directoryrecord>\n");
|
||||
debug_dump_integer("length",
|
||||
((struct iso_directory_record*) buf)->length, 711);
|
||||
debug_dump_integer("ext_attr_length",
|
||||
((struct iso_directory_record*) buf)->ext_attr_length,711);
|
||||
debug_dump_integer("extent",
|
||||
(char *)((struct iso_directory_record*) buf)->extent, 733);
|
||||
debug_dump_integer("size",
|
||||
(char *)((struct iso_directory_record*) buf)->size, 733);
|
||||
debug_dump_integer("flags",
|
||||
((struct iso_directory_record*) buf)->flags, 711);
|
||||
debug_dump_integer("file_unit_size",
|
||||
((struct iso_directory_record*) buf)->file_unit_size,711);
|
||||
debug_dump_integer("interleave",
|
||||
((struct iso_directory_record*) buf)->interleave, 711);
|
||||
debug_dump_integer("volume_sequence_number",
|
||||
((struct iso_directory_record*) buf)->volume_sequence_number,
|
||||
723);
|
||||
debug_dump_integer("name_len",
|
||||
((struct iso_directory_record*) buf)->name_len, 711);
|
||||
debug_dump_to_xml_padded_hex_output("name",
|
||||
(u_char *)((struct iso_directory_record*) buf)->name,
|
||||
debug_get_encoded_number((u_char *)
|
||||
((struct iso_directory_record*) buf)->length, 711));
|
||||
printf("</directoryrecord>\n");
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
debug_dump_to_xml_volume_descriptor(unsigned char* buf, int sector)
|
||||
{
|
||||
printf("<volumedescriptor sector=\"%i\">\n", sector);
|
||||
printf("<vdtype>");
|
||||
switch(buf[0]) {
|
||||
case 0:
|
||||
printf("boot");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
printf("primary");
|
||||
break;
|
||||
|
||||
case 2:
|
||||
printf("supplementary");
|
||||
break;
|
||||
|
||||
case 3:
|
||||
printf("volume partition descriptor");
|
||||
break;
|
||||
|
||||
case 255:
|
||||
printf("terminator");
|
||||
break;
|
||||
}
|
||||
|
||||
printf("</vdtype>\n");
|
||||
switch(buf[0]) {
|
||||
case 1:
|
||||
debug_dump_integer("type",
|
||||
((struct iso_primary_descriptor*)buf)->type, 711);
|
||||
debug_dump_to_xml_padded_hex_output("id",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->id,
|
||||
ISODCL ( 2, 6));
|
||||
debug_dump_integer("version",
|
||||
((struct iso_primary_descriptor*)buf)->version,
|
||||
711);
|
||||
debug_dump_to_xml_padded_hex_output("system_id",
|
||||
(u_char *)((struct iso_primary_descriptor*)buf)->system_id,
|
||||
ISODCL(9,40));
|
||||
debug_dump_to_xml_padded_hex_output("volume_id",
|
||||
(u_char *)((struct iso_primary_descriptor*)buf)->volume_id,
|
||||
ISODCL(41,72));
|
||||
debug_dump_integer("volume_space_size",
|
||||
((struct iso_primary_descriptor*)buf)->volume_space_size,
|
||||
733);
|
||||
debug_dump_integer("volume_set_size",
|
||||
((struct iso_primary_descriptor*)buf)->volume_set_size,
|
||||
733);
|
||||
debug_dump_integer("volume_sequence_number",
|
||||
((struct iso_primary_descriptor*)buf)->volume_sequence_number,
|
||||
723);
|
||||
debug_dump_integer("logical_block_size",
|
||||
((struct iso_primary_descriptor*)buf)->logical_block_size,
|
||||
723);
|
||||
debug_dump_integer("path_table_size",
|
||||
((struct iso_primary_descriptor*)buf)->path_table_size,
|
||||
733);
|
||||
debug_dump_integer("type_l_path_table",
|
||||
((struct iso_primary_descriptor*)buf)->type_l_path_table,
|
||||
731);
|
||||
debug_dump_integer("opt_type_l_path_table",
|
||||
((struct iso_primary_descriptor*)buf)->opt_type_l_path_table,
|
||||
731);
|
||||
debug_dump_integer("type_m_path_table",
|
||||
((struct iso_primary_descriptor*)buf)->type_m_path_table,
|
||||
732);
|
||||
debug_dump_integer("opt_type_m_path_table",
|
||||
((struct iso_primary_descriptor*)buf)->opt_type_m_path_table,732);
|
||||
debug_dump_directory_record_9_1(
|
||||
(u_char *)((struct iso_primary_descriptor*)buf)->root_directory_record);
|
||||
debug_dump_to_xml_padded_hex_output("volume_set_id",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->volume_set_id,
|
||||
ISODCL (191, 318));
|
||||
debug_dump_to_xml_padded_hex_output("publisher_id",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->publisher_id,
|
||||
ISODCL (319, 446));
|
||||
debug_dump_to_xml_padded_hex_output("preparer_id",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->preparer_id,
|
||||
ISODCL (447, 574));
|
||||
debug_dump_to_xml_padded_hex_output("application_id",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->application_id,
|
||||
ISODCL (575, 702));
|
||||
debug_dump_to_xml_padded_hex_output("copyright_file_id",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->copyright_file_id,
|
||||
ISODCL (703, 739));
|
||||
debug_dump_to_xml_padded_hex_output("abstract_file_id",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->abstract_file_id,
|
||||
ISODCL (740, 776));
|
||||
debug_dump_to_xml_padded_hex_output("bibliographic_file_id",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->bibliographic_file_id,
|
||||
ISODCL (777, 813));
|
||||
|
||||
debug_dump_to_xml_padded_hex_output("creation_date",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->creation_date,
|
||||
ISODCL (814, 830));
|
||||
debug_dump_to_xml_padded_hex_output("modification_date",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->modification_date,
|
||||
ISODCL (831, 847));
|
||||
debug_dump_to_xml_padded_hex_output("expiration_date",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->expiration_date,
|
||||
ISODCL (848, 864));
|
||||
debug_dump_to_xml_padded_hex_output("effective_date",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->effective_date,
|
||||
ISODCL (865, 881));
|
||||
|
||||
debug_dump_to_xml_padded_hex_output("file_structure_version",
|
||||
(u_char *)((struct iso_primary_descriptor*) buf)->file_structure_version,
|
||||
ISODCL(882,882));
|
||||
break;
|
||||
}
|
||||
printf("</volumedescriptor>\n");
|
||||
}
|
||||
|
539
usr.sbin/makefs/cd9660/cd9660_eltorito.c
Normal file
539
usr.sbin/makefs/cd9660/cd9660_eltorito.c
Normal file
@ -0,0 +1,539 @@
|
||||
/* $NetBSD: cd9660_eltorito.c,v 1.14 2010/10/27 18:51:35 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
|
||||
* Perez-Rathke and Ram Vedam. All rights reserved.
|
||||
*
|
||||
* This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
|
||||
* Alan Perez-Rathke and Ram Vedam.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "cd9660.h"
|
||||
#include "cd9660_eltorito.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ELTORITO_DPRINTF(__x) printf __x
|
||||
#else
|
||||
#define ELTORITO_DPRINTF(__x)
|
||||
#endif
|
||||
|
||||
static struct boot_catalog_entry *cd9660_init_boot_catalog_entry(void);
|
||||
static struct boot_catalog_entry *cd9660_boot_setup_validation_entry(char);
|
||||
static struct boot_catalog_entry *cd9660_boot_setup_default_entry(
|
||||
struct cd9660_boot_image *);
|
||||
static struct boot_catalog_entry *cd9660_boot_setup_section_head(char);
|
||||
static struct boot_catalog_entry *cd9660_boot_setup_validation_entry(char);
|
||||
#if 0
|
||||
static u_char cd9660_boot_get_system_type(struct cd9660_boot_image *);
|
||||
#endif
|
||||
|
||||
int
|
||||
cd9660_add_boot_disk(const char *boot_info)
|
||||
{
|
||||
struct stat stbuf;
|
||||
const char *mode_msg;
|
||||
char *temp;
|
||||
char *sysname;
|
||||
char *filename;
|
||||
struct cd9660_boot_image *new_image, *tmp_image;
|
||||
|
||||
assert(boot_info != NULL);
|
||||
|
||||
if (*boot_info == '\0') {
|
||||
warnx("Error: Boot disk information must be in the "
|
||||
"format 'system;filename'");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First decode the boot information */
|
||||
if ((temp = strdup(boot_info)) == NULL) {
|
||||
warn("%s: strdup", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sysname = temp;
|
||||
filename = strchr(sysname, ';');
|
||||
if (filename == NULL) {
|
||||
warnx("supply boot disk information in the format "
|
||||
"'system;filename'");
|
||||
free(temp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*filename++ = '\0';
|
||||
|
||||
if (diskStructure.verbose_level > 0) {
|
||||
printf("Found bootdisk with system %s, and filename %s\n",
|
||||
sysname, filename);
|
||||
}
|
||||
if ((new_image = malloc(sizeof(*new_image))) == NULL) {
|
||||
warn("%s: malloc", __func__);
|
||||
free(temp);
|
||||
return 0;
|
||||
}
|
||||
(void)memset(new_image, 0, sizeof(*new_image));
|
||||
new_image->loadSegment = 0; /* default for now */
|
||||
|
||||
/* Decode System */
|
||||
if (strcmp(sysname, "i386") == 0)
|
||||
new_image->system = ET_SYS_X86;
|
||||
else if (strcmp(sysname, "powerpc") == 0)
|
||||
new_image->system = ET_SYS_PPC;
|
||||
else if (strcmp(sysname, "macppc") == 0 ||
|
||||
strcmp(sysname, "mac68k") == 0)
|
||||
new_image->system = ET_SYS_MAC;
|
||||
else {
|
||||
warnx("boot disk system must be "
|
||||
"i386, powerpc, macppc, or mac68k");
|
||||
free(temp);
|
||||
free(new_image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if ((new_image->filename = strdup(filename)) == NULL) {
|
||||
warn("%s: strdup", __func__);
|
||||
free(temp);
|
||||
free(new_image);
|
||||
return 0;
|
||||
}
|
||||
|
||||
free(temp);
|
||||
|
||||
/* Get information about the file */
|
||||
if (lstat(new_image->filename, &stbuf) == -1)
|
||||
err(EXIT_FAILURE, "%s: lstat(\"%s\")", __func__,
|
||||
new_image->filename);
|
||||
|
||||
switch (stbuf.st_size) {
|
||||
case 1440 * 1024:
|
||||
new_image->targetMode = ET_MEDIA_144FDD;
|
||||
mode_msg = "Assigned boot image to 1.44 emulation mode";
|
||||
break;
|
||||
case 1200 * 1024:
|
||||
new_image->targetMode = ET_MEDIA_12FDD;
|
||||
mode_msg = "Assigned boot image to 1.2 emulation mode";
|
||||
break;
|
||||
case 2880 * 1024:
|
||||
new_image->targetMode = ET_MEDIA_288FDD;
|
||||
mode_msg = "Assigned boot image to 2.88 emulation mode";
|
||||
break;
|
||||
default:
|
||||
new_image->targetMode = ET_MEDIA_NOEM;
|
||||
mode_msg = "Assigned boot image to no emulation mode";
|
||||
break;
|
||||
}
|
||||
|
||||
if (diskStructure.verbose_level > 0)
|
||||
printf("%s\n", mode_msg);
|
||||
|
||||
new_image->size = stbuf.st_size;
|
||||
new_image->num_sectors =
|
||||
howmany(new_image->size, diskStructure.sectorSize) *
|
||||
howmany(diskStructure.sectorSize, 512);
|
||||
if (diskStructure.verbose_level > 0) {
|
||||
printf("New image has size %d, uses %d 512-byte sectors\n",
|
||||
new_image->size, new_image->num_sectors);
|
||||
}
|
||||
new_image->sector = -1;
|
||||
/* Bootable by default */
|
||||
new_image->bootable = ET_BOOTABLE;
|
||||
/* Add boot disk */
|
||||
|
||||
/* Group images for the same platform together. */
|
||||
TAILQ_FOREACH(tmp_image, &diskStructure.boot_images, image_list) {
|
||||
if (tmp_image->system != new_image->system)
|
||||
break;
|
||||
}
|
||||
|
||||
if (tmp_image == NULL) {
|
||||
TAILQ_INSERT_HEAD(&diskStructure.boot_images, new_image,
|
||||
image_list);
|
||||
} else
|
||||
TAILQ_INSERT_BEFORE(tmp_image, new_image, image_list);
|
||||
|
||||
new_image->serialno = diskStructure.image_serialno++;
|
||||
|
||||
/* TODO : Need to do anything about the boot image in the tree? */
|
||||
diskStructure.is_bootable = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_eltorito_add_boot_option(const char *option_string, const char *value)
|
||||
{
|
||||
char *eptr;
|
||||
struct cd9660_boot_image *image;
|
||||
|
||||
assert(option_string != NULL);
|
||||
|
||||
/* Find the last image added */
|
||||
TAILQ_FOREACH(image, &diskStructure.boot_images, image_list) {
|
||||
if (image->serialno + 1 == diskStructure.image_serialno)
|
||||
break;
|
||||
}
|
||||
if (image == NULL)
|
||||
errx(EXIT_FAILURE, "Attempted to add boot option, "
|
||||
"but no boot images have been specified");
|
||||
|
||||
if (strcmp(option_string, "no-emul-boot") == 0) {
|
||||
image->targetMode = ET_MEDIA_NOEM;
|
||||
} else if (strcmp(option_string, "no-boot") == 0) {
|
||||
image->bootable = ET_NOT_BOOTABLE;
|
||||
} else if (strcmp(option_string, "hard-disk-boot") == 0) {
|
||||
image->targetMode = ET_MEDIA_HDD;
|
||||
} else if (strcmp(option_string, "boot-load-segment") == 0) {
|
||||
image->loadSegment = strtoul(value, &eptr, 16);
|
||||
if (eptr == value || *eptr != '\0' || errno != ERANGE) {
|
||||
warn("%s: strtoul", __func__);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct boot_catalog_entry *
|
||||
cd9660_init_boot_catalog_entry(void)
|
||||
{
|
||||
struct boot_catalog_entry *temp;
|
||||
|
||||
if ((temp = malloc(sizeof(*temp))) == NULL)
|
||||
return NULL;
|
||||
|
||||
return memset(temp, 0, sizeof(*temp));
|
||||
}
|
||||
|
||||
static struct boot_catalog_entry *
|
||||
cd9660_boot_setup_validation_entry(char sys)
|
||||
{
|
||||
struct boot_catalog_entry *entry;
|
||||
boot_catalog_validation_entry *ve;
|
||||
int16_t checksum;
|
||||
unsigned char *csptr;
|
||||
int i;
|
||||
entry = cd9660_init_boot_catalog_entry();
|
||||
|
||||
if (entry == NULL) {
|
||||
warnx("Error: memory allocation failed in "
|
||||
"cd9660_boot_setup_validation_entry");
|
||||
return 0;
|
||||
}
|
||||
ve = &entry->entry_data.VE;
|
||||
|
||||
ve->header_id[0] = 1;
|
||||
ve->platform_id[0] = sys;
|
||||
ve->key[0] = 0x55;
|
||||
ve->key[1] = 0xAA;
|
||||
|
||||
/* Calculate checksum */
|
||||
checksum = 0;
|
||||
cd9660_721(0, ve->checksum);
|
||||
csptr = (unsigned char*)ve;
|
||||
for (i = 0; i < sizeof(*ve); i += 2) {
|
||||
checksum += (int16_t)csptr[i];
|
||||
checksum += 256 * (int16_t)csptr[i + 1];
|
||||
}
|
||||
checksum = -checksum;
|
||||
cd9660_721(checksum, ve->checksum);
|
||||
|
||||
ELTORITO_DPRINTF(("%s: header_id %d, platform_id %d, key[0] %d, key[1] %d, "
|
||||
"checksum %04x\n", __func__, ve->header_id[0], ve->platform_id[0],
|
||||
ve->key[0], ve->key[1], checksum));
|
||||
return entry;
|
||||
}
|
||||
|
||||
static struct boot_catalog_entry *
|
||||
cd9660_boot_setup_default_entry(struct cd9660_boot_image *disk)
|
||||
{
|
||||
struct boot_catalog_entry *default_entry;
|
||||
boot_catalog_initial_entry *ie;
|
||||
|
||||
default_entry = cd9660_init_boot_catalog_entry();
|
||||
if (default_entry == NULL)
|
||||
return NULL;
|
||||
|
||||
ie = &default_entry->entry_data.IE;
|
||||
|
||||
ie->boot_indicator[0] = disk->bootable;
|
||||
ie->media_type[0] = disk->targetMode;
|
||||
cd9660_721(disk->loadSegment, ie->load_segment);
|
||||
ie->system_type[0] = disk->system;
|
||||
cd9660_721(disk->num_sectors, ie->sector_count);
|
||||
cd9660_731(disk->sector, ie->load_rba);
|
||||
|
||||
ELTORITO_DPRINTF(("%s: boot indicator %d, media type %d, "
|
||||
"load segment %04x, system type %d, sector count %d, "
|
||||
"load rba %d\n", __func__, ie->boot_indicator[0],
|
||||
ie->media_type[0], disk->loadSegment, ie->system_type[0],
|
||||
disk->num_sectors, disk->sector));
|
||||
return default_entry;
|
||||
}
|
||||
|
||||
static struct boot_catalog_entry *
|
||||
cd9660_boot_setup_section_head(char platform)
|
||||
{
|
||||
struct boot_catalog_entry *entry;
|
||||
boot_catalog_section_header *sh;
|
||||
|
||||
entry = cd9660_init_boot_catalog_entry();
|
||||
if (entry == NULL)
|
||||
return NULL;
|
||||
|
||||
sh = &entry->entry_data.SH;
|
||||
/* More by default. The last one will manually be set to 0x91 */
|
||||
sh->header_indicator[0] = ET_SECTION_HEADER_MORE;
|
||||
sh->platform_id[0] = platform;
|
||||
sh->num_section_entries[0] = 0;
|
||||
return entry;
|
||||
}
|
||||
|
||||
static struct boot_catalog_entry *
|
||||
cd9660_boot_setup_section_entry(struct cd9660_boot_image *disk)
|
||||
{
|
||||
struct boot_catalog_entry *entry;
|
||||
boot_catalog_section_entry *se;
|
||||
if ((entry = cd9660_init_boot_catalog_entry()) == NULL)
|
||||
return NULL;
|
||||
|
||||
se = &entry->entry_data.SE;
|
||||
|
||||
se->boot_indicator[0] = ET_BOOTABLE;
|
||||
se->media_type[0] = disk->targetMode;
|
||||
cd9660_721(disk->loadSegment, se->load_segment);
|
||||
cd9660_721(disk->num_sectors, se->sector_count);
|
||||
cd9660_731(disk->sector, se->load_rba);
|
||||
return entry;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static u_char
|
||||
cd9660_boot_get_system_type(struct cd9660_boot_image *disk)
|
||||
{
|
||||
/*
|
||||
For hard drive booting, we need to examine the MBR to figure
|
||||
out what the partition type is
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set up the BVD, Boot catalog, and the boot entries, but do no writing
|
||||
*/
|
||||
int
|
||||
cd9660_setup_boot(int first_sector)
|
||||
{
|
||||
int sector;
|
||||
int used_sectors;
|
||||
int num_entries = 0;
|
||||
int catalog_sectors;
|
||||
struct boot_catalog_entry *x86_head, *mac_head, *ppc_head,
|
||||
*valid_entry, *default_entry, *temp, *head, **headp, *next;
|
||||
struct cd9660_boot_image *tmp_disk;
|
||||
|
||||
headp = NULL;
|
||||
x86_head = mac_head = ppc_head = NULL;
|
||||
|
||||
/* If there are no boot disks, don't bother building boot information */
|
||||
if (TAILQ_EMPTY(&diskStructure.boot_images))
|
||||
return 0;
|
||||
|
||||
/* Point to catalog: For now assume it consumes one sector */
|
||||
ELTORITO_DPRINTF(("Boot catalog will go in sector %d\n", first_sector));
|
||||
diskStructure.boot_catalog_sector = first_sector;
|
||||
cd9660_bothendian_dword(first_sector,
|
||||
diskStructure.boot_descriptor->boot_catalog_pointer);
|
||||
|
||||
/* Step 1: Generate boot catalog */
|
||||
/* Step 1a: Validation entry */
|
||||
valid_entry = cd9660_boot_setup_validation_entry(ET_SYS_X86);
|
||||
if (valid_entry == NULL)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* Count how many boot images there are,
|
||||
* and how many sectors they consume.
|
||||
*/
|
||||
num_entries = 1;
|
||||
used_sectors = 0;
|
||||
|
||||
TAILQ_FOREACH(tmp_disk, &diskStructure.boot_images, image_list) {
|
||||
used_sectors += tmp_disk->num_sectors;
|
||||
|
||||
/* One default entry per image */
|
||||
num_entries++;
|
||||
}
|
||||
catalog_sectors = howmany(num_entries * 0x20, diskStructure.sectorSize);
|
||||
used_sectors += catalog_sectors;
|
||||
|
||||
if (diskStructure.verbose_level > 0) {
|
||||
printf("%s: there will be %i entries consuming %i sectors. "
|
||||
"Catalog is %i sectors\n", __func__, num_entries,
|
||||
used_sectors, catalog_sectors);
|
||||
}
|
||||
|
||||
/* Populate sector numbers */
|
||||
sector = first_sector + catalog_sectors;
|
||||
TAILQ_FOREACH(tmp_disk, &diskStructure.boot_images, image_list) {
|
||||
tmp_disk->sector = sector;
|
||||
sector += tmp_disk->num_sectors;
|
||||
}
|
||||
|
||||
LIST_INSERT_HEAD(&diskStructure.boot_entries, valid_entry, ll_struct);
|
||||
|
||||
/* Step 1b: Initial/default entry */
|
||||
/* TODO : PARAM */
|
||||
tmp_disk = TAILQ_FIRST(&diskStructure.boot_images);
|
||||
default_entry = cd9660_boot_setup_default_entry(tmp_disk);
|
||||
if (default_entry == NULL) {
|
||||
warnx("Error: memory allocation failed in cd9660_setup_boot");
|
||||
return -1;
|
||||
}
|
||||
|
||||
LIST_INSERT_AFTER(valid_entry, default_entry, ll_struct);
|
||||
|
||||
/* Todo: multiple default entries? */
|
||||
|
||||
tmp_disk = TAILQ_NEXT(tmp_disk, image_list);
|
||||
|
||||
temp = default_entry;
|
||||
|
||||
/* If multiple boot images are given : */
|
||||
while (tmp_disk != NULL) {
|
||||
/* Step 2: Section header */
|
||||
switch (tmp_disk->system) {
|
||||
case ET_SYS_X86:
|
||||
headp = &x86_head;
|
||||
break;
|
||||
case ET_SYS_PPC:
|
||||
headp = &ppc_head;
|
||||
break;
|
||||
case ET_SYS_MAC:
|
||||
headp = &mac_head;
|
||||
break;
|
||||
default:
|
||||
warnx("%s: internal error: unknown system type",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*headp == NULL) {
|
||||
head =
|
||||
cd9660_boot_setup_section_head(tmp_disk->system);
|
||||
if (head == NULL) {
|
||||
warnx("Error: memory allocation failed in "
|
||||
"cd9660_setup_boot");
|
||||
return -1;
|
||||
}
|
||||
LIST_INSERT_AFTER(default_entry, head, ll_struct);
|
||||
*headp = head;
|
||||
} else
|
||||
head = *headp;
|
||||
|
||||
head->entry_data.SH.num_section_entries[0]++;
|
||||
|
||||
/* Step 2a: Section entry and extensions */
|
||||
temp = cd9660_boot_setup_section_entry(tmp_disk);
|
||||
if (temp == NULL) {
|
||||
warn("%s: cd9660_boot_setup_section_entry", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((next = LIST_NEXT(head, ll_struct)) != NULL &&
|
||||
next->entry_type == ET_ENTRY_SE)
|
||||
head = next;
|
||||
|
||||
LIST_INSERT_AFTER(head, temp, ll_struct);
|
||||
tmp_disk = TAILQ_NEXT(tmp_disk, image_list);
|
||||
}
|
||||
|
||||
/* TODO: Remaining boot disks when implemented */
|
||||
|
||||
return first_sector + used_sectors;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_setup_boot_volume_descriptor(volume_descriptor *bvd)
|
||||
{
|
||||
boot_volume_descriptor *bvdData =
|
||||
(boot_volume_descriptor*)bvd->volumeDescriptorData;
|
||||
|
||||
bvdData->boot_record_indicator[0] = ISO_VOLUME_DESCRIPTOR_BOOT;
|
||||
memcpy(bvdData->identifier, ISO_VOLUME_DESCRIPTOR_STANDARD_ID, 5);
|
||||
bvdData->version[0] = 1;
|
||||
memcpy(bvdData->boot_system_identifier, ET_ID, 23);
|
||||
memcpy(bvdData->identifier, ISO_VOLUME_DESCRIPTOR_STANDARD_ID, 5);
|
||||
diskStructure.boot_descriptor =
|
||||
(boot_volume_descriptor*) bvd->volumeDescriptorData;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_write_boot(FILE *fd)
|
||||
{
|
||||
struct boot_catalog_entry *e;
|
||||
struct cd9660_boot_image *t;
|
||||
|
||||
/* write boot catalog */
|
||||
if (fseeko(fd, (off_t)diskStructure.boot_catalog_sector *
|
||||
diskStructure.sectorSize, SEEK_SET) == -1)
|
||||
err(1, "fseeko");
|
||||
|
||||
if (diskStructure.verbose_level > 0) {
|
||||
printf("Writing boot catalog to sector %" PRId64 "\n",
|
||||
diskStructure.boot_catalog_sector);
|
||||
}
|
||||
LIST_FOREACH(e, &diskStructure.boot_entries, ll_struct) {
|
||||
if (diskStructure.verbose_level > 0) {
|
||||
printf("Writing catalog entry of type %d\n",
|
||||
e->entry_type);
|
||||
}
|
||||
/*
|
||||
* It doesnt matter which one gets written
|
||||
* since they are the same size
|
||||
*/
|
||||
fwrite(&(e->entry_data.VE), 1, 32, fd);
|
||||
}
|
||||
if (diskStructure.verbose_level > 0)
|
||||
printf("Finished writing boot catalog\n");
|
||||
|
||||
/* copy boot images */
|
||||
TAILQ_FOREACH(t, &diskStructure.boot_images, image_list) {
|
||||
if (diskStructure.verbose_level > 0) {
|
||||
printf("Writing boot image from %s to sectors %d\n",
|
||||
t->filename, t->sector);
|
||||
}
|
||||
cd9660_copy_file(fd, t->sector, t->filename);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
164
usr.sbin/makefs/cd9660/cd9660_eltorito.h
Normal file
164
usr.sbin/makefs/cd9660/cd9660_eltorito.h
Normal file
@ -0,0 +1,164 @@
|
||||
/* $NetBSD: cd9660_eltorito.h,v 1.5 2009/07/04 14:31:38 ahoka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
|
||||
* Perez-Rathke and Ram Vedam. All rights reserved.
|
||||
*
|
||||
* This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
|
||||
* Alan Perez-Rathke and Ram Vedam.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _CD9660_ELTORITO_H_
|
||||
#define _CD9660_ELTORITO_H_
|
||||
|
||||
/* Boot defines */
|
||||
#define ET_ID "EL TORITO SPECIFICATION"
|
||||
#define ET_SYS_X86 0
|
||||
#define ET_SYS_PPC 1
|
||||
#define ET_SYS_MAC 2
|
||||
|
||||
#define ET_BOOT_ENTRY_SIZE 0x20
|
||||
|
||||
#define ET_BOOTABLE 0x88
|
||||
#define ET_NOT_BOOTABLE 0
|
||||
|
||||
#define ET_MEDIA_NOEM 0
|
||||
#define ET_MEDIA_12FDD 1
|
||||
#define ET_MEDIA_144FDD 2
|
||||
#define ET_MEDIA_288FDD 3
|
||||
#define ET_MEDIA_HDD 4
|
||||
|
||||
#define ET_INDICATOR_HEADERMORE 0x90
|
||||
#define ET_INDICATOR_HEADERLAST 0x91
|
||||
#define ET_INDICATOR_EXTENSION 0x44
|
||||
|
||||
/*** Boot Structures ***/
|
||||
|
||||
typedef struct _boot_volume_descriptor {
|
||||
u_char boot_record_indicator [ISODCL(0x00,0x00)];
|
||||
u_char identifier [ISODCL(0x01,0x05)];
|
||||
u_char version [ISODCL(0x06,0x06)];
|
||||
u_char boot_system_identifier [ISODCL(0x07,0x26)];
|
||||
u_char unused1 [ISODCL(0x27,0x46)];
|
||||
u_char boot_catalog_pointer [ISODCL(0x47,0x4A)];
|
||||
u_char unused2 [ISODCL(0x4B,0x7FF)];
|
||||
} boot_volume_descriptor;
|
||||
|
||||
typedef struct _boot_catalog_validation_entry {
|
||||
u_char header_id [ISODCL(0x00,0x00)];
|
||||
u_char platform_id [ISODCL(0x01,0x01)];
|
||||
u_char reserved1 [ISODCL(0x02,0x03)];
|
||||
u_char manufacturer [ISODCL(0x04,0x1B)];
|
||||
u_char checksum [ISODCL(0x1C,0x1D)];
|
||||
u_char key [ISODCL(0x1E,0x1F)];
|
||||
} boot_catalog_validation_entry;
|
||||
|
||||
typedef struct _boot_catalog_initial_entry {
|
||||
u_char boot_indicator [ISODCL(0x00,0x00)];
|
||||
u_char media_type [ISODCL(0x01,0x01)];
|
||||
u_char load_segment [ISODCL(0x02,0x03)];
|
||||
u_char system_type [ISODCL(0x04,0x04)];
|
||||
u_char unused_1 [ISODCL(0x05,0x05)];
|
||||
u_char sector_count [ISODCL(0x06,0x07)];
|
||||
u_char load_rba [ISODCL(0x08,0x0B)];
|
||||
u_char unused_2 [ISODCL(0x0C,0x1F)];
|
||||
} boot_catalog_initial_entry;
|
||||
|
||||
#define ET_SECTION_HEADER_MORE 0x90
|
||||
#define ET_SECTION_HEADER_LAST 0x91
|
||||
|
||||
typedef struct _boot_catalog_section_header {
|
||||
u_char header_indicator [ISODCL(0x00,0x00)];
|
||||
u_char platform_id [ISODCL(0x01,0x01)];
|
||||
u_char num_section_entries [ISODCL(0x02,0x03)];
|
||||
u_char id_string [ISODCL(0x04,0x1F)];
|
||||
} boot_catalog_section_header;
|
||||
|
||||
typedef struct _boot_catalog_section_entry {
|
||||
u_char boot_indicator [ISODCL(0x00,0x00)];
|
||||
u_char media_type [ISODCL(0x01,0x01)];
|
||||
u_char load_segment [ISODCL(0x02,0x03)];
|
||||
u_char system_type [ISODCL(0x04,0x04)];
|
||||
u_char unused_1 [ISODCL(0x05,0x05)];
|
||||
u_char sector_count [ISODCL(0x06,0x07)];
|
||||
u_char load_rba [ISODCL(0x08,0x0B)];
|
||||
u_char selection_criteria [ISODCL(0x0C,0x0C)];
|
||||
u_char vendor_criteria [ISODCL(0x0D,0x1F)];
|
||||
} boot_catalog_section_entry;
|
||||
|
||||
typedef struct _boot_catalog_section_entry_extension {
|
||||
u_char extension_indicator [ISODCL(0x00,0x00)];
|
||||
u_char flags [ISODCL(0x01,0x01)];
|
||||
u_char vendor_criteria [ISODCL(0x02,0x1F)];
|
||||
} boot_catalog_section_entry_extension;
|
||||
|
||||
#define ET_ENTRY_VE 1
|
||||
#define ET_ENTRY_IE 2
|
||||
#define ET_ENTRY_SH 3
|
||||
#define ET_ENTRY_SE 4
|
||||
#define ET_ENTRY_EX 5
|
||||
|
||||
struct boot_catalog_entry {
|
||||
char entry_type;
|
||||
union {
|
||||
boot_catalog_validation_entry VE;
|
||||
boot_catalog_initial_entry IE;
|
||||
boot_catalog_section_header SH;
|
||||
boot_catalog_section_entry SE;
|
||||
boot_catalog_section_entry_extension EX;
|
||||
} entry_data;
|
||||
|
||||
LIST_ENTRY(boot_catalog_entry) ll_struct;
|
||||
};
|
||||
|
||||
/* Temporary structure */
|
||||
struct cd9660_boot_image {
|
||||
char *filename;
|
||||
int size;
|
||||
int sector; /* copied to LoadRBA */
|
||||
int num_sectors;
|
||||
unsigned int loadSegment;
|
||||
u_char targetMode;
|
||||
u_char system;
|
||||
u_char bootable;
|
||||
/*
|
||||
* If the boot image exists in the filesystem
|
||||
* already, this is a pointer to that node. For the sake
|
||||
* of simplicity in future versions, this pointer is only
|
||||
* to the node in the primary volume. This SHOULD be done
|
||||
* via a hashtable lookup.
|
||||
*/
|
||||
struct _cd9660node *boot_image_node;
|
||||
TAILQ_ENTRY(cd9660_boot_image) image_list;
|
||||
int serialno;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _CD9660_ELTORITO_H_ */
|
||||
|
120
usr.sbin/makefs/cd9660/cd9660_strings.c
Normal file
120
usr.sbin/makefs/cd9660/cd9660_strings.c
Normal file
@ -0,0 +1,120 @@
|
||||
/* $NetBSD: cd9660_strings.c,v 1.4 2007/01/16 17:32:05 hubertf Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
|
||||
* Perez-Rathke and Ram Vedam. All rights reserved.
|
||||
*
|
||||
* This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
|
||||
* Alan Perez-Rathke and Ram Vedam.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/mount.h>
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "makefs.h"
|
||||
#include "cd9660.h"
|
||||
|
||||
|
||||
void
|
||||
cd9660_uppercase_characters(char *str, int len)
|
||||
{
|
||||
int p;
|
||||
|
||||
for (p = 0; p < len; p++) {
|
||||
if (islower((unsigned char)str[p]) )
|
||||
str[p] -= 32;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
cd9660_is_a_char(char c)
|
||||
{
|
||||
return (isupper((unsigned char)c)
|
||||
|| c == '_'
|
||||
|| (c >= '0' && c <= '?'));
|
||||
}
|
||||
|
||||
static inline int
|
||||
cd9660_is_d_char(char c)
|
||||
{
|
||||
return (isupper((unsigned char)c)
|
||||
|| c == '_'
|
||||
|| (c >= '%' && c <= '9')
|
||||
|| (c >= ' ' && c <= '\"'));
|
||||
}
|
||||
|
||||
/*
|
||||
* Test a string to see if it is composed of valid a characters
|
||||
* @param const char* The string to test
|
||||
* @returns int 1 if valid, 2 if valid if characters are converted to
|
||||
* upper case, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cd9660_valid_a_chars(const char *str)
|
||||
{
|
||||
const char *c = str;
|
||||
int upperFound = 0;
|
||||
|
||||
while ((*c) != '\0') {
|
||||
if (!(cd9660_is_a_char(*c))) {
|
||||
if (islower((unsigned char)*c) )
|
||||
upperFound = 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
return upperFound + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test a string to see if it is composed of valid d characters
|
||||
* @param const char* The string to test
|
||||
* @returns int 1 if valid, 2 if valid if characters are converted to
|
||||
* upper case, 0 otherwise
|
||||
*/
|
||||
int
|
||||
cd9660_valid_d_chars(const char *str)
|
||||
{
|
||||
const char *c=str;
|
||||
int upperFound = 0;
|
||||
|
||||
while ((*c) != '\0') {
|
||||
if (!(cd9660_is_d_char(*c))) {
|
||||
if (islower((unsigned char)*c) )
|
||||
upperFound = 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
c++;
|
||||
}
|
||||
return upperFound + 1;
|
||||
}
|
518
usr.sbin/makefs/cd9660/cd9660_write.c
Normal file
518
usr.sbin/makefs/cd9660/cd9660_write.c
Normal file
@ -0,0 +1,518 @@
|
||||
/* $NetBSD: cd9660_write.c,v 1.13 2010/10/22 00:49:15 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
|
||||
* Perez-Rathke and Ram Vedam. All rights reserved.
|
||||
*
|
||||
* This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
|
||||
* Alan Perez-Rathke and Ram Vedam.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "cd9660.h"
|
||||
#include "iso9660_rrip.h"
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static int cd9660_write_volume_descriptors(FILE *);
|
||||
static int cd9660_write_path_table(FILE *, off_t, int);
|
||||
static int cd9660_write_path_tables(FILE *);
|
||||
static int cd9660_write_file(FILE *, cd9660node *);
|
||||
static int cd9660_write_filedata(FILE *, off_t, const unsigned char *, int);
|
||||
#if 0
|
||||
static int cd9660_write_buffered(FILE *, off_t, int, const unsigned char *);
|
||||
#endif
|
||||
static void cd9660_write_rr(FILE *, cd9660node *, off_t, off_t);
|
||||
|
||||
/*
|
||||
* Write the image
|
||||
* Writes the entire image
|
||||
* @param const char* The filename for the image
|
||||
* @returns int 1 on success, 0 on failure
|
||||
*/
|
||||
int
|
||||
cd9660_write_image(const char* image)
|
||||
{
|
||||
FILE *fd;
|
||||
int status;
|
||||
char buf[CD9660_SECTOR_SIZE];
|
||||
|
||||
if ((fd = fopen(image, "w+")) == NULL) {
|
||||
err(EXIT_FAILURE, "%s: Can't open `%s' for writing", __func__,
|
||||
image);
|
||||
}
|
||||
|
||||
if (diskStructure.verbose_level > 0)
|
||||
printf("Writing image\n");
|
||||
|
||||
if (diskStructure.has_generic_bootimage) {
|
||||
status = cd9660_copy_file(fd, 0,
|
||||
diskStructure.generic_bootimage);
|
||||
if (status == 0) {
|
||||
warnx("%s: Error writing generic boot image",
|
||||
__func__);
|
||||
goto cleanup_bad_image;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the volume descriptors */
|
||||
status = cd9660_write_volume_descriptors(fd);
|
||||
if (status == 0) {
|
||||
warnx("%s: Error writing volume descriptors to image",
|
||||
__func__);
|
||||
goto cleanup_bad_image;
|
||||
}
|
||||
|
||||
if (diskStructure.verbose_level > 0)
|
||||
printf("Volume descriptors written\n");
|
||||
|
||||
/*
|
||||
* Write the path tables: there are actually four, but right
|
||||
* now we are only concearned with two.
|
||||
*/
|
||||
status = cd9660_write_path_tables(fd);
|
||||
if (status == 0) {
|
||||
warnx("%s: Error writing path tables to image", __func__);
|
||||
goto cleanup_bad_image;
|
||||
}
|
||||
|
||||
if (diskStructure.verbose_level > 0)
|
||||
printf("Path tables written\n");
|
||||
|
||||
/* Write the directories and files */
|
||||
status = cd9660_write_file(fd, diskStructure.rootNode);
|
||||
if (status == 0) {
|
||||
warnx("%s: Error writing files to image", __func__);
|
||||
goto cleanup_bad_image;
|
||||
}
|
||||
|
||||
if (diskStructure.is_bootable) {
|
||||
cd9660_write_boot(fd);
|
||||
}
|
||||
|
||||
/* Write padding bits. This is temporary */
|
||||
memset(buf, 0, CD9660_SECTOR_SIZE);
|
||||
cd9660_write_filedata(fd, diskStructure.totalSectors - 1, buf, 1);
|
||||
|
||||
if (diskStructure.verbose_level > 0)
|
||||
printf("Files written\n");
|
||||
fclose(fd);
|
||||
|
||||
if (diskStructure.verbose_level > 0)
|
||||
printf("Image closed\n");
|
||||
return 1;
|
||||
|
||||
cleanup_bad_image:
|
||||
fclose(fd);
|
||||
if (!diskStructure.keep_bad_images)
|
||||
unlink(image);
|
||||
if (diskStructure.verbose_level > 0)
|
||||
printf("Bad image cleaned up\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cd9660_write_volume_descriptors(FILE *fd)
|
||||
{
|
||||
volume_descriptor *vd_temp = diskStructure.firstVolumeDescriptor;
|
||||
int pos;
|
||||
|
||||
while (vd_temp != NULL) {
|
||||
pos = vd_temp->sector * diskStructure.sectorSize;
|
||||
cd9660_write_filedata(fd, vd_temp->sector,
|
||||
vd_temp->volumeDescriptorData, 1);
|
||||
vd_temp = vd_temp->next;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out an individual path table
|
||||
* Used just to keep redundant code to a minimum
|
||||
* @param FILE *fd Valid file pointer
|
||||
* @param int Sector to start writing path table to
|
||||
* @param int Endian mode : BIG_ENDIAN or LITTLE_ENDIAN
|
||||
* @returns int 1 on success, 0 on failure
|
||||
*/
|
||||
static int
|
||||
cd9660_write_path_table(FILE *fd, off_t sector, int mode)
|
||||
{
|
||||
int path_table_sectors = CD9660_BLOCKS(diskStructure.sectorSize,
|
||||
diskStructure.pathTableLength);
|
||||
unsigned char *buffer;
|
||||
unsigned char *buffer_head;
|
||||
int len;
|
||||
path_table_entry temp_entry;
|
||||
cd9660node *ptcur;
|
||||
|
||||
buffer = malloc(diskStructure.sectorSize * path_table_sectors);
|
||||
if (buffer == NULL) {
|
||||
warnx("%s: Memory allocation error allocating buffer",
|
||||
__func__);
|
||||
return 0;
|
||||
}
|
||||
buffer_head = buffer;
|
||||
memset(buffer, 0, diskStructure.sectorSize * path_table_sectors);
|
||||
|
||||
ptcur = diskStructure.rootNode;
|
||||
|
||||
while (ptcur != NULL) {
|
||||
memset(&temp_entry, 0, sizeof(path_table_entry));
|
||||
temp_entry.length[0] = ptcur->isoDirRecord->name_len[0];
|
||||
temp_entry.extended_attribute_length[0] =
|
||||
ptcur->isoDirRecord->ext_attr_length[0];
|
||||
memcpy(temp_entry.name, ptcur->isoDirRecord->name,
|
||||
temp_entry.length[0] + 1);
|
||||
|
||||
/* round up */
|
||||
len = temp_entry.length[0] + 8 + (temp_entry.length[0] & 0x01);
|
||||
|
||||
/* todo: function pointers instead */
|
||||
if (mode == LITTLE_ENDIAN) {
|
||||
cd9660_731(ptcur->fileDataSector,
|
||||
temp_entry.first_sector);
|
||||
cd9660_721((ptcur->parent == NULL ?
|
||||
1 : ptcur->parent->ptnumber),
|
||||
temp_entry.parent_number);
|
||||
} else {
|
||||
cd9660_732(ptcur->fileDataSector,
|
||||
temp_entry.first_sector);
|
||||
cd9660_722((ptcur->parent == NULL ?
|
||||
1 : ptcur->parent->ptnumber),
|
||||
temp_entry.parent_number);
|
||||
}
|
||||
|
||||
|
||||
memcpy(buffer, &temp_entry, len);
|
||||
buffer += len;
|
||||
|
||||
ptcur = ptcur->ptnext;
|
||||
}
|
||||
|
||||
return cd9660_write_filedata(fd, sector, buffer_head,
|
||||
path_table_sectors);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Write out the path tables to disk
|
||||
* Each file descriptor should be pointed to by the PVD, so we know which
|
||||
* sector to copy them to. One thing to watch out for: the only path tables
|
||||
* stored are in the endian mode that the application is compiled for. So,
|
||||
* the first thing to do is write out that path table, then to write the one
|
||||
* in the other endian mode requires to convert the endianness of each entry
|
||||
* in the table. The best way to do this would be to create a temporary
|
||||
* path_table_entry structure, then for each path table entry, copy it to
|
||||
* the temporary entry, translate, then copy that to disk.
|
||||
*
|
||||
* @param FILE* Valid file descriptor
|
||||
* @returns int 0 on failure, 1 on success
|
||||
*/
|
||||
static int
|
||||
cd9660_write_path_tables(FILE *fd)
|
||||
{
|
||||
if (cd9660_write_path_table(fd,
|
||||
diskStructure.primaryLittleEndianTableSector, LITTLE_ENDIAN) == 0)
|
||||
return 0;
|
||||
|
||||
if (cd9660_write_path_table(fd,
|
||||
diskStructure.primaryBigEndianTableSector, BIG_ENDIAN) == 0)
|
||||
return 0;
|
||||
|
||||
/* @TODO: handle remaining two path tables */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a file to disk
|
||||
* Writes a file, its directory record, and its data to disk
|
||||
* This file is designed to be called RECURSIVELY, so initially call it
|
||||
* with the root node. All of the records should store what sector the
|
||||
* file goes in, so no computation should be necessary.
|
||||
*
|
||||
* @param int fd Valid file descriptor
|
||||
* @param struct cd9660node* writenode Pointer to the file to be written
|
||||
* @returns int 0 on failure, 1 on success
|
||||
*/
|
||||
static int
|
||||
cd9660_write_file(FILE *fd, cd9660node *writenode)
|
||||
{
|
||||
char *buf;
|
||||
char *temp_file_name;
|
||||
int ret;
|
||||
off_t working_sector;
|
||||
int cur_sector_offset;
|
||||
int written;
|
||||
iso_directory_record_cd9660 temp_record;
|
||||
cd9660node *temp;
|
||||
int rv = 0;
|
||||
|
||||
/* Todo : clean up variables */
|
||||
|
||||
temp_file_name = malloc(CD9660MAXPATH + 1);
|
||||
if (temp_file_name == NULL)
|
||||
err(EXIT_FAILURE, "%s: malloc", __func__);
|
||||
|
||||
memset(temp_file_name, 0, CD9660MAXPATH + 1);
|
||||
|
||||
buf = malloc(diskStructure.sectorSize);
|
||||
if (buf == NULL)
|
||||
err(EXIT_FAILURE, "%s: malloc", __func__);
|
||||
|
||||
if ((writenode->level != 0) &&
|
||||
!(writenode->node->type & S_IFDIR)) {
|
||||
fsinode *inode = writenode->node->inode;
|
||||
/* Only attempt to write unwritten files that have length. */
|
||||
if ((inode->flags & FI_WRITTEN) != 0) {
|
||||
INODE_WARNX(("%s: skipping written inode %d", __func__,
|
||||
(int)inode->st.st_ino));
|
||||
} else if (writenode->fileDataLength > 0) {
|
||||
INODE_WARNX(("%s: writing inode %d blocks at %" PRIu32,
|
||||
__func__, (int)inode->st.st_ino, inode->ino));
|
||||
inode->flags |= FI_WRITTEN;
|
||||
cd9660_compute_full_filename(writenode,
|
||||
temp_file_name, 0);
|
||||
ret = cd9660_copy_file(fd, writenode->fileDataSector,
|
||||
temp_file_name);
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Here is a new revelation that ECMA didnt explain
|
||||
* (at least not well).
|
||||
* ALL . and .. records store the name "\0" and "\1"
|
||||
* resepctively. So, for each directory, we have to
|
||||
* make a new node.
|
||||
*
|
||||
* This is where it gets kinda messy, since we have to
|
||||
* be careful of sector boundaries
|
||||
*/
|
||||
cur_sector_offset = 0;
|
||||
working_sector = writenode->fileDataSector;
|
||||
if (fseeko(fd, working_sector * diskStructure.sectorSize,
|
||||
SEEK_SET) == -1)
|
||||
err(1, "fseeko");
|
||||
|
||||
/*
|
||||
* Now loop over children, writing out their directory
|
||||
* records - beware of sector boundaries
|
||||
*/
|
||||
TAILQ_FOREACH(temp, &writenode->cn_children, cn_next_child) {
|
||||
/*
|
||||
* Copy the temporary record and adjust its size
|
||||
* if necessary
|
||||
*/
|
||||
memcpy(&temp_record, temp->isoDirRecord,
|
||||
sizeof(iso_directory_record_cd9660));
|
||||
|
||||
temp_record.length[0] =
|
||||
cd9660_compute_record_size(temp);
|
||||
|
||||
if (temp_record.length[0] + cur_sector_offset >=
|
||||
diskStructure.sectorSize) {
|
||||
cur_sector_offset = 0;
|
||||
working_sector++;
|
||||
|
||||
/* Seek to the next sector. */
|
||||
if (fseeko(fd, working_sector *
|
||||
diskStructure.sectorSize, SEEK_SET) == -1)
|
||||
err(1, "fseeko");
|
||||
}
|
||||
/* Write out the basic ISO directory record */
|
||||
written = fwrite(&temp_record, 1,
|
||||
temp->isoDirRecord->length[0], fd);
|
||||
if (diskStructure.rock_ridge_enabled) {
|
||||
cd9660_write_rr(fd, temp,
|
||||
cur_sector_offset, working_sector);
|
||||
}
|
||||
if (fseeko(fd, working_sector *
|
||||
diskStructure.sectorSize + cur_sector_offset +
|
||||
temp_record.length[0] - temp->su_tail_size,
|
||||
SEEK_SET) == -1)
|
||||
err(1, "fseeko");
|
||||
if (temp->su_tail_size > 0)
|
||||
fwrite(temp->su_tail_data, 1,
|
||||
temp->su_tail_size, fd);
|
||||
if (ferror(fd)) {
|
||||
warnx("%s: write error", __func__);
|
||||
goto out;
|
||||
}
|
||||
cur_sector_offset += temp_record.length[0];
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Recurse on children.
|
||||
*/
|
||||
TAILQ_FOREACH(temp, &writenode->cn_children, cn_next_child) {
|
||||
if ((ret = cd9660_write_file(fd, temp)) == 0)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
rv = 1;
|
||||
out:
|
||||
free(temp_file_name);
|
||||
free(buf);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper function to write a buffer (one sector) to disk.
|
||||
* Seeks and writes the buffer.
|
||||
* NOTE: You dont NEED to use this function, but it might make your
|
||||
* life easier if you have to write things that align to a sector
|
||||
* (such as volume descriptors).
|
||||
*
|
||||
* @param int fd Valid file descriptor
|
||||
* @param int sector Sector number to write to
|
||||
* @param const unsigned char* Buffer to write. This should be the
|
||||
* size of a sector, and if only a portion
|
||||
* is written, the rest should be set to 0.
|
||||
*/
|
||||
static int
|
||||
cd9660_write_filedata(FILE *fd, off_t sector, const unsigned char *buf,
|
||||
int numsecs)
|
||||
{
|
||||
off_t curpos;
|
||||
size_t success;
|
||||
|
||||
curpos = ftello(fd);
|
||||
|
||||
if (fseeko(fd, sector * diskStructure.sectorSize, SEEK_SET) == -1)
|
||||
err(1, "fseeko");
|
||||
|
||||
success = fwrite(buf, diskStructure.sectorSize * numsecs, 1, fd);
|
||||
|
||||
if (fseeko(fd, curpos, SEEK_SET) == -1)
|
||||
err(1, "fseeko");
|
||||
|
||||
if (success == 1)
|
||||
success = diskStructure.sectorSize * numsecs;
|
||||
return success;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int
|
||||
cd9660_write_buffered(FILE *fd, off_t offset, int buff_len,
|
||||
const unsigned char* buffer)
|
||||
{
|
||||
static int working_sector = -1;
|
||||
static char buf[CD9660_SECTOR_SIZE];
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
cd9660_copy_file(FILE *fd, off_t start_sector, const char *filename)
|
||||
{
|
||||
FILE *rf;
|
||||
int bytes_read;
|
||||
off_t sector = start_sector;
|
||||
int buf_size = diskStructure.sectorSize;
|
||||
char *buf;
|
||||
|
||||
buf = malloc(buf_size);
|
||||
if (buf == NULL)
|
||||
err(EXIT_FAILURE, "%s: malloc", __func__);
|
||||
|
||||
if ((rf = fopen(filename, "rb")) == NULL) {
|
||||
warn("%s: cannot open %s", __func__, filename);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (diskStructure.verbose_level > 1)
|
||||
printf("Writing file: %s\n",filename);
|
||||
|
||||
if (fseeko(fd, start_sector * diskStructure.sectorSize, SEEK_SET) == -1)
|
||||
err(1, "fseeko");
|
||||
|
||||
while (!feof(rf)) {
|
||||
bytes_read = fread(buf,1,buf_size,rf);
|
||||
if (ferror(rf)) {
|
||||
warn("%s: fread", __func__);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fwrite(buf,1,bytes_read,fd);
|
||||
if (ferror(fd)) {
|
||||
warn("%s: fwrite", __func__);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
sector++;
|
||||
}
|
||||
|
||||
fclose(rf);
|
||||
free(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
cd9660_write_rr(FILE *fd, cd9660node *writenode, off_t offset, off_t sector)
|
||||
{
|
||||
int in_ca = 0;
|
||||
struct ISO_SUSP_ATTRIBUTES *myattr;
|
||||
|
||||
offset += writenode->isoDirRecord->length[0];
|
||||
if (fseeko(fd, sector * diskStructure.sectorSize + offset, SEEK_SET) ==
|
||||
-1)
|
||||
err(1, "fseeko");
|
||||
/* Offset now points at the end of the record */
|
||||
TAILQ_FOREACH(myattr, &writenode->head, rr_ll) {
|
||||
fwrite(&(myattr->attr), CD9660_SUSP_ENTRY_SIZE(myattr), 1, fd);
|
||||
|
||||
if (!in_ca) {
|
||||
offset += CD9660_SUSP_ENTRY_SIZE(myattr);
|
||||
if (myattr->last_in_suf) {
|
||||
/*
|
||||
* Point the offset to the start of this
|
||||
* record's CE area
|
||||
*/
|
||||
if (fseeko(fd, ((off_t)diskStructure.
|
||||
susp_continuation_area_start_sector *
|
||||
diskStructure.sectorSize)
|
||||
+ writenode->susp_entry_ce_start,
|
||||
SEEK_SET) == -1)
|
||||
err(1, "fseeko");
|
||||
in_ca = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we had to go to the continuation area, head back to
|
||||
* where we should be.
|
||||
*/
|
||||
if (in_ca)
|
||||
if (fseeko(fd, sector * diskStructure.sectorSize + offset,
|
||||
SEEK_SET) == -1)
|
||||
err(1, "fseeko");
|
||||
}
|
836
usr.sbin/makefs/cd9660/iso9660_rrip.c
Normal file
836
usr.sbin/makefs/cd9660/iso9660_rrip.c
Normal file
@ -0,0 +1,836 @@
|
||||
/* $NetBSD: iso9660_rrip.c,v 1.8 2009/01/10 22:06:29 bjh21 Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
|
||||
* Perez-Rathke and Ram Vedam. All rights reserved.
|
||||
*
|
||||
* This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
|
||||
* Alan Perez-Rathke and Ram Vedam.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*/
|
||||
/* This will hold all the function definitions
|
||||
* defined in iso9660_rrip.h
|
||||
*/
|
||||
|
||||
#include "makefs.h"
|
||||
#include "cd9660.h"
|
||||
#include "iso9660_rrip.h"
|
||||
#include <sys/queue.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
static void cd9660_rrip_initialize_inode(cd9660node *);
|
||||
static int cd9660_susp_handle_continuation(cd9660node *);
|
||||
static int cd9660_susp_handle_continuation_common(cd9660node *, int);
|
||||
|
||||
int
|
||||
cd9660_susp_initialize(cd9660node *node, cd9660node *parent,
|
||||
cd9660node *grandparent)
|
||||
{
|
||||
cd9660node *cn;
|
||||
int r;
|
||||
|
||||
/* Make sure the node is not NULL. If it is, there are major problems */
|
||||
assert(node != NULL);
|
||||
|
||||
if (!(node->type & CD9660_TYPE_DOT) &&
|
||||
!(node->type & CD9660_TYPE_DOTDOT))
|
||||
TAILQ_INIT(&(node->head));
|
||||
if (node->dot_record != 0)
|
||||
TAILQ_INIT(&(node->dot_record->head));
|
||||
if (node->dot_dot_record != 0)
|
||||
TAILQ_INIT(&(node->dot_dot_record->head));
|
||||
|
||||
/* SUSP specific entries here */
|
||||
if ((r = cd9660_susp_initialize_node(node)) < 0)
|
||||
return r;
|
||||
|
||||
/* currently called cd9660node_rrip_init_links */
|
||||
r = cd9660_rrip_initialize_node(node, parent, grandparent);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/*
|
||||
* See if we need a CE record, and set all of the
|
||||
* associated counters.
|
||||
*
|
||||
* This should be called after all extensions. After
|
||||
* this is called, no new records should be added.
|
||||
*/
|
||||
if ((r = cd9660_susp_handle_continuation(node)) < 0)
|
||||
return r;
|
||||
|
||||
/* Recurse on children. */
|
||||
TAILQ_FOREACH(cn, &node->cn_children, cn_next_child) {
|
||||
if ((r = cd9660_susp_initialize(cn, node, parent)) < 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_susp_finalize(cd9660node *node)
|
||||
{
|
||||
cd9660node *temp;
|
||||
int r;
|
||||
|
||||
assert(node != NULL);
|
||||
|
||||
if (node == diskStructure.rootNode)
|
||||
diskStructure.susp_continuation_area_current_free = 0;
|
||||
|
||||
if ((r = cd9660_susp_finalize_node(node)) < 0)
|
||||
return r;
|
||||
if ((r = cd9660_rrip_finalize_node(node)) < 0)
|
||||
return r;
|
||||
|
||||
TAILQ_FOREACH(temp, &node->cn_children, cn_next_child) {
|
||||
if ((r = cd9660_susp_finalize(temp)) < 0)
|
||||
return r;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we really wanted to speed things up, we could have some sort of
|
||||
* lookup table on the SUSP entry type that calls a functor. Or, we could
|
||||
* combine the functions. These functions are kept separate to allow
|
||||
* easier addition of other extensions.
|
||||
|
||||
* For the sake of simplicity and clarity, we won't be doing that for now.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SUSP needs to update the following types:
|
||||
* CE (continuation area)
|
||||
*/
|
||||
int
|
||||
cd9660_susp_finalize_node(cd9660node *node)
|
||||
{
|
||||
struct ISO_SUSP_ATTRIBUTES *t;
|
||||
|
||||
/* Handle CE counters */
|
||||
if (node->susp_entry_ce_length > 0) {
|
||||
node->susp_entry_ce_start =
|
||||
diskStructure.susp_continuation_area_current_free;
|
||||
diskStructure.susp_continuation_area_current_free +=
|
||||
node->susp_entry_ce_length;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(t, &node->head, rr_ll) {
|
||||
if (t->susp_type != SUSP_TYPE_SUSP ||
|
||||
t->entry_type != SUSP_ENTRY_SUSP_CE)
|
||||
continue;
|
||||
cd9660_bothendian_dword(
|
||||
diskStructure.
|
||||
susp_continuation_area_start_sector,
|
||||
t->attr.su_entry.CE.ca_sector);
|
||||
|
||||
cd9660_bothendian_dword(
|
||||
diskStructure.
|
||||
susp_continuation_area_start_sector,
|
||||
t->attr.su_entry.CE.ca_sector);
|
||||
cd9660_bothendian_dword(node->susp_entry_ce_start,
|
||||
t->attr.su_entry.CE.offset);
|
||||
cd9660_bothendian_dword(node->susp_entry_ce_length,
|
||||
t->attr.su_entry.CE.length);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_rrip_finalize_node(cd9660node *node)
|
||||
{
|
||||
struct ISO_SUSP_ATTRIBUTES *t;
|
||||
|
||||
TAILQ_FOREACH(t, &node->head, rr_ll) {
|
||||
if (t->susp_type != SUSP_TYPE_RRIP)
|
||||
continue;
|
||||
switch (t->entry_type) {
|
||||
case SUSP_ENTRY_RRIP_CL:
|
||||
/* Look at rr_relocated*/
|
||||
if (node->rr_relocated == NULL)
|
||||
return -1;
|
||||
cd9660_bothendian_dword(
|
||||
node->rr_relocated->fileDataSector,
|
||||
(unsigned char *)
|
||||
t->attr.rr_entry.CL.dir_loc);
|
||||
break;
|
||||
case SUSP_ENTRY_RRIP_PL:
|
||||
/* Look at rr_real_parent */
|
||||
if (node->rr_real_parent == NULL)
|
||||
return -1;
|
||||
cd9660_bothendian_dword(
|
||||
node->rr_real_parent->fileDataSector,
|
||||
(unsigned char *)
|
||||
t->attr.rr_entry.PL.dir_loc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cd9660_susp_handle_continuation_common(cd9660node *node, int space)
|
||||
{
|
||||
int ca_used, susp_used, susp_used_pre_ce, working;
|
||||
struct ISO_SUSP_ATTRIBUTES *temp, *pre_ce, *last, *CE, *ST;
|
||||
|
||||
pre_ce = last = NULL;
|
||||
working = 254 - space;
|
||||
if (node->su_tail_size > 0)
|
||||
/* Allow 4 bytes for "ST" record. */
|
||||
working -= node->su_tail_size + 4;
|
||||
/* printf("There are %i bytes to work with\n",working); */
|
||||
|
||||
susp_used_pre_ce = susp_used = 0;
|
||||
ca_used = 0;
|
||||
TAILQ_FOREACH(temp, &node->head, rr_ll) {
|
||||
if (working < 0)
|
||||
break;
|
||||
/*
|
||||
* printf("SUSP Entry found, length is %i\n",
|
||||
* CD9660_SUSP_ENTRY_SIZE(temp));
|
||||
*/
|
||||
working -= CD9660_SUSP_ENTRY_SIZE(temp);
|
||||
if (working >= 0) {
|
||||
last = temp;
|
||||
susp_used += CD9660_SUSP_ENTRY_SIZE(temp);
|
||||
}
|
||||
if (working >= 28) {
|
||||
/*
|
||||
* Remember the last entry after which we
|
||||
* could insert a "CE" entry.
|
||||
*/
|
||||
pre_ce = last;
|
||||
susp_used_pre_ce = susp_used;
|
||||
}
|
||||
}
|
||||
|
||||
/* A CE entry is needed */
|
||||
if (working <= 0) {
|
||||
CE = cd9660node_susp_create_node(SUSP_TYPE_SUSP,
|
||||
SUSP_ENTRY_SUSP_CE, "CE", SUSP_LOC_ENTRY);
|
||||
cd9660_susp_ce(CE, node);
|
||||
/* This will automatically insert at the appropriate location */
|
||||
if (pre_ce != NULL)
|
||||
TAILQ_INSERT_AFTER(&node->head, pre_ce, CE, rr_ll);
|
||||
else
|
||||
TAILQ_INSERT_HEAD(&node->head, CE, rr_ll);
|
||||
last = CE;
|
||||
susp_used = susp_used_pre_ce + 28;
|
||||
/* Count how much CA data is necessary */
|
||||
for (temp = TAILQ_NEXT(last, rr_ll); temp != NULL;
|
||||
temp = TAILQ_NEXT(temp, rr_ll)) {
|
||||
ca_used += CD9660_SUSP_ENTRY_SIZE(temp);
|
||||
}
|
||||
}
|
||||
|
||||
/* An ST entry is needed */
|
||||
if (node->su_tail_size > 0) {
|
||||
ST = cd9660node_susp_create_node(SUSP_TYPE_SUSP,
|
||||
SUSP_ENTRY_SUSP_ST, "ST", SUSP_LOC_ENTRY);
|
||||
cd9660_susp_st(ST, node);
|
||||
if (last != NULL)
|
||||
TAILQ_INSERT_AFTER(&node->head, last, ST, rr_ll);
|
||||
else
|
||||
TAILQ_INSERT_HEAD(&node->head, ST, rr_ll);
|
||||
last = ST;
|
||||
susp_used += 4;
|
||||
}
|
||||
if (last != NULL)
|
||||
last->last_in_suf = 1;
|
||||
|
||||
node->susp_entry_size = susp_used;
|
||||
node->susp_entry_ce_length = ca_used;
|
||||
|
||||
diskStructure.susp_continuation_area_size += ca_used;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* See if a continuation entry is needed for each of the different types */
|
||||
static int
|
||||
cd9660_susp_handle_continuation(cd9660node *node)
|
||||
{
|
||||
assert (node != NULL);
|
||||
|
||||
/* Entry */
|
||||
if (cd9660_susp_handle_continuation_common(
|
||||
node,(int)(node->isoDirRecord->length[0])) < 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_susp_initialize_node(cd9660node *node)
|
||||
{
|
||||
struct ISO_SUSP_ATTRIBUTES *temp;
|
||||
|
||||
/*
|
||||
* Requirements/notes:
|
||||
* CE: is added for us where needed
|
||||
* ST: not sure if it is even required, but if so, should be
|
||||
* handled by the CE code
|
||||
* PD: isnt needed (though might be added for testing)
|
||||
* SP: is stored ONLY on the . record of the root directory
|
||||
* ES: not sure
|
||||
*/
|
||||
|
||||
/* Check for root directory, add SP and ER if needed. */
|
||||
if (node->type & CD9660_TYPE_DOT) {
|
||||
if (node->parent == diskStructure.rootNode) {
|
||||
temp = cd9660node_susp_create_node(SUSP_TYPE_SUSP,
|
||||
SUSP_ENTRY_SUSP_SP, "SP", SUSP_LOC_DOT);
|
||||
cd9660_susp_sp(temp, node);
|
||||
|
||||
/* Should be first entry. */
|
||||
TAILQ_INSERT_HEAD(&node->head, temp, rr_ll);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
cd9660_rrip_initialize_inode(cd9660node *node)
|
||||
{
|
||||
struct ISO_SUSP_ATTRIBUTES *attr;
|
||||
|
||||
/*
|
||||
* Inode dependent values - this may change,
|
||||
* but for now virtual files and directories do
|
||||
* not have an inode structure
|
||||
*/
|
||||
|
||||
if ((node->node != NULL) && (node->node->inode != NULL)) {
|
||||
/* PX - POSIX attributes */
|
||||
attr = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
|
||||
SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY);
|
||||
cd9660node_rrip_px(attr, node->node);
|
||||
|
||||
TAILQ_INSERT_TAIL(&node->head, attr, rr_ll);
|
||||
|
||||
/* TF - timestamp */
|
||||
attr = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
|
||||
SUSP_ENTRY_RRIP_TF, "TF", SUSP_LOC_ENTRY);
|
||||
cd9660node_rrip_tf(attr, node->node);
|
||||
TAILQ_INSERT_TAIL(&node->head, attr, rr_ll);
|
||||
|
||||
/* SL - Symbolic link */
|
||||
/* ?????????? Dan - why is this here? */
|
||||
if (TAILQ_EMPTY(&node->cn_children) &&
|
||||
node->node->inode != NULL &&
|
||||
S_ISLNK(node->node->inode->st.st_mode))
|
||||
cd9660_createSL(node);
|
||||
|
||||
/* PN - device number */
|
||||
if (node->node->inode != NULL &&
|
||||
((S_ISCHR(node->node->inode->st.st_mode) ||
|
||||
S_ISBLK(node->node->inode->st.st_mode)))) {
|
||||
attr =
|
||||
cd9660node_susp_create_node(SUSP_TYPE_RRIP,
|
||||
SUSP_ENTRY_RRIP_PN, "PN",
|
||||
SUSP_LOC_ENTRY);
|
||||
cd9660node_rrip_pn(attr, node->node);
|
||||
TAILQ_INSERT_TAIL(&node->head, attr, rr_ll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_rrip_initialize_node(cd9660node *node, cd9660node *parent,
|
||||
cd9660node *grandparent)
|
||||
{
|
||||
struct ISO_SUSP_ATTRIBUTES *current = NULL;
|
||||
|
||||
assert(node != NULL);
|
||||
|
||||
if (node->type & CD9660_TYPE_DOT) {
|
||||
/*
|
||||
* Handle ER - should be the only entry to appear on
|
||||
* a "." record
|
||||
*/
|
||||
if (node->parent == diskStructure.rootNode) {
|
||||
cd9660_susp_ER(node, 1, SUSP_RRIP_ER_EXT_ID,
|
||||
SUSP_RRIP_ER_EXT_DES, SUSP_RRIP_ER_EXT_SRC);
|
||||
}
|
||||
if (parent != NULL && parent->node != NULL &&
|
||||
parent->node->inode != NULL) {
|
||||
/* PX - POSIX attributes */
|
||||
current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
|
||||
SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY);
|
||||
cd9660node_rrip_px(current, parent->node);
|
||||
TAILQ_INSERT_TAIL(&node->head, current, rr_ll);
|
||||
}
|
||||
} else if (node->type & CD9660_TYPE_DOTDOT) {
|
||||
if (grandparent != NULL && grandparent->node != NULL &&
|
||||
grandparent->node->inode != NULL) {
|
||||
/* PX - POSIX attributes */
|
||||
current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
|
||||
SUSP_ENTRY_RRIP_PX, "PX", SUSP_LOC_ENTRY);
|
||||
cd9660node_rrip_px(current, grandparent->node);
|
||||
TAILQ_INSERT_TAIL(&node->head, current, rr_ll);
|
||||
}
|
||||
} else {
|
||||
cd9660_rrip_initialize_inode(node);
|
||||
|
||||
/*
|
||||
* Not every node needs a NM set - only if the name is
|
||||
* actually different. IE: If a file is TEST -> TEST,
|
||||
* no NM. test -> TEST, need a NM
|
||||
*
|
||||
* The rr_moved_dir needs to be assigned a NM record as well.
|
||||
*/
|
||||
if (node == diskStructure.rr_moved_dir) {
|
||||
cd9660_rrip_add_NM(node, RRIP_DEFAULT_MOVE_DIR_NAME);
|
||||
}
|
||||
else if ((node->node != NULL) &&
|
||||
((strlen(node->node->name) !=
|
||||
(int)node->isoDirRecord->name_len[0]) ||
|
||||
(memcmp(node->node->name,node->isoDirRecord->name,
|
||||
(int) node->isoDirRecord->name_len[0]) != 0))) {
|
||||
cd9660_rrip_NM(node);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Rock ridge directory relocation code here. */
|
||||
|
||||
/* First handle the CL for the placeholder file. */
|
||||
if (node->rr_relocated != NULL) {
|
||||
current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
|
||||
SUSP_ENTRY_RRIP_CL, "CL", SUSP_LOC_ENTRY);
|
||||
cd9660_rrip_CL(current, node);
|
||||
TAILQ_INSERT_TAIL(&node->head, current, rr_ll);
|
||||
}
|
||||
|
||||
/* Handle RE*/
|
||||
if (node->rr_real_parent != NULL) {
|
||||
current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
|
||||
SUSP_ENTRY_RRIP_RE, "RE", SUSP_LOC_ENTRY);
|
||||
cd9660_rrip_RE(current,node);
|
||||
TAILQ_INSERT_TAIL(&node->head, current, rr_ll);
|
||||
|
||||
/* Handle PL */
|
||||
current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
|
||||
SUSP_ENTRY_RRIP_PL, "PL", SUSP_LOC_DOTDOT);
|
||||
cd9660_rrip_PL(current,node->dot_dot_record);
|
||||
TAILQ_INSERT_TAIL(&node->dot_dot_record->head, current,
|
||||
rr_ll);
|
||||
TAILQ_INSERT_TAIL(&node->head, current, rr_ll);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct ISO_SUSP_ATTRIBUTES*
|
||||
cd9660node_susp_create_node(int susp_type, int entry_type, const char *type_id,
|
||||
int write_loc)
|
||||
{
|
||||
struct ISO_SUSP_ATTRIBUTES* temp;
|
||||
|
||||
if ((temp = malloc(sizeof(struct ISO_SUSP_ATTRIBUTES))) == NULL) {
|
||||
CD9660_MEM_ALLOC_ERROR("cd9660node_susp_create_node");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
temp->susp_type = susp_type;
|
||||
temp->entry_type = entry_type;
|
||||
temp->last_in_suf = 0;
|
||||
/* Phase this out */
|
||||
temp->type_of[0] = type_id[0];
|
||||
temp->type_of[1] = type_id[1];
|
||||
temp->write_location = write_loc;
|
||||
|
||||
/*
|
||||
* Since the first four bytes is common, lets go ahead and
|
||||
* set the type identifier, since we are passing that to this
|
||||
* function anyhow.
|
||||
*/
|
||||
temp->attr.su_entry.SP.h.type[0] = type_id[0];
|
||||
temp->attr.su_entry.SP.h.type[1] = type_id[1];
|
||||
return temp;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_rrip_PL(struct ISO_SUSP_ATTRIBUTES* p, cd9660node *node __unused)
|
||||
{
|
||||
p->attr.rr_entry.PL.h.length[0] = 12;
|
||||
p->attr.rr_entry.PL.h.version[0] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_rrip_CL(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *node __unused)
|
||||
{
|
||||
p->attr.rr_entry.CL.h.length[0] = 12;
|
||||
p->attr.rr_entry.CL.h.version[0] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_rrip_RE(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *node __unused)
|
||||
{
|
||||
p->attr.rr_entry.RE.h.length[0] = 0;
|
||||
p->attr.rr_entry.RE.h.version[0] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
cd9660_createSL(cd9660node *node)
|
||||
{
|
||||
struct ISO_SUSP_ATTRIBUTES* current;
|
||||
int path_count, dir_count, done, i, j, dir_copied;
|
||||
char temp_cr[255];
|
||||
char temp_sl[255]; /* used in copying continuation entry*/
|
||||
char* sl_ptr;
|
||||
|
||||
sl_ptr = node->node->symlink;
|
||||
|
||||
done = 0;
|
||||
path_count = 0;
|
||||
dir_count = 0;
|
||||
dir_copied = 0;
|
||||
current = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
|
||||
SUSP_ENTRY_RRIP_SL, "SL", SUSP_LOC_ENTRY);
|
||||
|
||||
current->attr.rr_entry.SL.h.version[0] = 1;
|
||||
current->attr.rr_entry.SL.flags[0] = SL_FLAGS_NONE;
|
||||
|
||||
if (*sl_ptr == '/') {
|
||||
temp_cr[0] = SL_FLAGS_ROOT;
|
||||
temp_cr[1] = 0;
|
||||
memcpy(current->attr.rr_entry.SL.component + path_count,
|
||||
temp_cr, 2);
|
||||
path_count += 2;
|
||||
sl_ptr++;
|
||||
}
|
||||
|
||||
for (i = 0; i < (dir_count + 2); i++)
|
||||
temp_cr[i] = '\0';
|
||||
|
||||
while (!done) {
|
||||
while ((*sl_ptr != '/') && (*sl_ptr != '\0')) {
|
||||
dir_copied = 1;
|
||||
if (*sl_ptr == '.') {
|
||||
if ((*(sl_ptr + 1) == '/') || (*(sl_ptr + 1)
|
||||
== '\0')) {
|
||||
temp_cr[0] = SL_FLAGS_CURRENT;
|
||||
sl_ptr++;
|
||||
} else if(*(sl_ptr + 1) == '.') {
|
||||
if ((*(sl_ptr + 2) == '/') ||
|
||||
(*(sl_ptr + 2) == '\0')) {
|
||||
temp_cr[0] = SL_FLAGS_PARENT;
|
||||
sl_ptr += 2;
|
||||
}
|
||||
} else {
|
||||
temp_cr[dir_count+2] = *sl_ptr;
|
||||
sl_ptr++;
|
||||
dir_count++;
|
||||
}
|
||||
} else {
|
||||
temp_cr[dir_count + 2] = *sl_ptr;
|
||||
sl_ptr++;
|
||||
dir_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((path_count + dir_count) >= 249) {
|
||||
current->attr.rr_entry.SL.flags[0] |= SL_FLAGS_CONTINUE;
|
||||
|
||||
j = 0;
|
||||
|
||||
if (path_count <= 249) {
|
||||
while(j != (249 - path_count)) {
|
||||
temp_sl[j] = temp_cr[j];
|
||||
j++;
|
||||
}
|
||||
temp_sl[0] = SL_FLAGS_CONTINUE;
|
||||
temp_sl[1] = j - 2;
|
||||
memcpy(
|
||||
current->attr.rr_entry.SL.component +
|
||||
path_count,
|
||||
temp_sl, j);
|
||||
}
|
||||
|
||||
path_count += j;
|
||||
current->attr.rr_entry.SL.h.length[0] = path_count + 5;
|
||||
TAILQ_INSERT_TAIL(&node->head, current, rr_ll);
|
||||
current= cd9660node_susp_create_node(SUSP_TYPE_RRIP,
|
||||
SUSP_ENTRY_RRIP_SL, "SL", SUSP_LOC_ENTRY);
|
||||
current->attr.rr_entry.SL.h.version[0] = 1;
|
||||
current->attr.rr_entry.SL.flags[0] = SL_FLAGS_NONE;
|
||||
|
||||
path_count = 0;
|
||||
|
||||
if (dir_count > 2) {
|
||||
while (j != dir_count + 2) {
|
||||
current->attr.rr_entry.SL.component[
|
||||
path_count + 2] = temp_cr[j];
|
||||
j++;
|
||||
path_count++;
|
||||
}
|
||||
current->attr.rr_entry.SL.component[1]
|
||||
= path_count;
|
||||
path_count+= 2;
|
||||
} else {
|
||||
while(j != dir_count) {
|
||||
current->attr.rr_entry.SL.component[
|
||||
path_count+2] = temp_cr[j];
|
||||
j++;
|
||||
path_count++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (dir_copied == 1) {
|
||||
temp_cr[1] = dir_count;
|
||||
memcpy(current->attr.rr_entry.SL.component +
|
||||
path_count,
|
||||
temp_cr, dir_count + 2);
|
||||
path_count += dir_count + 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (*sl_ptr == '\0') {
|
||||
done = 1;
|
||||
current->attr.rr_entry.SL.h.length[0] = path_count + 5;
|
||||
TAILQ_INSERT_TAIL(&node->head, current, rr_ll);
|
||||
} else {
|
||||
sl_ptr++;
|
||||
dir_count = 0;
|
||||
dir_copied = 0;
|
||||
for(i = 0; i < 255; i++) {
|
||||
temp_cr[i] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
cd9660node_rrip_px(struct ISO_SUSP_ATTRIBUTES *v, fsnode *pxinfo)
|
||||
{
|
||||
v->attr.rr_entry.PX.h.length[0] = 36;
|
||||
v->attr.rr_entry.PX.h.version[0] = 1;
|
||||
cd9660_bothendian_dword(pxinfo->inode->st.st_mode,
|
||||
v->attr.rr_entry.PX.mode);
|
||||
cd9660_bothendian_dword(pxinfo->inode->st.st_nlink,
|
||||
v->attr.rr_entry.PX.links);
|
||||
cd9660_bothendian_dword(pxinfo->inode->st.st_uid,
|
||||
v->attr.rr_entry.PX.uid);
|
||||
cd9660_bothendian_dword(pxinfo->inode->st.st_gid,
|
||||
v->attr.rr_entry.PX.gid);
|
||||
|
||||
/* Ignoring the serial number for now */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660node_rrip_pn(struct ISO_SUSP_ATTRIBUTES *pn_field, fsnode *fnode)
|
||||
{
|
||||
pn_field->attr.rr_entry.PN.h.length[0] = 20;
|
||||
pn_field->attr.rr_entry.PN.h.version[0] = 1;
|
||||
|
||||
if (sizeof (fnode->inode->st.st_dev) > 32)
|
||||
cd9660_bothendian_dword((uint64_t)fnode->inode->st.st_dev >> 32,
|
||||
pn_field->attr.rr_entry.PN.high);
|
||||
else
|
||||
cd9660_bothendian_dword(0, pn_field->attr.rr_entry.PN.high);
|
||||
|
||||
cd9660_bothendian_dword(fnode->inode->st.st_dev & 0xffffffff,
|
||||
pn_field->attr.rr_entry.PN.low);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int
|
||||
cd9660node_rrip_nm(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *file_node)
|
||||
{
|
||||
int nm_length = strlen(file_node->isoDirRecord->name) + 5;
|
||||
p->attr.rr_entry.NM.h.type[0] = 'N';
|
||||
p->attr.rr_entry.NM.h.type[1] = 'M';
|
||||
sprintf(p->attr.rr_entry.NM.altname, "%s", file_node->isoDirRecord->name);
|
||||
p->attr.rr_entry.NM.h.length[0] = (unsigned char)nm_length;
|
||||
p->attr.rr_entry.NM.h.version[0] = (unsigned char)1;
|
||||
p->attr.rr_entry.NM.flags[0] = (unsigned char) NM_PARENT;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
cd9660node_rrip_tf(struct ISO_SUSP_ATTRIBUTES *p, fsnode *_node)
|
||||
{
|
||||
p->attr.rr_entry.TF.flags[0] = TF_MODIFY | TF_ACCESS | TF_ATTRIBUTES;
|
||||
p->attr.rr_entry.TF.h.length[0] = 4;
|
||||
p->attr.rr_entry.TF.h.version[0] = 1;
|
||||
|
||||
/*
|
||||
* Need to add creation time, backup time,
|
||||
* expiration time, and effective time.
|
||||
*/
|
||||
|
||||
cd9660_time_915(p->attr.rr_entry.TF.timestamp,
|
||||
_node->inode->st.st_atime);
|
||||
p->attr.rr_entry.TF.h.length[0] += 7;
|
||||
|
||||
cd9660_time_915(p->attr.rr_entry.TF.timestamp + 7,
|
||||
_node->inode->st.st_mtime);
|
||||
p->attr.rr_entry.TF.h.length[0] += 7;
|
||||
|
||||
cd9660_time_915(p->attr.rr_entry.TF.timestamp + 14,
|
||||
_node->inode->st.st_ctime);
|
||||
p->attr.rr_entry.TF.h.length[0] += 7;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_susp_sp(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *spinfo __unused)
|
||||
{
|
||||
p->attr.su_entry.SP.h.length[0] = 7;
|
||||
p->attr.su_entry.SP.h.version[0] = 1;
|
||||
p->attr.su_entry.SP.check[0] = 0xBE;
|
||||
p->attr.su_entry.SP.check[1] = 0xEF;
|
||||
p->attr.su_entry.SP.len_skp[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_susp_st(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *stinfo __unused)
|
||||
{
|
||||
p->attr.su_entry.ST.h.type[0] = 'S';
|
||||
p->attr.su_entry.ST.h.type[1] = 'T';
|
||||
p->attr.su_entry.ST.h.length[0] = 4;
|
||||
p->attr.su_entry.ST.h.version[0] = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_susp_ce(struct ISO_SUSP_ATTRIBUTES *p, cd9660node *spinfo __unused)
|
||||
{
|
||||
p->attr.su_entry.CE.h.length[0] = 28;
|
||||
p->attr.su_entry.CE.h.version[0] = 1;
|
||||
/* Other attributes dont matter right now, will be updated later */
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
cd9660_susp_pd(struct ISO_SUSP_ATTRIBUTES *p __unused, int length __unused)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
cd9660_rrip_add_NM(cd9660node *node, const char *name)
|
||||
{
|
||||
int working,len;
|
||||
const char *p;
|
||||
struct ISO_SUSP_ATTRIBUTES *r;
|
||||
|
||||
/*
|
||||
* Each NM record has 254 byes to work with. This means that
|
||||
* the name data itself only has 249 bytes to work with. So, a
|
||||
* name with 251 characters would require two nm records.
|
||||
*/
|
||||
p = name;
|
||||
working = 1;
|
||||
while (working) {
|
||||
r = cd9660node_susp_create_node(SUSP_TYPE_RRIP,
|
||||
SUSP_ENTRY_RRIP_NM, "NM", SUSP_LOC_ENTRY);
|
||||
r->attr.rr_entry.NM.h.version[0] = 1;
|
||||
r->attr.rr_entry.NM.flags[0] = RRIP_NM_FLAGS_NONE;
|
||||
len = strlen(p);
|
||||
|
||||
if (len > 249) {
|
||||
len = 249;
|
||||
r->attr.rr_entry.NM.flags[0] = RRIP_NM_FLAGS_CONTINUE;
|
||||
} else {
|
||||
working = 0;
|
||||
}
|
||||
memcpy(r->attr.rr_entry.NM.altname, p, len);
|
||||
r->attr.rr_entry.NM.h.length[0] = 5 + len;
|
||||
|
||||
TAILQ_INSERT_TAIL(&node->head, r, rr_ll);
|
||||
|
||||
p += len;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cd9660_rrip_NM(cd9660node *node)
|
||||
{
|
||||
cd9660_rrip_add_NM(node, node->node->name);
|
||||
}
|
||||
|
||||
struct ISO_SUSP_ATTRIBUTES*
|
||||
cd9660_susp_ER(cd9660node *node,
|
||||
u_char ext_version, const char* ext_id, const char* ext_des,
|
||||
const char* ext_src)
|
||||
{
|
||||
int l;
|
||||
struct ISO_SUSP_ATTRIBUTES *r;
|
||||
|
||||
r = cd9660node_susp_create_node(SUSP_TYPE_SUSP,
|
||||
SUSP_ENTRY_SUSP_ER, "ER", SUSP_LOC_DOT);
|
||||
|
||||
/* Fixed data is 8 bytes */
|
||||
r->attr.su_entry.ER.h.length[0] = 8;
|
||||
r->attr.su_entry.ER.h.version[0] = 1;
|
||||
|
||||
r->attr.su_entry.ER.len_id[0] = (u_char)strlen(ext_id);
|
||||
r->attr.su_entry.ER.len_des[0] = (u_char)strlen(ext_des);
|
||||
r->attr.su_entry.ER.len_src[0] = (u_char)strlen(ext_src);
|
||||
|
||||
l = r->attr.su_entry.ER.len_id[0] +
|
||||
r->attr.su_entry.ER.len_src[0] +
|
||||
r->attr.su_entry.ER.len_des[0];
|
||||
|
||||
/* Everything must fit. */
|
||||
assert(l + r->attr.su_entry.ER.h.length[0] <= 254);
|
||||
|
||||
r->attr.su_entry.ER.h.length[0] += (u_char)l;
|
||||
|
||||
|
||||
r->attr.su_entry.ER.ext_ver[0] = ext_version;
|
||||
memcpy(r->attr.su_entry.ER.ext_data, ext_id,
|
||||
(int)r->attr.su_entry.ER.len_id[0]);
|
||||
l = (int) r->attr.su_entry.ER.len_id[0];
|
||||
memcpy(r->attr.su_entry.ER.ext_data + l,ext_des,
|
||||
(int)r->attr.su_entry.ER.len_des[0]);
|
||||
|
||||
l += (int)r->attr.su_entry.ER.len_des[0];
|
||||
memcpy(r->attr.su_entry.ER.ext_data + l,ext_src,
|
||||
(int)r->attr.su_entry.ER.len_src[0]);
|
||||
|
||||
TAILQ_INSERT_TAIL(&node->head, r, rr_ll);
|
||||
return r;
|
||||
}
|
||||
|
||||
struct ISO_SUSP_ATTRIBUTES*
|
||||
cd9660_susp_ES(struct ISO_SUSP_ATTRIBUTES *last __unused, cd9660node *node __unused)
|
||||
{
|
||||
return NULL;
|
||||
}
|
290
usr.sbin/makefs/cd9660/iso9660_rrip.h
Normal file
290
usr.sbin/makefs/cd9660/iso9660_rrip.h
Normal file
@ -0,0 +1,290 @@
|
||||
/* $NetBSD: iso9660_rrip.h,v 1.5 2009/01/10 22:06:29 bjh21 Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2005 Daniel Watt, Walter Deignan, Ryan Gabrys, Alan
|
||||
* Perez-Rathke and Ram Vedam. All rights reserved.
|
||||
*
|
||||
* This code was written by Daniel Watt, Walter Deignan, Ryan Gabrys,
|
||||
* Alan Perez-Rathke and Ram Vedam.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL DANIEL WATT, WALTER DEIGNAN, RYAN
|
||||
* GABRYS, ALAN PEREZ-RATHKE AND RAM VEDAM BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE,DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#ifndef __ISO9660_RRIP_H__
|
||||
#define __ISO9660_RRIP_H__
|
||||
|
||||
/*
|
||||
* This will hold all the functions needed to
|
||||
* write an ISO 9660 image with Rock Ridge Extensions
|
||||
*/
|
||||
|
||||
/* For writing must use ISO_RRIP_EXTREF structure */
|
||||
|
||||
#include "makefs.h"
|
||||
#include <cd9660_rrip.h>
|
||||
#include "cd9660.h"
|
||||
#include <sys/queue.h>
|
||||
|
||||
#define PX_LENGTH 0x2C
|
||||
#define PN_LENGTH 0x14
|
||||
#define TF_CREATION 0x00
|
||||
#define TF_MODIFY 0x01
|
||||
#define TF_ACCESS 0x02
|
||||
#define TF_ATTRIBUTES 0x04
|
||||
#define TF_BACKUP 0x08
|
||||
#define TF_EXPIRATION 0x10
|
||||
#define TF_EFFECTIVE 0x20
|
||||
#define TF_LONGFORM 0x40
|
||||
#define NM_CONTINUE 0x80
|
||||
#define NM_CURRENT 0x100
|
||||
#define NM_PARENT 0x200
|
||||
|
||||
|
||||
#define SUSP_LOC_ENTRY 0x01
|
||||
#define SUSP_LOC_DOT 0x02
|
||||
#define SUSP_LOC_DOTDOT 0x04
|
||||
|
||||
#define SUSP_TYPE_SUSP 1
|
||||
#define SUSP_TYPE_RRIP 2
|
||||
|
||||
#define SUSP_ENTRY_SUSP_CE 1
|
||||
#define SUSP_ENTRY_SUSP_PD 2
|
||||
#define SUSP_ENTRY_SUSP_SP 3
|
||||
#define SUSP_ENTRY_SUSP_ST 4
|
||||
#define SUSP_ENTRY_SUSP_ER 5
|
||||
#define SUSP_ENTRY_SUSP_ES 6
|
||||
|
||||
#define SUSP_ENTRY_RRIP_PX 1
|
||||
#define SUSP_ENTRY_RRIP_PN 2
|
||||
#define SUSP_ENTRY_RRIP_SL 3
|
||||
#define SUSP_ENTRY_RRIP_NM 4
|
||||
#define SUSP_ENTRY_RRIP_CL 5
|
||||
#define SUSP_ENTRY_RRIP_PL 6
|
||||
#define SUSP_ENTRY_RRIP_RE 7
|
||||
#define SUSP_ENTRY_RRIP_TF 8
|
||||
#define SUSP_ENTRY_RRIP_SF 9
|
||||
|
||||
#define SUSP_RRIP_ER_EXT_ID "IEEE_P1282"
|
||||
#define SUSP_RRIP_ER_EXT_DES "THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS."
|
||||
#define SUSP_RRIP_ER_EXT_SRC "PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION."
|
||||
|
||||
#define SL_FLAGS_NONE 0
|
||||
#define SL_FLAGS_CONTINUE 1
|
||||
#define SL_FLAGS_CURRENT 2
|
||||
#define SL_FLAGS_PARENT 4
|
||||
#define SL_FLAGS_ROOT 8
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
u_char mode [ISODCL(5,12)];
|
||||
u_char links [ISODCL(13,20)];
|
||||
u_char uid [ISODCL(21,28)];
|
||||
u_char gid [ISODCL(29,36)];
|
||||
u_char serial [ISODCL(37,44)];/* Not used */
|
||||
} ISO_RRIP_PX;
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
u_char high [ISODCL(5,12)];
|
||||
u_char low [ISODCL(13,20)];
|
||||
} ISO_RRIP_PN;
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
u_char flags [ISODCL ( 4, 4)];
|
||||
u_char component [ISODCL ( 4, 256)];
|
||||
u_int nBytes;
|
||||
} ISO_RRIP_SL;
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
u_char flags [ISODCL ( 4, 4)];
|
||||
u_char timestamp [ISODCL ( 5, 256)];
|
||||
} ISO_RRIP_TF;
|
||||
|
||||
#define RRIP_NM_FLAGS_NONE 0x00
|
||||
#define RRIP_NM_FLAGS_CONTINUE 0x01
|
||||
#define RRIP_NM_FLAGS_CURRENT 0x02
|
||||
#define RRIP_NM_FLAGS_PARENT 0x04
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
u_char flags [ISODCL ( 4, 4)];
|
||||
u_char altname [ISODCL ( 4, 256)];
|
||||
} ISO_RRIP_NM;
|
||||
|
||||
/* Note that this is the same structure as cd9660_rrip.h : ISO_RRIP_CONT */
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
u_char ca_sector [ISODCL ( 5, 12)];
|
||||
u_char offset [ISODCL ( 13, 20)];
|
||||
u_char length [ISODCL ( 21, 28)];
|
||||
} ISO_SUSP_CE;
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
u_char padding_area [ISODCL ( 4, 256)];
|
||||
} ISO_SUSP_PD;
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
u_char check [ISODCL ( 4, 5)];
|
||||
u_char len_skp [ISODCL ( 6, 6)];
|
||||
} ISO_SUSP_SP;
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
} ISO_SUSP_ST;
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
u_char len_id [ISODCL ( 4, 4)];
|
||||
u_char len_des [ISODCL ( 5, 5)];
|
||||
u_char len_src [ISODCL ( 6, 6)];
|
||||
u_char ext_ver [ISODCL ( 7, 7)];
|
||||
u_char ext_data [ISODCL (8,256)];
|
||||
/* u_char ext_id [ISODCL ( 8, 256)];
|
||||
u_char ext_des [ISODCL ( 257, 513)];
|
||||
u_char ext_src [ISODCL ( 514, 770)];*/
|
||||
} ISO_SUSP_ER;
|
||||
|
||||
typedef struct {
|
||||
ISO_SUSP_HEADER h;
|
||||
u_char ext_seq [ISODCL ( 4, 4)];
|
||||
} ISO_SUSP_ES;
|
||||
|
||||
typedef union {
|
||||
ISO_RRIP_PX PX;
|
||||
ISO_RRIP_PN PN;
|
||||
ISO_RRIP_SL SL;
|
||||
ISO_RRIP_NM NM;
|
||||
ISO_RRIP_CLINK CL;
|
||||
ISO_RRIP_PLINK PL;
|
||||
ISO_RRIP_RELDIR RE;
|
||||
ISO_RRIP_TF TF;
|
||||
} rrip_entry;
|
||||
|
||||
typedef union {
|
||||
ISO_SUSP_CE CE;
|
||||
ISO_SUSP_PD PD;
|
||||
ISO_SUSP_SP SP;
|
||||
ISO_SUSP_ST ST;
|
||||
ISO_SUSP_ER ER;
|
||||
ISO_SUSP_ES ES;
|
||||
} susp_entry;
|
||||
|
||||
typedef union {
|
||||
susp_entry su_entry;
|
||||
rrip_entry rr_entry;
|
||||
} SUSP_ENTRIES;
|
||||
|
||||
struct ISO_SUSP_ATTRIBUTES {
|
||||
SUSP_ENTRIES attr;
|
||||
int type;
|
||||
char type_of[2];
|
||||
char last_in_suf; /* last entry in the System Use Field? */
|
||||
/* Dan's addons - will merge later. This allows use of a switch */
|
||||
char susp_type; /* SUSP or RRIP */
|
||||
char entry_type; /* Record type */
|
||||
char write_location;
|
||||
TAILQ_ENTRY(ISO_SUSP_ATTRIBUTES) rr_ll;
|
||||
};
|
||||
|
||||
#define CD9660_SUSP_ENTRY_SIZE(entry)\
|
||||
((int) ((entry)->attr.su_entry.SP.h.length[0]))
|
||||
|
||||
/* Recursive function - move later to func pointer code*/
|
||||
int cd9660_susp_finalize(cd9660node *);
|
||||
|
||||
/* These two operate on single nodes */
|
||||
int cd9660_susp_finalize_node(cd9660node *);
|
||||
int cd9660_rrip_finalize_node(cd9660node *);
|
||||
|
||||
/* POSIX File attribute */
|
||||
int cd9660node_rrip_px(struct ISO_SUSP_ATTRIBUTES *, fsnode *);
|
||||
|
||||
/* Device number */
|
||||
int cd9660node_rrip_pn(struct ISO_SUSP_ATTRIBUTES *, fsnode *);
|
||||
|
||||
/* Symbolic link */
|
||||
int cd9660node_rrip_SL(struct ISO_SUSP_ATTRIBUTES *, fsnode *);
|
||||
|
||||
/* Alternate Name function */
|
||||
void cd9660_rrip_NM(cd9660node *);
|
||||
void cd9660_rrip_add_NM(cd9660node *,const char *);
|
||||
|
||||
/* Parent and child link function */
|
||||
int cd9660_rrip_PL(struct ISO_SUSP_ATTRIBUTES *, cd9660node *);
|
||||
int cd9660_rrip_CL(struct ISO_SUSP_ATTRIBUTES *, cd9660node *);
|
||||
int cd9660_rrip_RE(struct ISO_SUSP_ATTRIBUTES *, cd9660node *);
|
||||
|
||||
int cd9660node_rrip_tf(struct ISO_SUSP_ATTRIBUTES *, fsnode *);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Relocation directory function. I'm not quite sure what
|
||||
* sort of parameters are needed, but personally I don't think
|
||||
* any parameters are needed except for the memory address where
|
||||
* the information needs to be put in
|
||||
*/
|
||||
int cd9660node_rrip_re(void *, fsnode *);
|
||||
|
||||
/*
|
||||
* Don't know if this function is needed because it apparently is an
|
||||
* optional feature that does not really need to be implemented but I
|
||||
* thought I should add it anyway.
|
||||
*/
|
||||
int cd9660_susp_ce (struct ISO_SUSP_ATTRIBUTES *, cd9660node *);
|
||||
int cd9660_susp_pd (struct ISO_SUSP_ATTRIBUTES *, int);
|
||||
int cd9660_susp_sp (struct ISO_SUSP_ATTRIBUTES *, cd9660node *);
|
||||
int cd9660_susp_st (struct ISO_SUSP_ATTRIBUTES *, cd9660node *);
|
||||
|
||||
struct ISO_SUSP_ATTRIBUTES *cd9660_susp_ER(cd9660node *, u_char, const char *,
|
||||
const char *, const char *);
|
||||
struct ISO_SUSP_ATTRIBUTES *cd9660_susp_ES(struct ISO_SUSP_ATTRIBUTES*,
|
||||
cd9660node *);
|
||||
|
||||
|
||||
/* Helper functions */
|
||||
|
||||
/* Common SUSP/RRIP functions */
|
||||
int cd9660_susp_initialize(cd9660node *, cd9660node *, cd9660node *);
|
||||
int cd9660_susp_initialize_node(cd9660node *);
|
||||
struct ISO_SUSP_ATTRIBUTES *cd9660node_susp_create_node(int, int, const char *,
|
||||
int);
|
||||
struct ISO_SUSP_ATTRIBUTES *cd9660node_susp_add_entry(cd9660node *,
|
||||
struct ISO_SUSP_ATTRIBUTES *, struct ISO_SUSP_ATTRIBUTES *, int);
|
||||
|
||||
/* RRIP specific functions */
|
||||
int cd9660_rrip_initialize_node(cd9660node *, cd9660node *, cd9660node *);
|
||||
void cd9660_createSL(cd9660node *);
|
||||
|
||||
/* Functions that probably can be removed */
|
||||
/* int cd9660node_initialize_node(int, char *); */
|
||||
|
||||
|
||||
#endif
|
8
usr.sbin/makefs/compat/Makefile.inc
Normal file
8
usr.sbin/makefs/compat/Makefile.inc
Normal file
@ -0,0 +1,8 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
.PATH: ${.CURDIR}/compat
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/compat
|
||||
|
||||
SRCS+= pwcache.c strsuftoll.c
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ffs.c,v 1.30 2004/06/24 22:30:13 lukem Exp $ */
|
||||
/* $NetBSD: ffs.c,v 1.44 2009/04/28 22:49:26 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
@ -76,17 +76,24 @@ __FBSDID("$FreeBSD$");
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "makefs.h"
|
||||
#include "ffs.h"
|
||||
|
||||
#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <ufs/ufs/dir.h>
|
||||
#include <ufs/ffs/fs.h>
|
||||
|
||||
|
||||
#include "ffs/ufs_bswap.h"
|
||||
#include "ffs/ufs_inode.h"
|
||||
#include "ffs/newfs_extern.h"
|
||||
@ -94,7 +101,7 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#undef DIP
|
||||
#define DIP(dp, field) \
|
||||
((fsopts->version == 1) ? \
|
||||
((ffs_opts->version == 1) ? \
|
||||
(dp)->ffs1_din.di_##field : (dp)->ffs2_din.di_##field)
|
||||
|
||||
/*
|
||||
@ -139,39 +146,71 @@ int sectorsize; /* XXX: for buf.c::getblk() */
|
||||
|
||||
/* publically visible functions */
|
||||
|
||||
void
|
||||
ffs_prep_opts(fsinfo_t *fsopts)
|
||||
{
|
||||
ffs_opt_t *ffs_opts;
|
||||
|
||||
if ((ffs_opts = calloc(1, sizeof(ffs_opt_t))) == NULL)
|
||||
err(1, "Allocating memory for ffs_options");
|
||||
|
||||
fsopts->fs_specific = ffs_opts;
|
||||
|
||||
ffs_opts->bsize= -1;
|
||||
ffs_opts->fsize= -1;
|
||||
ffs_opts->cpg= -1;
|
||||
ffs_opts->density= -1;
|
||||
ffs_opts->minfree= -1;
|
||||
ffs_opts->optimization= -1;
|
||||
ffs_opts->maxcontig= -1;
|
||||
ffs_opts->maxbpg= -1;
|
||||
ffs_opts->avgfilesize= -1;
|
||||
ffs_opts->avgfpdir= -1;
|
||||
ffs_opts->version = 1;
|
||||
}
|
||||
|
||||
void
|
||||
ffs_cleanup_opts(fsinfo_t *fsopts)
|
||||
{
|
||||
if (fsopts->fs_specific)
|
||||
free(fsopts->fs_specific);
|
||||
}
|
||||
|
||||
int
|
||||
ffs_parse_opts(const char *option, fsinfo_t *fsopts)
|
||||
{
|
||||
ffs_opt_t *ffs_opts = fsopts->fs_specific;
|
||||
|
||||
option_t ffs_options[] = {
|
||||
{ "bsize", &fsopts->bsize, 1, INT_MAX,
|
||||
{ "bsize", &ffs_opts->bsize, 1, INT_MAX,
|
||||
"block size" },
|
||||
{ "fsize", &fsopts->fsize, 1, INT_MAX,
|
||||
{ "fsize", &ffs_opts->fsize, 1, INT_MAX,
|
||||
"fragment size" },
|
||||
{ "density", &fsopts->density, 1, INT_MAX,
|
||||
{ "density", &ffs_opts->density, 1, INT_MAX,
|
||||
"bytes per inode" },
|
||||
{ "minfree", &fsopts->minfree, 0, 99,
|
||||
{ "minfree", &ffs_opts->minfree, 0, 99,
|
||||
"minfree" },
|
||||
{ "maxbpf", &fsopts->maxbpg, 1, INT_MAX,
|
||||
{ "maxbpf", &ffs_opts->maxbpg, 1, INT_MAX,
|
||||
"max blocks per file in a cg" },
|
||||
{ "avgfilesize", &fsopts->avgfilesize, 1, INT_MAX,
|
||||
{ "avgfilesize", &ffs_opts->avgfilesize,1, INT_MAX,
|
||||
"expected average file size" },
|
||||
{ "avgfpdir", &fsopts->avgfpdir, 1, INT_MAX,
|
||||
{ "avgfpdir", &ffs_opts->avgfpdir, 1, INT_MAX,
|
||||
"expected # of files per directory" },
|
||||
{ "extent", &fsopts->maxbsize, 1, INT_MAX,
|
||||
{ "extent", &ffs_opts->maxbsize, 1, INT_MAX,
|
||||
"maximum # extent size" },
|
||||
{ "maxbpcg", &fsopts->maxblkspercg, 1, INT_MAX,
|
||||
{ "maxbpcg", &ffs_opts->maxblkspercg,1, INT_MAX,
|
||||
"max # of blocks per group" },
|
||||
{ "version", &fsopts->version, 1, 2,
|
||||
{ "version", &ffs_opts->version, 1, 2,
|
||||
"UFS version" },
|
||||
{ NULL }
|
||||
{ .name = NULL }
|
||||
};
|
||||
|
||||
char *var, *val;
|
||||
int rv;
|
||||
|
||||
(void)&ffs_options;
|
||||
assert(option != NULL);
|
||||
assert(fsopts != NULL);
|
||||
assert(ffs_opts != NULL);
|
||||
|
||||
if (debug & DEBUG_FS_PARSE_OPTS)
|
||||
printf("ffs_parse_opts: got `%s'\n", option);
|
||||
@ -188,9 +227,9 @@ ffs_parse_opts(const char *option, fsinfo_t *fsopts)
|
||||
|
||||
if (strcmp(var, "optimization") == 0) {
|
||||
if (strcmp(val, "time") == 0) {
|
||||
fsopts->optimization = FS_OPTTIME;
|
||||
ffs_opts->optimization = FS_OPTTIME;
|
||||
} else if (strcmp(val, "space") == 0) {
|
||||
fsopts->optimization = FS_OPTSPACE;
|
||||
ffs_opts->optimization = FS_OPTSPACE;
|
||||
} else {
|
||||
warnx("Invalid optimization `%s'", val);
|
||||
goto leave_ffs_parse_opts;
|
||||
@ -277,11 +316,12 @@ ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
#if notyet
|
||||
int32_t spc, nspf, ncyl, fssize;
|
||||
#endif
|
||||
off_t size;
|
||||
ffs_opt_t *ffs_opts = fsopts->fs_specific;
|
||||
|
||||
assert(dir != NULL);
|
||||
assert(root != NULL);
|
||||
assert(fsopts != NULL);
|
||||
assert(ffs_opts != NULL);
|
||||
|
||||
if (debug & DEBUG_FS_VALIDATE) {
|
||||
printf("ffs_validate: before defaults set:\n");
|
||||
@ -291,31 +331,31 @@ ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
/* set FFS defaults */
|
||||
if (fsopts->sectorsize == -1)
|
||||
fsopts->sectorsize = DFL_SECSIZE;
|
||||
if (fsopts->fsize == -1)
|
||||
fsopts->fsize = MAX(DFL_FRAGSIZE, fsopts->sectorsize);
|
||||
if (fsopts->bsize == -1)
|
||||
fsopts->bsize = MIN(DFL_BLKSIZE, 8 * fsopts->fsize);
|
||||
if (fsopts->cpg == -1)
|
||||
fsopts->cpg = DFL_CYLSPERGROUP;
|
||||
if (ffs_opts->fsize == -1)
|
||||
ffs_opts->fsize = MAX(DFL_FRAGSIZE, fsopts->sectorsize);
|
||||
if (ffs_opts->bsize == -1)
|
||||
ffs_opts->bsize = MIN(DFL_BLKSIZE, 8 * ffs_opts->fsize);
|
||||
if (ffs_opts->cpg == -1)
|
||||
ffs_opts->cpg = DFL_CYLSPERGROUP;
|
||||
else
|
||||
fsopts->cpgflg = 1;
|
||||
ffs_opts->cpgflg = 1;
|
||||
/* fsopts->density is set below */
|
||||
if (fsopts->nsectors == -1)
|
||||
fsopts->nsectors = DFL_NSECTORS;
|
||||
if (fsopts->minfree == -1)
|
||||
fsopts->minfree = MINFREE;
|
||||
if (fsopts->optimization == -1)
|
||||
fsopts->optimization = DEFAULTOPT;
|
||||
if (fsopts->maxcontig == -1)
|
||||
fsopts->maxcontig =
|
||||
MAX(1, MIN(MAXPHYS, FFS_MAXBSIZE) / fsopts->bsize);
|
||||
if (ffs_opts->nsectors == -1)
|
||||
ffs_opts->nsectors = DFL_NSECTORS;
|
||||
if (ffs_opts->minfree == -1)
|
||||
ffs_opts->minfree = MINFREE;
|
||||
if (ffs_opts->optimization == -1)
|
||||
ffs_opts->optimization = DEFAULTOPT;
|
||||
if (ffs_opts->maxcontig == -1)
|
||||
ffs_opts->maxcontig =
|
||||
MAX(1, MIN(MAXPHYS, FFS_MAXBSIZE) / ffs_opts->bsize);
|
||||
/* XXX ondisk32 */
|
||||
if (fsopts->maxbpg == -1)
|
||||
fsopts->maxbpg = fsopts->bsize / sizeof(int32_t);
|
||||
if (fsopts->avgfilesize == -1)
|
||||
fsopts->avgfilesize = AVFILESIZ;
|
||||
if (fsopts->avgfpdir == -1)
|
||||
fsopts->avgfpdir = AFPDIR;
|
||||
if (ffs_opts->maxbpg == -1)
|
||||
ffs_opts->maxbpg = ffs_opts->bsize / sizeof(int32_t);
|
||||
if (ffs_opts->avgfilesize == -1)
|
||||
ffs_opts->avgfilesize = AVFILESIZ;
|
||||
if (ffs_opts->avgfpdir == -1)
|
||||
ffs_opts->avgfpdir = AFPDIR;
|
||||
|
||||
/* calculate size of tree */
|
||||
ffs_size_dir(root, fsopts);
|
||||
@ -343,17 +383,19 @@ ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
*/
|
||||
fsopts->size += (SBLOCK_UFS1 + SBLOCKSIZE) * ncg;
|
||||
/* add space needed to store inodes, x3 for blockmaps, etc */
|
||||
if (fsopts->version == 1)
|
||||
if (ffs_opts->version == 1)
|
||||
fsopts->size += ncg * DINODE1_SIZE *
|
||||
roundup(fsopts->inodes / ncg, fsopts->bsize / DINODE1_SIZE);
|
||||
roundup(fsopts->inodes / ncg,
|
||||
ffs_opts->bsize / DINODE1_SIZE);
|
||||
else
|
||||
fsopts->size += ncg * DINODE2_SIZE *
|
||||
roundup(fsopts->inodes / ncg, fsopts->bsize / DINODE2_SIZE);
|
||||
roundup(fsopts->inodes / ncg,
|
||||
ffs_opts->bsize / DINODE2_SIZE);
|
||||
|
||||
/* add minfree */
|
||||
if (fsopts->minfree > 0)
|
||||
if (ffs_opts->minfree > 0)
|
||||
fsopts->size =
|
||||
fsopts->size * (100 + fsopts->minfree) / 100;
|
||||
fsopts->size * (100 + ffs_opts->minfree) / 100;
|
||||
/*
|
||||
* XXX any other fs slop to add, such as csum's, bitmaps, etc ??
|
||||
*/
|
||||
@ -362,24 +404,11 @@ ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
fsopts->size = fsopts->minsize;
|
||||
|
||||
/* round up to the next block */
|
||||
size = roundup(fsopts->size, fsopts->bsize);
|
||||
|
||||
/* now check calculated sizes vs requested sizes */
|
||||
if (fsopts->maxsize > 0 && size > fsopts->maxsize) {
|
||||
if (debug & DEBUG_FS_VALIDATE) {
|
||||
printf("%s: `%s' size of %lld is larger than the "
|
||||
"maxsize of %lld; rounding down to %lld.",
|
||||
__func__, dir, (long long)size,
|
||||
(long long)fsopts->maxsize,
|
||||
(long long) rounddown(fsopts->size, fsopts->bsize));
|
||||
}
|
||||
size = rounddown(fsopts->size, fsopts->bsize);
|
||||
}
|
||||
fsopts->size = size;
|
||||
fsopts->size = roundup(fsopts->size, ffs_opts->bsize);
|
||||
|
||||
/* calculate density if necessary */
|
||||
if (fsopts->density == -1)
|
||||
fsopts->density = fsopts->size / fsopts->inodes + 1;
|
||||
if (ffs_opts->density == -1)
|
||||
ffs_opts->density = fsopts->size / fsopts->inodes + 1;
|
||||
|
||||
if (debug & DEBUG_FS_VALIDATE) {
|
||||
printf("ffs_validate: after defaults set:\n");
|
||||
@ -388,6 +417,12 @@ ffs_validate(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
dir, (long long)fsopts->size, (long long)fsopts->inodes);
|
||||
}
|
||||
sectorsize = fsopts->sectorsize; /* XXX - see earlier */
|
||||
|
||||
/* now check calculated sizes vs requested sizes */
|
||||
if (fsopts->maxsize > 0 && fsopts->size > fsopts->maxsize) {
|
||||
errx(1, "`%s' size of %lld is larger than the maxsize of %lld.",
|
||||
dir, (long long)fsopts->size, (long long)fsopts->maxsize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -395,6 +430,8 @@ static void
|
||||
ffs_dump_fsinfo(fsinfo_t *f)
|
||||
{
|
||||
|
||||
ffs_opt_t *fs = f->fs_specific;
|
||||
|
||||
printf("fsopts at %p\n", f);
|
||||
|
||||
printf("\tsize %lld, inodes %lld, curinode %u\n",
|
||||
@ -409,20 +446,20 @@ ffs_dump_fsinfo(fsinfo_t *f)
|
||||
printf("\tneedswap %d, sectorsize %d\n", f->needswap, f->sectorsize);
|
||||
|
||||
printf("\tbsize %d, fsize %d, cpg %d, density %d\n",
|
||||
f->bsize, f->fsize, f->cpg, f->density);
|
||||
fs->bsize, fs->fsize, fs->cpg, fs->density);
|
||||
printf("\tnsectors %d, rpm %d, minfree %d\n",
|
||||
f->nsectors, f->rpm, f->minfree);
|
||||
fs->nsectors, fs->rpm, fs->minfree);
|
||||
printf("\tmaxcontig %d, maxbpg %d\n",
|
||||
f->maxcontig, f->maxbpg);
|
||||
fs->maxcontig, fs->maxbpg);
|
||||
printf("\toptimization %s\n",
|
||||
f->optimization == FS_OPTSPACE ? "space" : "time");
|
||||
fs->optimization == FS_OPTSPACE ? "space" : "time");
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
ffs_create_image(const char *image, fsinfo_t *fsopts)
|
||||
{
|
||||
#if HAVE_STRUCT_STATVFS_F_IOSIZE
|
||||
#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
|
||||
struct statvfs sfs;
|
||||
#endif
|
||||
struct fs *fs;
|
||||
@ -434,18 +471,18 @@ ffs_create_image(const char *image, fsinfo_t *fsopts)
|
||||
assert (fsopts != NULL);
|
||||
|
||||
/* create image */
|
||||
if ((fsopts->fd = open(image, O_RDWR | O_CREAT | O_TRUNC, 0777))
|
||||
if ((fsopts->fd = open(image, O_RDWR | O_CREAT | O_TRUNC, 0666))
|
||||
== -1) {
|
||||
warn("Can't open `%s' for writing", image);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* zero image */
|
||||
#if HAVE_STRUCT_STATVFS_F_IOSIZE
|
||||
#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
|
||||
if (fstatvfs(fsopts->fd, &sfs) == -1) {
|
||||
#endif
|
||||
bufsize = 8192;
|
||||
#if HAVE_STRUCT_STATVFS_F_IOSIZE
|
||||
#if HAVE_STRUCT_STATVFS_F_IOSIZE && HAVE_FSTATVFS
|
||||
warn("can't fstatvfs `%s', using default %d byte chunk",
|
||||
image, bufsize);
|
||||
} else
|
||||
@ -465,10 +502,12 @@ ffs_create_image(const char *image, fsinfo_t *fsopts)
|
||||
if (i == -1) {
|
||||
warn("zeroing image, %lld bytes to go",
|
||||
(long long)bufrem);
|
||||
free(buf);
|
||||
return (-1);
|
||||
}
|
||||
bufrem -= i;
|
||||
}
|
||||
free(buf);
|
||||
|
||||
/* make the file system */
|
||||
if (debug & DEBUG_FS_CREATE_IMAGE)
|
||||
@ -492,7 +531,7 @@ ffs_create_image(const char *image, fsinfo_t *fsopts)
|
||||
warnx(
|
||||
"Image file `%s' has %lld free inodes; %lld are required.",
|
||||
image,
|
||||
(long long)fs->fs_cstotal.cs_nifree + ROOTINO,
|
||||
(long long)(fs->fs_cstotal.cs_nifree + ROOTINO),
|
||||
(long long)fsopts->inodes);
|
||||
return (-1);
|
||||
}
|
||||
@ -506,9 +545,11 @@ ffs_size_dir(fsnode *root, fsinfo_t *fsopts)
|
||||
struct direct tmpdir;
|
||||
fsnode * node;
|
||||
int curdirsize, this;
|
||||
ffs_opt_t *ffs_opts = fsopts->fs_specific;
|
||||
|
||||
/* node may be NULL (empty directory) */
|
||||
assert(fsopts != NULL);
|
||||
assert(ffs_opts != NULL);
|
||||
|
||||
if (debug & DEBUG_FS_SIZE_DIR)
|
||||
printf("ffs_size_dir: entry: bytes %lld inodes %lld\n",
|
||||
@ -516,7 +557,7 @@ ffs_size_dir(fsnode *root, fsinfo_t *fsopts)
|
||||
|
||||
#define ADDDIRENT(e) do { \
|
||||
tmpdir.d_namlen = strlen((e)); \
|
||||
this = DIRSIZ_SWAP(0, &tmpdir, 0); \
|
||||
this = DIRSIZ_SWAP(0, &tmpdir, 0); \
|
||||
if (debug & DEBUG_FS_SIZE_DIR_ADD_DIRENT) \
|
||||
printf("ADDDIRENT: was: %s (%d) this %d cur %d\n", \
|
||||
e, tmpdir.d_namlen, this, curdirsize); \
|
||||
@ -533,14 +574,12 @@ ffs_size_dir(fsnode *root, fsinfo_t *fsopts)
|
||||
* by indirect blocks, etc.
|
||||
*/
|
||||
#define ADDSIZE(x) do { \
|
||||
fsopts->size += roundup((x), fsopts->fsize); \
|
||||
fsopts->size += roundup((x), ffs_opts->fsize); \
|
||||
} while (0);
|
||||
|
||||
curdirsize = 0;
|
||||
for (node = root; node != NULL; node = node->next) {
|
||||
ADDDIRENT(node->name);
|
||||
if (FSNODE_EXCLUDE_P(fsopts, node))
|
||||
continue;
|
||||
if (node == root) { /* we're at "." */
|
||||
assert(strcmp(node->name, ".") == 0);
|
||||
ADDDIRENT("..");
|
||||
@ -558,7 +597,7 @@ ffs_size_dir(fsnode *root, fsinfo_t *fsopts)
|
||||
int slen;
|
||||
|
||||
slen = strlen(node->symlink) + 1;
|
||||
if (slen >= (fsopts->version == 1 ?
|
||||
if (slen >= (ffs_opts->version == 1 ?
|
||||
MAXSYMLINKLEN_UFS1 :
|
||||
MAXSYMLINKLEN_UFS2))
|
||||
ADDSIZE(slen);
|
||||
@ -682,10 +721,12 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
union dinode din;
|
||||
void *membuf;
|
||||
char path[MAXPATHLEN + 1];
|
||||
ffs_opt_t *ffs_opts = fsopts->fs_specific;
|
||||
|
||||
assert(dir != NULL);
|
||||
assert(root != NULL);
|
||||
assert(fsopts != NULL);
|
||||
assert(ffs_opts != NULL);
|
||||
|
||||
(void)memset(&dirbuf, 0, sizeof(dirbuf));
|
||||
|
||||
@ -696,8 +737,6 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
* pass 1: allocate inode numbers, build directory `file'
|
||||
*/
|
||||
for (cur = root; cur != NULL; cur = cur->next) {
|
||||
if (FSNODE_EXCLUDE_P(fsopts, cur))
|
||||
continue;
|
||||
if ((cur->inode->flags & FI_ALLOCATED) == 0) {
|
||||
cur->inode->flags |= FI_ALLOCATED;
|
||||
if (cur == root && cur->parent != NULL)
|
||||
@ -732,8 +771,6 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
if (debug & DEBUG_FS_POPULATE)
|
||||
printf("ffs_populate_dir: PASS 2 dir %s\n", dir);
|
||||
for (cur = root; cur != NULL; cur = cur->next) {
|
||||
if (FSNODE_EXCLUDE_P(fsopts, cur))
|
||||
continue;
|
||||
if (cur->inode->flags & FI_WRITTEN)
|
||||
continue; /* skip hard-linked entries */
|
||||
cur->inode->flags |= FI_WRITTEN;
|
||||
@ -746,7 +783,7 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
continue; /* child creates own inode */
|
||||
|
||||
/* build on-disk inode */
|
||||
if (fsopts->version == 1)
|
||||
if (ffs_opts->version == 1)
|
||||
membuf = ffs_build_dinode1(&din.ffs1_din, &dirbuf, cur,
|
||||
root, fsopts);
|
||||
else
|
||||
@ -777,8 +814,6 @@ ffs_populate_dir(const char *dir, fsnode *root, fsinfo_t *fsopts)
|
||||
if (debug & DEBUG_FS_POPULATE)
|
||||
printf("ffs_populate_dir: PASS 3 dir %s\n", dir);
|
||||
for (cur = root; cur != NULL; cur = cur->next) {
|
||||
if (FSNODE_EXCLUDE_P(fsopts, cur))
|
||||
continue;
|
||||
if (cur->child == NULL)
|
||||
continue;
|
||||
if (snprintf(path, sizeof(path), "%s/%s", dir, cur->name)
|
||||
@ -804,16 +839,20 @@ ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts)
|
||||
int isfile, ffd;
|
||||
char *fbuf, *p;
|
||||
off_t bufleft, chunk, offset;
|
||||
ssize_t nread;
|
||||
struct inode in;
|
||||
struct buf * bp;
|
||||
ffs_opt_t *ffs_opts = fsopts->fs_specific;
|
||||
|
||||
assert (din != NULL);
|
||||
assert (buf != NULL);
|
||||
assert (fsopts != NULL);
|
||||
assert (ffs_opts != NULL);
|
||||
|
||||
isfile = S_ISREG(DIP(din, mode));
|
||||
fbuf = NULL;
|
||||
ffd = -1;
|
||||
p = NULL;
|
||||
|
||||
in.i_fs = (struct fs *)fsopts->superblock;
|
||||
|
||||
@ -830,7 +869,7 @@ ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts)
|
||||
|
||||
in.i_number = ino;
|
||||
in.i_size = DIP(din, size);
|
||||
if (fsopts->version == 1)
|
||||
if (ffs_opts->version == 1)
|
||||
memcpy(&in.i_din.ffs1_din, &din->ffs1_din,
|
||||
sizeof(in.i_din.ffs1_din));
|
||||
else
|
||||
@ -842,7 +881,7 @@ ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts)
|
||||
goto write_inode_and_leave; /* mmm, cheating */
|
||||
|
||||
if (isfile) {
|
||||
if ((fbuf = malloc(fsopts->bsize)) == NULL)
|
||||
if ((fbuf = malloc(ffs_opts->bsize)) == NULL)
|
||||
err(1, "Allocating memory for write buffer");
|
||||
if ((ffd = open((char *)buf, O_RDONLY, 0444)) == -1) {
|
||||
warn("Can't open `%s' for reading", (char *)buf);
|
||||
@ -854,13 +893,20 @@ ffs_write_file(union dinode *din, uint32_t ino, void *buf, fsinfo_t *fsopts)
|
||||
|
||||
chunk = 0;
|
||||
for (bufleft = DIP(din, size); bufleft > 0; bufleft -= chunk) {
|
||||
chunk = MIN(bufleft, fsopts->bsize);
|
||||
if (isfile) {
|
||||
if (read(ffd, fbuf, chunk) != chunk)
|
||||
err(1, "Reading `%s', %lld bytes to go",
|
||||
(char *)buf, (long long)bufleft);
|
||||
chunk = MIN(bufleft, ffs_opts->bsize);
|
||||
if (!isfile)
|
||||
;
|
||||
else if ((nread = read(ffd, fbuf, chunk)) == -1)
|
||||
err(EXIT_FAILURE, "Reading `%s', %lld bytes to go",
|
||||
(char *)buf, (long long)bufleft);
|
||||
else if (nread != chunk)
|
||||
errx(EXIT_FAILURE, "Reading `%s', %lld bytes to go, "
|
||||
"read %zd bytes, expected %ju bytes, does "
|
||||
"metalog size= attribute mismatch source size?",
|
||||
(char *)buf, (long long)bufleft, nread,
|
||||
(uintmax_t)chunk);
|
||||
else
|
||||
p = fbuf;
|
||||
}
|
||||
offset = DIP(din, size) - bufleft;
|
||||
if (debug & DEBUG_FS_WRITE_FILE_BLOCK)
|
||||
printf(
|
||||
@ -932,7 +978,7 @@ ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap)
|
||||
{
|
||||
struct direct de, *dp;
|
||||
uint16_t llen, reclen;
|
||||
char *newbuf;
|
||||
u_char *newbuf;
|
||||
|
||||
assert (dbuf != NULL);
|
||||
assert (name != NULL);
|
||||
@ -969,7 +1015,7 @@ ffs_make_dirbuf(dirbuf_t *dbuf, const char *name, fsnode *node, int needswap)
|
||||
dbuf->size += DIRBLKSIZ;
|
||||
memset(dbuf->buf + dbuf->size - DIRBLKSIZ, 0, DIRBLKSIZ);
|
||||
dbuf->cur = dbuf->size - DIRBLKSIZ;
|
||||
} else { /* shrink end of previous */
|
||||
} else if (dp) { /* shrink end of previous */
|
||||
dp->d_reclen = ufs_rw16(llen,needswap);
|
||||
dbuf->cur += llen;
|
||||
}
|
||||
@ -993,10 +1039,12 @@ ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts)
|
||||
daddr_t d;
|
||||
char sbbuf[FFS_MAXBSIZE];
|
||||
int32_t initediblk;
|
||||
ffs_opt_t *ffs_opts = fsopts->fs_specific;
|
||||
|
||||
assert (dp != NULL);
|
||||
assert (ino > 0);
|
||||
assert (fsopts != NULL);
|
||||
assert (ffs_opts != NULL);
|
||||
|
||||
fs = (struct fs *)fsopts->superblock;
|
||||
cg = ino_to_cg(fs, ino);
|
||||
@ -1041,7 +1089,7 @@ ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts)
|
||||
* Initialize inode blocks on the fly for UFS2.
|
||||
*/
|
||||
initediblk = ufs_rw32(cgp->cg_initediblk, fsopts->needswap);
|
||||
if (fsopts->version == 2 && cgino + INOPB(fs) > initediblk &&
|
||||
if (ffs_opts->version == 2 && cgino + INOPB(fs) > initediblk &&
|
||||
initediblk < ufs_rw32(cgp->cg_niblk, fsopts->needswap)) {
|
||||
memset(buf, 0, fs->fs_bsize);
|
||||
dip = (struct ufs2_dinode *)buf;
|
||||
@ -1065,14 +1113,14 @@ ffs_write_inode(union dinode *dp, uint32_t ino, const fsinfo_t *fsopts)
|
||||
d = fsbtodb(fs, ino_to_fsba(fs, ino));
|
||||
ffs_rdfs(d, fs->fs_bsize, buf, fsopts);
|
||||
if (fsopts->needswap) {
|
||||
if (fsopts->version == 1)
|
||||
if (ffs_opts->version == 1)
|
||||
ffs_dinode1_swap(&dp->ffs1_din,
|
||||
&dp1[ino_to_fsbo(fs, ino)]);
|
||||
else
|
||||
ffs_dinode2_swap(&dp->ffs2_din,
|
||||
&dp2[ino_to_fsbo(fs, ino)]);
|
||||
} else {
|
||||
if (fsopts->version == 1)
|
||||
if (ffs_opts->version == 1)
|
||||
dp1[ino_to_fsbo(fs, ino)] = dp->ffs1_din;
|
||||
else
|
||||
dp2[ino_to_fsbo(fs, ino)] = dp->ffs2_din;
|
||||
|
66
usr.sbin/makefs/ffs.h
Normal file
66
usr.sbin/makefs/ffs.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* $NetBSD: ffs.h,v 1.1 2004/12/20 20:51:42 jmc Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Wasabi Systems, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Written by Luke Mewburn for Wasabi Systems, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project by
|
||||
* Wasabi Systems, Inc.
|
||||
* 4. The name of Wasabi Systems, Inc. may not be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _FFS_H
|
||||
#define _FFS_H
|
||||
|
||||
typedef struct {
|
||||
int bsize; /* block size */
|
||||
int fsize; /* fragment size */
|
||||
int cpg; /* cylinders per group */
|
||||
int cpgflg; /* cpg was specified by user */
|
||||
int density; /* bytes per inode */
|
||||
int ntracks; /* number of tracks */
|
||||
int nsectors; /* number of sectors */
|
||||
int rpm; /* rpm */
|
||||
int minfree; /* free space threshold */
|
||||
int optimization; /* optimization (space or time) */
|
||||
int maxcontig; /* max contiguous blocks to allocate */
|
||||
int rotdelay; /* rotational delay between blocks */
|
||||
int maxbpg; /* maximum blocks per file in a cyl group */
|
||||
int nrpos; /* # of distinguished rotational positions */
|
||||
int avgfilesize; /* expected average file size */
|
||||
int avgfpdir; /* expected # of files per directory */
|
||||
int version; /* filesystem version (1 = FFS, 2 = UFS2) */
|
||||
int maxbsize; /* maximum extent size */
|
||||
int maxblkspercg; /* max # of blocks per cylinder group */
|
||||
/* XXX: support `old' file systems ? */
|
||||
} ffs_opt_t;
|
||||
|
||||
#endif /* _FFS_H */
|
9
usr.sbin/makefs/ffs/Makefile.inc
Normal file
9
usr.sbin/makefs/ffs/Makefile.inc
Normal file
@ -0,0 +1,9 @@
|
||||
# $FreeBSD$
|
||||
#
|
||||
|
||||
.PATH: ${.CURDIR}/ffs ${.CURDIR}/../../sys/ufs/ffs
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../sys/ufs/ffs
|
||||
|
||||
SRCS+= ffs_alloc.c ffs_balloc.c ffs_bswap.c ffs_subr.c ufs_bmap.c
|
||||
SRCS+= buf.c mkfs.c
|
@ -118,7 +118,7 @@ brelse(struct buf *bp)
|
||||
bp->b_bcount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
TAILQ_REMOVE(&buftail, bp, b_tailq);
|
||||
free(bp->b_data);
|
||||
free(bp);
|
||||
@ -160,7 +160,7 @@ bcleanup(void)
|
||||
* know why there's still some buffers lying around that
|
||||
* aren't brelse()d
|
||||
*/
|
||||
|
||||
|
||||
if (TAILQ_EMPTY(&buftail))
|
||||
return;
|
||||
|
||||
@ -201,7 +201,7 @@ getblk(int fd, struct fs *fs, daddr_t blkno, int size)
|
||||
if (bp == NULL) {
|
||||
if ((bp = calloc(1, sizeof(struct buf))) == NULL)
|
||||
err(1, "getblk: calloc");
|
||||
|
||||
|
||||
bp->b_bufsize = 0;
|
||||
bp->b_blkno = bp->b_lblkno = blkno;
|
||||
bp->b_fd = fd;
|
||||
|
@ -87,7 +87,7 @@ static int32_t ffs_mapsearch(struct fs *, struct cg *, daddr_t, int);
|
||||
* available block is located.
|
||||
*/
|
||||
int
|
||||
ffs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, int size,
|
||||
ffs_alloc(struct inode *ip, daddr_t lbn __unused, daddr_t bpref, int size,
|
||||
daddr_t *bnp)
|
||||
{
|
||||
struct fs *fs = ip->i_fs;
|
||||
@ -95,7 +95,7 @@ ffs_alloc(struct inode *ip, daddr_t lbn, daddr_t bpref, int size,
|
||||
int cg;
|
||||
|
||||
*bnp = 0;
|
||||
if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0) {
|
||||
if (size > fs->fs_bsize || fragoff(fs, size) != 0) {
|
||||
errx(1, "ffs_alloc: bad size: bsize %d size %d",
|
||||
fs->fs_bsize, size);
|
||||
}
|
||||
@ -187,11 +187,7 @@ ffs_blkpref_ufs1(struct inode *ip, daddr_t lbn, int indx, int32_t *bap)
|
||||
}
|
||||
|
||||
daddr_t
|
||||
ffs_blkpref_ufs2(ip, lbn, indx, bap)
|
||||
struct inode *ip;
|
||||
daddr_t lbn;
|
||||
int indx;
|
||||
int64_t *bap;
|
||||
ffs_blkpref_ufs2(struct inode *ip, daddr_t lbn, int indx, int64_t *bap)
|
||||
{
|
||||
struct fs *fs;
|
||||
int cg;
|
||||
@ -385,11 +381,11 @@ ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref)
|
||||
int32_t bno;
|
||||
struct fs *fs = ip->i_fs;
|
||||
const int needswap = UFS_FSNEEDSWAP(fs);
|
||||
u_int8_t *blksfree;
|
||||
u_int8_t *blksfree_swap;
|
||||
|
||||
cgp = (struct cg *)bp->b_data;
|
||||
blksfree = cg_blksfree_swap(cgp, needswap);
|
||||
if (bpref == 0 || dtog(fs, bpref) != ufs_rw32(cgp->cg_cgx, needswap)) {
|
||||
blksfree_swap = cg_blksfree_swap(cgp, needswap);
|
||||
if (bpref == 0 || (uint32_t)dtog(fs, bpref) != ufs_rw32(cgp->cg_cgx, needswap)) {
|
||||
bpref = ufs_rw32(cgp->cg_rotor, needswap);
|
||||
} else {
|
||||
bpref = blknum(fs, bpref);
|
||||
@ -397,7 +393,7 @@ ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref)
|
||||
/*
|
||||
* if the requested block is available, use it
|
||||
*/
|
||||
if (ffs_isblock(fs, blksfree, fragstoblks(fs, bno)))
|
||||
if (ffs_isblock(fs, blksfree_swap, fragstoblks(fs, bno)))
|
||||
goto gotit;
|
||||
}
|
||||
/*
|
||||
@ -409,7 +405,7 @@ ffs_alloccgblk(struct inode *ip, struct buf *bp, daddr_t bpref)
|
||||
cgp->cg_rotor = ufs_rw32(bno, needswap);
|
||||
gotit:
|
||||
blkno = fragstoblks(fs, bno);
|
||||
ffs_clrblock(fs, blksfree, (long)blkno);
|
||||
ffs_clrblock(fs, blksfree_swap, (long)blkno);
|
||||
ffs_clusteracct(fs, cgp, blkno, -1);
|
||||
ufs_add32(cgp->cg_cs.cs_nbfree, -1, needswap);
|
||||
fs->fs_cstotal.cs_nbfree--;
|
||||
@ -436,14 +432,15 @@ ffs_blkfree(struct inode *ip, daddr_t bno, long size)
|
||||
struct fs *fs = ip->i_fs;
|
||||
const int needswap = UFS_FSNEEDSWAP(fs);
|
||||
|
||||
if ((u_int)size > fs->fs_bsize || fragoff(fs, size) != 0 ||
|
||||
if (size > fs->fs_bsize || fragoff(fs, size) != 0 ||
|
||||
fragnum(fs, bno) + numfrags(fs, size) > fs->fs_frag) {
|
||||
errx(1, "blkfree: bad size: bno %lld bsize %d size %ld",
|
||||
(long long)bno, fs->fs_bsize, size);
|
||||
}
|
||||
cg = dtog(fs, bno);
|
||||
if (bno >= fs->fs_size) {
|
||||
warnx("bad block %lld, ino %d", (long long)bno, ip->i_number);
|
||||
warnx("bad block %lld, ino %llu", (long long)bno,
|
||||
(unsigned long long)ip->i_number);
|
||||
return;
|
||||
}
|
||||
error = bread(ip->i_fd, ip->i_fs, fsbtodb(fs, cgtod(fs, cg)),
|
||||
@ -622,7 +619,7 @@ ffs_clusteracct(struct fs *fs, struct cg *cgp, int32_t blkno, int cnt)
|
||||
*/
|
||||
start = blkno + 1;
|
||||
end = start + fs->fs_contigsumsize;
|
||||
if (end >= ufs_rw32(cgp->cg_nclusterblks, needswap))
|
||||
if ((unsigned)end >= ufs_rw32(cgp->cg_nclusterblks, needswap))
|
||||
end = ufs_rw32(cgp->cg_nclusterblks, needswap);
|
||||
mapp = &freemapp[start / NBBY];
|
||||
map = *mapp++;
|
||||
|
@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <errno.h>
|
||||
|
||||
#include "makefs.h"
|
||||
#include "ffs.h"
|
||||
|
||||
#include <ufs/ufs/dinode.h>
|
||||
#include <ufs/ffs/fs.h>
|
||||
@ -61,6 +62,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include "ffs/ffs_extern.h"
|
||||
#include "ffs/newfs_extern.h"
|
||||
|
||||
#ifndef BBSIZE
|
||||
#define BBSIZE 8192 /* size of boot area, with label */
|
||||
#endif
|
||||
|
||||
static void initcg(int, time_t, const fsinfo_t *);
|
||||
static int ilog2(int);
|
||||
|
||||
@ -102,6 +107,7 @@ static int opt; /* optimization preference (space or time) */
|
||||
static int density; /* number of bytes per inode */
|
||||
static int maxcontig; /* max contiguous blocks to allocate */
|
||||
static int maxbpg; /* maximum blocks per file in a cyl group */
|
||||
static int bbsize; /* boot block size */
|
||||
static int sbsize; /* superblock size */
|
||||
static int avgfilesize; /* expected average file size */
|
||||
static int avgfpdir; /* expected number of files per directory */
|
||||
@ -115,21 +121,23 @@ ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
|
||||
void *space;
|
||||
int size, blks;
|
||||
int nprintcols, printcolwidth;
|
||||
ffs_opt_t *ffs_opts = fsopts->fs_specific;
|
||||
|
||||
Oflag = fsopts->version;
|
||||
Oflag = ffs_opts->version;
|
||||
fssize = fsopts->size / fsopts->sectorsize;
|
||||
sectorsize = fsopts->sectorsize;
|
||||
fsize = fsopts->fsize;
|
||||
bsize = fsopts->bsize;
|
||||
maxbsize = fsopts->maxbsize;
|
||||
maxblkspercg = fsopts->maxblkspercg;
|
||||
minfree = fsopts->minfree;
|
||||
opt = fsopts->optimization;
|
||||
density = fsopts->density;
|
||||
maxcontig = fsopts->maxcontig;
|
||||
maxbpg = fsopts->maxbpg;
|
||||
avgfilesize = fsopts->avgfilesize;
|
||||
avgfpdir = fsopts->avgfpdir;
|
||||
fsize = ffs_opts->fsize;
|
||||
bsize = ffs_opts->bsize;
|
||||
maxbsize = ffs_opts->maxbsize;
|
||||
maxblkspercg = ffs_opts->maxblkspercg;
|
||||
minfree = ffs_opts->minfree;
|
||||
opt = ffs_opts->optimization;
|
||||
density = ffs_opts->density;
|
||||
maxcontig = ffs_opts->maxcontig;
|
||||
maxbpg = ffs_opts->maxbpg;
|
||||
avgfilesize = ffs_opts->avgfilesize;
|
||||
avgfpdir = ffs_opts->avgfpdir;
|
||||
bbsize = BBSIZE;
|
||||
sbsize = SBLOCKSIZE;
|
||||
|
||||
if (Oflag == 0) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
.\" $NetBSD: makefs.8,v 1.13 2004/02/13 17:56:18 wiz Exp $
|
||||
.\" $NetBSD: makefs.8,v 1.32 2009/01/20 20:47:25 bjh21 Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 2001-2003 Wasabi Systems, Inc.
|
||||
.\" All rights reserved.
|
||||
@ -35,7 +35,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd March 30, 2003
|
||||
.Dd January 10, 2009
|
||||
.Dt MAKEFS 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -43,43 +43,19 @@
|
||||
.Nd create a file system image from a directory tree
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Bk -words
|
||||
.Op Fl t Ar fs-type
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl o Ar fs-options
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl d Ar debug-mask
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl B Ar byte-order
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl S Ar sector-size
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl M Ar minimum-size
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl m Ar maximum-size
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl s Ar image-size
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl b Ar free-blocks
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl f Ar free-files
|
||||
.Ek
|
||||
.Bk -words
|
||||
.Op Fl F Ar specfile
|
||||
.Ek
|
||||
.Op Fl x
|
||||
.Bk -words
|
||||
.Op Fl B Ar byte-order
|
||||
.Op Fl b Ar free-blocks
|
||||
.Op Fl d Ar debug-mask
|
||||
.Op Fl F Ar specfile
|
||||
.Op Fl f Ar free-files
|
||||
.Op Fl M Ar minimum-size
|
||||
.Op Fl m Ar maximum-size
|
||||
.Op Fl N Ar userdb-dir
|
||||
.Ek
|
||||
.Op Fl o Ar fs-options
|
||||
.Op Fl S Ar sector-size
|
||||
.Op Fl s Ar image-size
|
||||
.Op Fl t Ar fs-type
|
||||
.Ar image-file
|
||||
.Ar directory
|
||||
.Sh DESCRIPTION
|
||||
@ -93,56 +69,22 @@ No special devices or privileges are required to perform this task.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width flag
|
||||
.It Fl t Ar fs-type
|
||||
Create an
|
||||
.Ar fs-type
|
||||
file system image.
|
||||
The following file system types are supported:
|
||||
.Bl -tag -width ffs -offset indent
|
||||
.It Sy ffs
|
||||
BSD fast file system (default).
|
||||
.El
|
||||
.It Fl o Ar fs-options
|
||||
Set file system specific options.
|
||||
.Ar fs-options
|
||||
is a comma separated list of options.
|
||||
Valid file system specific options are detailed below.
|
||||
.It Fl d Ar debug-mask
|
||||
Enable various levels of debugging, depending upon which bits are set
|
||||
in
|
||||
.Ar debug-mask .
|
||||
XXX: document these
|
||||
.It Fl B Ar byte-order
|
||||
Set the byte order of the image to
|
||||
.Ar byte-order .
|
||||
Valid byte orders are
|
||||
.Ql 4321 ,
|
||||
.Ql big
|
||||
.Ql big ,
|
||||
or
|
||||
.Ql be
|
||||
for big endian, and
|
||||
.Ql 1234 ,
|
||||
.Ql little
|
||||
.Ql little ,
|
||||
or
|
||||
.Ql le
|
||||
for little endian.
|
||||
Some file systems may have a fixed byte order; in those cases this
|
||||
argument will be ignored.
|
||||
.It Fl S Ar sector-size
|
||||
Set the file system sector size to
|
||||
.Ar sector-size .
|
||||
Defaults to 512.
|
||||
.It Fl M Ar minimum-size
|
||||
Set the minimum size of the file system image to
|
||||
.Ar minimum-size .
|
||||
.It Fl m Ar maximum-size
|
||||
Set the maximum size of the file system image to
|
||||
.Ar maximum-size .
|
||||
An error will be raised if the target file system needs to be larger
|
||||
than this to accommodate the provided directory tree.
|
||||
.It Fl s Ar image-size
|
||||
Set the size of the file system image to
|
||||
.Ar image-size .
|
||||
.It Fl b Ar free-blocks
|
||||
Ensure that a minimum of
|
||||
.Ar free-blocks
|
||||
@ -151,16 +93,12 @@ An optional
|
||||
.Ql %
|
||||
suffix may be provided to indicate that
|
||||
.Ar free-blocks
|
||||
indicates a percentage of the calculated image size
|
||||
.It Fl f Ar free-files
|
||||
Ensure that a minimum of
|
||||
.Ar free-files
|
||||
free files (inodes) exist in the image.
|
||||
An optional
|
||||
.Ql %
|
||||
suffix may be provided to indicate that
|
||||
.Ar free-files
|
||||
indicates a percentage of the calculated image size
|
||||
indicates a percentage of the calculated image size.
|
||||
.It Fl d Ar debug-mask
|
||||
Enable various levels of debugging, depending upon which bits are
|
||||
set in
|
||||
.Ar debug-mask .
|
||||
XXX: document these
|
||||
.It Fl F Ar specfile
|
||||
Use
|
||||
.Ar specfile
|
||||
@ -169,23 +107,23 @@ as an
|
||||
.Sq specfile
|
||||
specification.
|
||||
.Pp
|
||||
If a specfile entry exists in the underlying file system, its permissions and
|
||||
modification time will be used unless specifically overridden by the specfile.
|
||||
An error will be raised if the type of entry in the specfile conflicts
|
||||
with that of an existing entry.
|
||||
If a specfile entry exists in the underlying file system, its
|
||||
permissions and modification time will be used unless specifically
|
||||
overridden by the specfile.
|
||||
An error will be raised if the type of entry in the specfile
|
||||
conflicts with that of an existing entry.
|
||||
.Pp
|
||||
In the opposite case
|
||||
(where a specfile entry does not have an entry in the underlying file system)
|
||||
the following occurs:
|
||||
In the opposite case (where a specfile entry does not have an entry
|
||||
in the underlying file system) the following occurs:
|
||||
If the specfile entry is marked
|
||||
.Sy optional ,
|
||||
the specfile entry is ignored.
|
||||
Otherwise, the entry will be created in the image,
|
||||
and it is necessary to specify at least the following parameters
|
||||
in the specfile:
|
||||
Otherwise, the entry will be created in the image, and it is
|
||||
necessary to specify at least the following parameters in the
|
||||
specfile:
|
||||
.Sy type ,
|
||||
.Sy mode ,
|
||||
.Sy gname
|
||||
.Sy gname ,
|
||||
or
|
||||
.Sy gid ,
|
||||
and
|
||||
@ -203,8 +141,23 @@ If
|
||||
.Sy flags
|
||||
isn't provided, the current file flags will be used.
|
||||
Missing regular file entries will be created as zero-length files.
|
||||
.It Fl x
|
||||
Exclude file system nodes not explicitly listed in the specfile.
|
||||
.It Fl f Ar free-files
|
||||
Ensure that a minimum of
|
||||
.Ar free-files
|
||||
free files (inodes) exist in the image.
|
||||
An optional
|
||||
.Ql %
|
||||
suffix may be provided to indicate that
|
||||
.Ar free-files
|
||||
indicates a percentage of the calculated image size.
|
||||
.It Fl M Ar minimum-size
|
||||
Set the minimum size of the file system image to
|
||||
.Ar minimum-size .
|
||||
.It Fl m Ar maximum-size
|
||||
Set the maximum size of the file system image to
|
||||
.Ar maximum-size .
|
||||
An error will be raised if the target file system needs to be larger
|
||||
than this to accommodate the provided directory tree.
|
||||
.It Fl N Ar dbdir
|
||||
Use the user database text file
|
||||
.Pa master.passwd
|
||||
@ -217,6 +170,32 @@ rather than using the results from the system's
|
||||
and
|
||||
.Xr getgrnam 3
|
||||
(and related) library calls.
|
||||
.It Fl o Ar fs-options
|
||||
Set file system specific options.
|
||||
.Ar fs-options
|
||||
is a comma separated list of options.
|
||||
Valid file system specific options are detailed below.
|
||||
.It Fl S Ar sector-size
|
||||
Set the file system sector size to
|
||||
.Ar sector-size .
|
||||
.\" XXX: next line also true for cd9660?
|
||||
Defaults to 512.
|
||||
.It Fl s Ar image-size
|
||||
Set the size of the file system image to
|
||||
.Ar image-size .
|
||||
.It Fl t Ar fs-type
|
||||
Create an
|
||||
.Ar fs-type
|
||||
file system image.
|
||||
The following file system types are supported:
|
||||
.Bl -tag -width cd9660 -offset indent
|
||||
.It Sy ffs
|
||||
BSD fast file system (default).
|
||||
.It Sy cd9660
|
||||
ISO 9660 file system.
|
||||
.El
|
||||
.It Fl x
|
||||
Exclude file system nodes not explicitly listed in the specfile.
|
||||
.El
|
||||
.Pp
|
||||
Where sizes are specified, a decimal number of bytes is expected.
|
||||
@ -228,13 +207,13 @@ Each number may have one of the following optional suffixes:
|
||||
.It b
|
||||
Block; multiply by 512
|
||||
.It k
|
||||
Kilo; multiply by 1024 (1 KB)
|
||||
Kibi; multiply by 1024 (1 KiB)
|
||||
.It m
|
||||
Mega; multiply by 1048576 (1 MB)
|
||||
Mebi; multiply by 1048576 (1 MiB)
|
||||
.It g
|
||||
Giga; multiply by 1073741824 (1 GB)
|
||||
Gibi; multiply by 1073741824 (1 GiB)
|
||||
.It t
|
||||
Tera; multiply by 1099511627776 (1 TB)
|
||||
Tebi; multiply by 1099511627776 (1 TiB)
|
||||
.It w
|
||||
Word; multiply by the number of bytes in an integer
|
||||
.El
|
||||
@ -243,37 +222,109 @@ Word; multiply by the number of bytes in an integer
|
||||
.Ss FFS-specific options
|
||||
.Sy ffs
|
||||
images have ffs-specific optional parameters that may be provided.
|
||||
Each of the options consists of a keyword, an equals sign
|
||||
Each of the options consists of a keyword, an equal sign
|
||||
.Pq Ql = ,
|
||||
and a value.
|
||||
The following keywords are supported:
|
||||
.Pp
|
||||
.Bl -tag -width optimization -offset indent -compact
|
||||
.It Sy avgfilesize
|
||||
Expected average file size
|
||||
Expected average file size.
|
||||
.It Sy avgfpdir
|
||||
Expected number of files per directory
|
||||
Expected number of files per directory.
|
||||
.It Sy bsize
|
||||
Block size
|
||||
Block size.
|
||||
.It Sy density
|
||||
Bytes per inode
|
||||
Bytes per inode.
|
||||
.It Sy fsize
|
||||
Fragment size
|
||||
Fragment size.
|
||||
.It Sy maxbpg
|
||||
Maximum blocks per file in a cylinder group
|
||||
Maximum blocks per file in a cylinder group.
|
||||
.It Sy minfree
|
||||
Minimum % free
|
||||
Minimum % free.
|
||||
.It Sy optimization
|
||||
Optimization preference; one of
|
||||
.Ql space
|
||||
or
|
||||
.Ql time .
|
||||
.It Sy extent
|
||||
Maximum extent size
|
||||
Maximum extent size.
|
||||
.It Sy maxbpcg
|
||||
Maximum total number of blocks in a cylinder group
|
||||
Maximum total number of blocks in a cylinder group.
|
||||
.It Sy version
|
||||
UFS version. 1 for FFS (default), 2 for UFS2
|
||||
UFS version.
|
||||
1 for FFS (default), 2 for UFS2.
|
||||
.El
|
||||
.Ss CD9660-specific options
|
||||
.Sy cd9660
|
||||
images have ISO9660-specific optional parameters that may be
|
||||
provided.
|
||||
The arguments consist of a keyword and, optionally, an equal sign
|
||||
.Pq Ql = ,
|
||||
and a value.
|
||||
The following keywords are supported:
|
||||
.Pp
|
||||
.Bl -tag -width omit-trailing-period -offset indent -compact
|
||||
.It Sy allow-deep-trees
|
||||
Allow the directory structure to exceed the maximum specified in
|
||||
the spec.
|
||||
.\" .It Sy allow-illegal-chars
|
||||
.\" Unknown
|
||||
.\" .It Sy allow-lowercase
|
||||
.\" Unknown
|
||||
.It Sy allow-max-name
|
||||
Allow 37 instead of 33 characters for filenames by omitting the
|
||||
version id.
|
||||
.It Sy allow-multidot
|
||||
Allow multiple dots in a filename.
|
||||
.It Sy applicationid
|
||||
Application ID of the image.
|
||||
.It Sy archimedes
|
||||
Use the
|
||||
.Ql ARCHIMEDES
|
||||
extension to encode
|
||||
.Tn RISC OS
|
||||
metadata.
|
||||
.It Sy boot-load-segment
|
||||
Set load segment for the boot image.
|
||||
.It Sy bootimage
|
||||
Filename of a boot image in the format
|
||||
.Dq sysid;filename ,
|
||||
where
|
||||
.Dq sysid
|
||||
is one of
|
||||
.Ql i386 ,
|
||||
.Ql mac68k ,
|
||||
.Ql macppc ,
|
||||
or
|
||||
.Ql powerpc .
|
||||
.It Sy generic-bootimage
|
||||
Load a generic boot image into the first 32K of the cd9660 image.
|
||||
.It Sy hard-disk-boot
|
||||
Boot image is a hard disk image.
|
||||
.It Sy keep-bad-images
|
||||
Don't throw away images whose write was aborted due to an error.
|
||||
For debugging purposes.
|
||||
.It Sy label
|
||||
Label name of the image.
|
||||
.It Sy no-boot
|
||||
Boot image is not bootable.
|
||||
.It Sy no-emul-boot
|
||||
Boot image is a
|
||||
.Dq no emulation
|
||||
ElTorito image.
|
||||
.It Sy no-trailing-padding
|
||||
Do not pad the image (apparently Linux needs the padding).
|
||||
.\" .It Sy omit-trailing-period
|
||||
.\" Unknown
|
||||
.It Sy preparer
|
||||
Preparer ID of the image.
|
||||
.It Sy publisher
|
||||
Publisher ID of the image.
|
||||
.It Sy rockridge
|
||||
Use RockRidge extensions (for longer filenames, etc.).
|
||||
.It Sy volumeid
|
||||
Volume set identifier of the image.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr mtree 8 ,
|
||||
@ -285,4 +336,11 @@ utility appeared in
|
||||
.Nx 1.6 .
|
||||
.Sh AUTHORS
|
||||
.An Luke Mewburn
|
||||
.Aq lukem@NetBSD.org .
|
||||
.Aq lukem@NetBSD.org
|
||||
(original program)
|
||||
.An Daniel Watt ,
|
||||
.An Walter Deignan ,
|
||||
.An Ryan Gabrys ,
|
||||
.An Alan Perez-Rathke ,
|
||||
.An Ram Vedam
|
||||
(cd9660 support)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: makefs.c,v 1.20 2004/06/20 22:20:18 jmc Exp $ */
|
||||
/* $NetBSD: makefs.c,v 1.26 2006/10/22 21:11:56 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Wasabi Systems, Inc.
|
||||
@ -55,14 +55,18 @@ __FBSDID("$FreeBSD$");
|
||||
*/
|
||||
typedef struct {
|
||||
const char *type;
|
||||
void (*prepare_options)(fsinfo_t *);
|
||||
int (*parse_options)(const char *, fsinfo_t *);
|
||||
void (*cleanup_options)(fsinfo_t *);
|
||||
void (*make_fs)(const char *, const char *, fsnode *,
|
||||
fsinfo_t *);
|
||||
} fstype_t;
|
||||
|
||||
static fstype_t fstypes[] = {
|
||||
{ "ffs", ffs_parse_opts, ffs_makefs },
|
||||
{ NULL },
|
||||
{ "ffs", ffs_prep_opts, ffs_parse_opts, ffs_cleanup_opts, ffs_makefs },
|
||||
{ "cd9660", cd9660_prep_opts, cd9660_parse_opts, cd9660_cleanup_opts,
|
||||
cd9660_makefs},
|
||||
{ .type = NULL },
|
||||
};
|
||||
|
||||
u_int debug;
|
||||
@ -92,17 +96,9 @@ main(int argc, char *argv[])
|
||||
(void)memset(&fsoptions, 0, sizeof(fsoptions));
|
||||
fsoptions.fd = -1;
|
||||
fsoptions.sectorsize = -1;
|
||||
fsoptions.bsize= -1;
|
||||
fsoptions.fsize= -1;
|
||||
fsoptions.cpg= -1;
|
||||
fsoptions.density= -1;
|
||||
fsoptions.minfree= -1;
|
||||
fsoptions.optimization= -1;
|
||||
fsoptions.maxcontig= -1;
|
||||
fsoptions.maxbpg= -1;
|
||||
fsoptions.avgfilesize= -1;
|
||||
fsoptions.avgfpdir= -1;
|
||||
fsoptions.version = 1;
|
||||
|
||||
if (fstype->prepare_options)
|
||||
fstype->prepare_options(&fsoptions);
|
||||
|
||||
specfile = NULL;
|
||||
if (gettimeofday(&start, NULL) == -1)
|
||||
@ -148,8 +144,7 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
debug =
|
||||
(int)strsuftoll("debug mask", optarg, 0, UINT_MAX);
|
||||
debug = strtoll(optarg, NULL, 0);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
@ -212,8 +207,13 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
|
||||
case 't':
|
||||
/* Check current one and cleanup if necessary. */
|
||||
if (fstype->cleanup_options)
|
||||
fstype->cleanup_options(&fsoptions);
|
||||
fsoptions.fs_specific = NULL;
|
||||
if ((fstype = get_fstype(optarg)) == NULL)
|
||||
errx(1, "Unknown fs type `%s'.", optarg);
|
||||
fstype->prepare_options(&fsoptions);
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
@ -250,7 +250,7 @@ main(int argc, char *argv[])
|
||||
|
||||
if (specfile) { /* apply a specfile */
|
||||
TIMER_START(start);
|
||||
apply_specfile(specfile, argv[1], root);
|
||||
apply_specfile(specfile, argv[1], root, fsoptions.onlyspec);
|
||||
TIMER_RESULTS(start, "apply_specfile");
|
||||
}
|
||||
|
||||
@ -265,6 +265,8 @@ main(int argc, char *argv[])
|
||||
fstype->make_fs(argv[0], argv[1], root, &fsoptions);
|
||||
TIMER_RESULTS(start, "make_fs");
|
||||
|
||||
free_fsnodes(root);
|
||||
|
||||
exit(0);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: makefs.h,v 1.14 2004/06/20 22:20:18 jmc Exp $ */
|
||||
/* $NetBSD: makefs.h,v 1.20 2008/12/28 21:51:46 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
@ -126,27 +126,7 @@ typedef struct {
|
||||
int needswap; /* non-zero if byte swapping needed */
|
||||
int sectorsize; /* sector size */
|
||||
|
||||
/* ffs specific options */
|
||||
int bsize; /* block size */
|
||||
int fsize; /* fragment size */
|
||||
int cpg; /* cylinders per group */
|
||||
int cpgflg; /* cpg was specified by user */
|
||||
int density; /* bytes per inode */
|
||||
int ntracks; /* number of tracks */
|
||||
int nsectors; /* number of sectors */
|
||||
int rpm; /* rpm */
|
||||
int minfree; /* free space threshold */
|
||||
int optimization; /* optimization (space or time) */
|
||||
int maxcontig; /* max contiguous blocks to allocate */
|
||||
int rotdelay; /* rotational delay between blocks */
|
||||
int maxbpg; /* maximum blocks per file in a cyl group */
|
||||
int nrpos; /* # of distinguished rotational positions */
|
||||
int avgfilesize; /* expected average file size */
|
||||
int avgfpdir; /* expected # of files per directory */
|
||||
int version; /* filesystem version (1 = FFS, 2 = UFS2) */
|
||||
int maxbsize; /* maximum extent size */
|
||||
int maxblkspercg; /* max # of blocks per cylinder group */
|
||||
/* XXX: support `old' file systems ? */
|
||||
void *fs_specific; /* File system specific additions. */
|
||||
} fsinfo_t;
|
||||
|
||||
|
||||
@ -164,15 +144,22 @@ typedef struct {
|
||||
} option_t;
|
||||
|
||||
|
||||
void apply_specfile(const char *, const char *, fsnode *);
|
||||
void apply_specfile(const char *, const char *, fsnode *, int);
|
||||
void dump_fsnodes(const char *, fsnode *);
|
||||
const char * inode_type(mode_t);
|
||||
int set_option(option_t *, const char *, const char *);
|
||||
fsnode * walk_dir(const char *, fsnode *);
|
||||
void free_fsnodes(fsnode *);
|
||||
|
||||
void ffs_prep_opts(fsinfo_t *);
|
||||
int ffs_parse_opts(const char *, fsinfo_t *);
|
||||
void ffs_cleanup_opts(fsinfo_t *);
|
||||
void ffs_makefs(const char *, const char *, fsnode *, fsinfo_t *);
|
||||
|
||||
void cd9660_prep_opts(fsinfo_t *);
|
||||
int cd9660_parse_opts(const char *, fsinfo_t *);
|
||||
void cd9660_cleanup_opts(fsinfo_t *);
|
||||
void cd9660_makefs(const char *, const char *, fsnode *, fsinfo_t *);
|
||||
|
||||
|
||||
extern u_int debug;
|
||||
@ -211,6 +198,7 @@ extern struct timespec start_time;
|
||||
#define DEBUG_BUF_GETBLK 0x02000000
|
||||
#define DEBUG_APPLY_SPECFILE 0x04000000
|
||||
#define DEBUG_APPLY_SPECENTRY 0x08000000
|
||||
#define DEBUG_APPLY_SPECONLY 0x10000000
|
||||
|
||||
|
||||
#define TIMER_START(x) \
|
||||
@ -222,8 +210,9 @@ extern struct timespec start_time;
|
||||
struct timeval end, td; \
|
||||
gettimeofday(&end, NULL); \
|
||||
timersub(&end, &(x), &td); \
|
||||
printf("%s took %ld.%06ld seconds\n", \
|
||||
(d), (long) td.tv_sec, (long) td.tv_usec); \
|
||||
printf("%s took %lld.%06ld seconds\n", \
|
||||
(d), (long long)td.tv_sec, \
|
||||
(long)td.tv_usec); \
|
||||
}
|
||||
|
||||
|
||||
@ -249,56 +238,56 @@ extern struct timespec start_time;
|
||||
* File system internal flags, also in fs_flags.
|
||||
* (Pick highest number to avoid conflicts with others)
|
||||
*/
|
||||
#define FS_SWAPPED 0x80000000 /* file system is endian swapped */
|
||||
#define FS_INTERNAL 0x80000000 /* mask for internal flags */
|
||||
#define FS_SWAPPED 0x80000000 /* file system is endian swapped */
|
||||
#define FS_INTERNAL 0x80000000 /* mask for internal flags */
|
||||
|
||||
#define FS_ISCLEAN 1
|
||||
#define FS_ISCLEAN 1
|
||||
|
||||
#define DINODE1_SIZE (sizeof(struct ufs1_dinode))
|
||||
#define DINODE2_SIZE (sizeof(struct ufs2_dinode))
|
||||
#define DINODE1_SIZE (sizeof(struct ufs1_dinode))
|
||||
#define DINODE2_SIZE (sizeof(struct ufs2_dinode))
|
||||
|
||||
#define MAXSYMLINKLEN_UFS1 ((NDADDR + NIADDR) * sizeof(ufs1_daddr_t))
|
||||
#define MAXSYMLINKLEN_UFS2 ((NDADDR + NIADDR) * sizeof(ufs2_daddr_t))
|
||||
#define MAXSYMLINKLEN_UFS1 ((NDADDR + NIADDR) * sizeof(ufs1_daddr_t))
|
||||
#define MAXSYMLINKLEN_UFS2 ((NDADDR + NIADDR) * sizeof(ufs2_daddr_t))
|
||||
|
||||
#if (BYTE_ORDER == LITTLE_ENDIAN)
|
||||
#define DIRSIZ_SWAP(oldfmt, dp, needswap) \
|
||||
(((oldfmt) && !(needswap)) ? \
|
||||
#define DIRSIZ_SWAP(oldfmt, dp, needswap) \
|
||||
(((oldfmt) && !(needswap)) ? \
|
||||
DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen))
|
||||
#else
|
||||
#define DIRSIZ_SWAP(oldfmt, dp, needswap) \
|
||||
(((oldfmt) && (needswap)) ? \
|
||||
#define DIRSIZ_SWAP(oldfmt, dp, needswap) \
|
||||
(((oldfmt) && (needswap)) ? \
|
||||
DIRECTSIZ((dp)->d_type) : DIRECTSIZ((dp)->d_namlen))
|
||||
#endif
|
||||
|
||||
#define cg_chkmagic_swap(cgp, ns) \
|
||||
#define cg_chkmagic_swap(cgp, ns) \
|
||||
(ufs_rw32((cgp)->cg_magic, (ns)) == CG_MAGIC)
|
||||
#define cg_inosused_swap(cgp, ns) \
|
||||
#define cg_inosused_swap(cgp, ns) \
|
||||
((u_int8_t *)((u_int8_t *)(cgp) + ufs_rw32((cgp)->cg_iusedoff, (ns))))
|
||||
#define cg_blksfree_swap(cgp, ns) \
|
||||
#define cg_blksfree_swap(cgp, ns) \
|
||||
((u_int8_t *)((u_int8_t *)(cgp) + ufs_rw32((cgp)->cg_freeoff, (ns))))
|
||||
#define cg_clustersfree_swap(cgp, ns) \
|
||||
#define cg_clustersfree_swap(cgp, ns) \
|
||||
((u_int8_t *)((u_int8_t *)(cgp) + ufs_rw32((cgp)->cg_clusteroff, (ns))))
|
||||
#define cg_clustersum_swap(cgp, ns) \
|
||||
#define cg_clustersum_swap(cgp, ns) \
|
||||
((int32_t *)((uintptr_t)(cgp) + ufs_rw32((cgp)->cg_clustersumoff, ns)))
|
||||
|
||||
struct fs;
|
||||
void ffs_fragacct_swap(struct fs *, int, int32_t [], int, int);
|
||||
void ffs_fragacct_swap(struct fs *, int, int32_t [], int, int);
|
||||
|
||||
/*
|
||||
* Declarations for compat routines.
|
||||
*/
|
||||
long long strsuftoll(const char *, const char *, long long, long long);
|
||||
long long strsuftollx(const char *, const char *,
|
||||
long long, long long, char *, size_t);
|
||||
long long, long long, char *, size_t);
|
||||
|
||||
struct passwd;
|
||||
int uid_from_user(const char *, uid_t *);
|
||||
int pwcache_userdb(int (*)(int), void (*)(void),
|
||||
struct passwd * (*)(const char *), struct passwd * (*)(uid_t));
|
||||
struct passwd * (*)(const char *), struct passwd * (*)(uid_t));
|
||||
struct group;
|
||||
int gid_from_group(const char *, gid_t *);
|
||||
int pwcache_groupdb(int (*)(int), void (*)(void),
|
||||
struct group * (*)(const char *), struct group * (*)(gid_t));
|
||||
struct group * (*)(const char *), struct group * (*)(gid_t));
|
||||
|
||||
int setup_getid(const char *dir);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: walk.c,v 1.17 2004/06/20 22:20:18 jmc Exp $ */
|
||||
/* $NetBSD: walk.c,v 1.24 2008/12/28 21:51:46 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001 Wasabi Systems, Inc.
|
||||
@ -35,41 +35,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The function link_check() was inspired from NetBSD's usr.bin/du/du.c,
|
||||
* which has the following copyright notice:
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1989, 1993, 1994
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Chris Newcomb.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
@ -84,13 +49,13 @@ __FBSDID("$FreeBSD$");
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "makefs.h"
|
||||
|
||||
#include "mtree.h"
|
||||
#include "extern.h" /* NB: mtree */
|
||||
#include "extern.h"
|
||||
|
||||
static void apply_specdir(const char *, NODE *, fsnode *);
|
||||
static void apply_specdir(const char *, NODE *, fsnode *, int);
|
||||
static void apply_specentry(const char *, NODE *, fsnode *);
|
||||
static fsnode *create_fsnode(const char *, struct stat *);
|
||||
static fsinode *link_check(fsinode *);
|
||||
@ -164,6 +129,10 @@ walk_dir(const char *dir, fsnode *parent)
|
||||
free(cur->inode);
|
||||
cur->inode = curino;
|
||||
cur->inode->nlink++;
|
||||
if (debug & DEBUG_WALK_DIR_LINKCHECK)
|
||||
printf("link_check: found [%llu, %llu]\n",
|
||||
(unsigned long long)curino->st.st_dev,
|
||||
(unsigned long long)curino->st.st_ino);
|
||||
}
|
||||
}
|
||||
if (S_ISLNK(cur->type)) {
|
||||
@ -200,6 +169,53 @@ create_fsnode(const char *name, struct stat *stbuf)
|
||||
return (cur);
|
||||
}
|
||||
|
||||
/*
|
||||
* free_fsnodes --
|
||||
* Removes node from tree and frees it and all of
|
||||
* its decendents.
|
||||
*/
|
||||
void
|
||||
free_fsnodes(fsnode *node)
|
||||
{
|
||||
fsnode *cur, *next;
|
||||
|
||||
assert(node != NULL);
|
||||
|
||||
/* for ".", start with actual parent node */
|
||||
if (node->first == node) {
|
||||
assert(node->name[0] == '.' && node->name[1] == '\0');
|
||||
if (node->parent) {
|
||||
assert(node->parent->child == node);
|
||||
node = node->parent;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find ourselves in our sibling list and unlink */
|
||||
if (node->first != node) {
|
||||
for (cur = node->first; cur->next; cur = cur->next) {
|
||||
if (cur->next == node) {
|
||||
cur->next = node->next;
|
||||
node->next = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (cur = node; cur != NULL; cur = next) {
|
||||
next = cur->next;
|
||||
if (cur->child) {
|
||||
cur->child->parent = NULL;
|
||||
free_fsnodes(cur->child);
|
||||
}
|
||||
if (cur->inode->nlink-- == 1)
|
||||
free(cur->inode);
|
||||
if (cur->symlink)
|
||||
free(cur->symlink);
|
||||
free(cur->name);
|
||||
free(cur);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* apply_specfile --
|
||||
* read in the mtree(8) specfile, and apply it to the tree
|
||||
@ -208,7 +224,7 @@ create_fsnode(const char *name, struct stat *stbuf)
|
||||
* entries will be added.
|
||||
*/
|
||||
void
|
||||
apply_specfile(const char *specfile, const char *dir, fsnode *parent)
|
||||
apply_specfile(const char *specfile, const char *dir, fsnode *parent, int speconly)
|
||||
{
|
||||
struct timeval start;
|
||||
FILE *fp;
|
||||
@ -236,7 +252,8 @@ apply_specfile(const char *specfile, const char *dir, fsnode *parent)
|
||||
assert(root->type == F_DIR);
|
||||
|
||||
/* merge in the changes */
|
||||
apply_specdir(dir, root, parent);
|
||||
apply_specdir(dir, root, parent, speconly);
|
||||
|
||||
}
|
||||
|
||||
static u_int
|
||||
@ -265,8 +282,9 @@ nodetoino(u_int type)
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode)
|
||||
apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode, int speconly)
|
||||
{
|
||||
char path[MAXPATHLEN + 1];
|
||||
NODE *curnode;
|
||||
@ -287,6 +305,30 @@ apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode)
|
||||
|
||||
apply_specentry(dir, specnode, dirnode);
|
||||
|
||||
/* Remove any filesystem nodes not found in specfile */
|
||||
/* XXX inefficient. This is O^2 in each dir and it would
|
||||
* have been better never to have walked this part of the tree
|
||||
* to begin with
|
||||
*/
|
||||
if (speconly) {
|
||||
fsnode *next;
|
||||
assert(dirnode->name[0] == '.' && dirnode->name[1] == '\0');
|
||||
for (curfsnode = dirnode->next; curfsnode != NULL; curfsnode = next) {
|
||||
next = curfsnode->next;
|
||||
for (curnode = specnode->child; curnode != NULL;
|
||||
curnode = curnode->next) {
|
||||
if (strcmp(curnode->name, curfsnode->name) == 0)
|
||||
break;
|
||||
}
|
||||
if (curnode == NULL) {
|
||||
if (debug & DEBUG_APPLY_SPECONLY) {
|
||||
printf("apply_specdir: trimming %s/%s %p\n", dir, curfsnode->name, curfsnode);
|
||||
}
|
||||
free_fsnodes(curfsnode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* now walk specnode->child matching up with dirnode */
|
||||
for (curnode = specnode->child; curnode != NULL;
|
||||
curnode = curnode->next) {
|
||||
@ -328,6 +370,9 @@ apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode)
|
||||
curnode->flags & F_GNAME, "group");
|
||||
NODETEST(curnode->flags & F_UID ||
|
||||
curnode->flags & F_UNAME, "user");
|
||||
/* if (curnode->type == F_BLOCK || curnode->type == F_CHAR)
|
||||
NODETEST(curnode->flags & F_DEV,
|
||||
"device number");*/
|
||||
#undef NODETEST
|
||||
|
||||
if (debug & DEBUG_APPLY_SPECFILE)
|
||||
@ -367,7 +412,7 @@ apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode)
|
||||
if (curfsnode->type != S_IFDIR)
|
||||
errx(1, "`%s' is not a directory", path);
|
||||
assert (curfsnode->child != NULL);
|
||||
apply_specdir(path, curnode, curfsnode->child);
|
||||
apply_specdir(path, curnode, curfsnode->child, speconly);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -444,6 +489,12 @@ apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode)
|
||||
dirnode->inode->st.st_flags = specnode->st_flags;
|
||||
}
|
||||
#endif
|
||||
/* if (specnode->flags & F_DEV) {
|
||||
ASEPRINT("rdev", "%#llx",
|
||||
(unsigned long long)dirnode->inode->st.st_rdev,
|
||||
(unsigned long long)specnode->st_rdev);
|
||||
dirnode->inode->st.st_rdev = specnode->st_rdev;
|
||||
}*/
|
||||
#undef ASEPRINT
|
||||
|
||||
dirnode->flags |= FSNODE_F_HASSPEC;
|
||||
@ -493,11 +544,11 @@ dump_fsnodes(const char *dir, fsnode *root)
|
||||
/*
|
||||
* inode_type --
|
||||
* for a given inode type `mode', return a descriptive string.
|
||||
* for most cases, uses inotype() from mtree/misc.c
|
||||
*/
|
||||
const char *
|
||||
inode_type(mode_t mode)
|
||||
{
|
||||
|
||||
if (S_ISREG(mode))
|
||||
return ("file");
|
||||
if (S_ISLNK(mode))
|
||||
@ -521,48 +572,78 @@ inode_type(mode_t mode)
|
||||
|
||||
/*
|
||||
* link_check --
|
||||
* return pointer to fsnode matching `entry's st_ino & st_dev if it exists,
|
||||
* return pointer to fsinode matching `entry's st_ino & st_dev if it exists,
|
||||
* otherwise add `entry' to table and return NULL
|
||||
*/
|
||||
/* This was borrowed from du.c and tweaked to keep an fsnode
|
||||
* pointer instead. -- dbj@netbsd.org
|
||||
*/
|
||||
static fsinode *
|
||||
link_check(fsinode *entry)
|
||||
{
|
||||
static struct dupnode {
|
||||
uint32_t dev;
|
||||
uint64_t ino;
|
||||
fsinode *dup;
|
||||
} *dups, *newdups;
|
||||
static int ndups, maxdups;
|
||||
static struct entry {
|
||||
fsinode *data;
|
||||
} *htable;
|
||||
static int htshift; /* log(allocated size) */
|
||||
static int htmask; /* allocated size - 1 */
|
||||
static int htused; /* 2*number of insertions */
|
||||
int h, h2;
|
||||
uint64_t tmp;
|
||||
/* this constant is (1<<64)/((1+sqrt(5))/2)
|
||||
* aka (word size)/(golden ratio)
|
||||
*/
|
||||
const uint64_t HTCONST = 11400714819323198485ULL;
|
||||
const int HTBITS = 64;
|
||||
|
||||
/* Never store zero in hashtable */
|
||||
assert(entry);
|
||||
|
||||
int i;
|
||||
/* Extend hash table if necessary, keep load under 0.5 */
|
||||
if (htused<<1 >= htmask) {
|
||||
struct entry *ohtable;
|
||||
|
||||
assert (entry != NULL);
|
||||
if (!htable)
|
||||
htshift = 10; /* starting hashtable size */
|
||||
else
|
||||
htshift++; /* exponential hashtable growth */
|
||||
|
||||
/* XXX; maybe traverse in reverse for speed? */
|
||||
for (i = 0; i < ndups; i++) {
|
||||
if (dups[i].dev == entry->st.st_dev &&
|
||||
dups[i].ino == entry->st.st_ino) {
|
||||
if (debug & DEBUG_WALK_DIR_LINKCHECK)
|
||||
printf("link_check: found [%d,%d]\n",
|
||||
entry->st.st_dev, entry->st.st_ino);
|
||||
return (dups[i].dup);
|
||||
htmask = (1 << htshift) - 1;
|
||||
htused = 0;
|
||||
|
||||
ohtable = htable;
|
||||
htable = calloc(htmask+1, sizeof(*htable));
|
||||
if (!htable)
|
||||
err(1, "Memory allocation error");
|
||||
|
||||
/* populate newly allocated hashtable */
|
||||
if (ohtable) {
|
||||
int i;
|
||||
for (i = 0; i <= htmask>>1; i++)
|
||||
if (ohtable[i].data)
|
||||
link_check(ohtable[i].data);
|
||||
free(ohtable);
|
||||
}
|
||||
}
|
||||
|
||||
if (debug & DEBUG_WALK_DIR_LINKCHECK)
|
||||
printf("link_check: no match for [%d, %d]\n",
|
||||
entry->st.st_dev, entry->st.st_ino);
|
||||
if (ndups == maxdups) {
|
||||
if ((newdups = realloc(dups, sizeof(struct dupnode) * (maxdups + 128)))
|
||||
== NULL)
|
||||
err(1, "Memory allocation error");
|
||||
dups = newdups;
|
||||
maxdups += 128;
|
||||
/* multiplicative hashing */
|
||||
tmp = entry->st.st_dev;
|
||||
tmp <<= HTBITS>>1;
|
||||
tmp |= entry->st.st_ino;
|
||||
tmp *= HTCONST;
|
||||
h = tmp >> (HTBITS - htshift);
|
||||
h2 = 1 | ( tmp >> (HTBITS - (htshift<<1) - 1)); /* must be odd */
|
||||
|
||||
/* open address hashtable search with double hash probing */
|
||||
while (htable[h].data) {
|
||||
if ((htable[h].data->st.st_ino == entry->st.st_ino) &&
|
||||
(htable[h].data->st.st_dev == entry->st.st_dev)) {
|
||||
return htable[h].data;
|
||||
}
|
||||
h = (h + h2) & htmask;
|
||||
}
|
||||
dups[ndups].dev = entry->st.st_dev;
|
||||
dups[ndups].ino = entry->st.st_ino;
|
||||
dups[ndups].dup = entry;
|
||||
ndups++;
|
||||
|
||||
return (NULL);
|
||||
/* Insert the current entry into hashtable */
|
||||
htable[h].data = entry;
|
||||
htused++;
|
||||
return NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user