From add8e748507880c11e821eb6a19e3d11d1f555f0 Mon Sep 17 00:00:00 2001 From: Philip Kendall Date: Wed, 16 Jun 2004 15:52:17 +0000 Subject: [PATCH] Add createhdf utility for creating empty .hdf files. Legacy-ID: 2255 --- .gitignore | 1 + Makefile.am | 3 +- createhdf.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++ hacking/ChangeLog | 2 + 4 files changed, 225 insertions(+), 1 deletion(-) create mode 100755 createhdf.c diff --git a/.gitignore b/.gitignore index 705127f..ebba359 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ /config.log /config.status /configure +/createhdf /fuse-utils.qpg /listbasic /rzxcheck diff --git a/Makefile.am b/Makefile.am index a07413d..6017e95 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,7 +26,8 @@ AUTOMAKE_OPTIONS = foreign SUBDIRS = man -bin_PROGRAMS = listbasic \ +bin_PROGRAMS = createhdf \ + listbasic \ @RZXCHECK@ \ rzxdump \ rzxtool \ diff --git a/createhdf.c b/createhdf.c new file mode 100755 index 0000000..3acab52 --- /dev/null +++ b/createhdf.c @@ -0,0 +1,220 @@ +/* createhdf.c: Create an empty .hdf file + Copyright (c) 2004 Philip Kendall + + $Id$ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Author contact information: + + Philip Kendall + Postal address: 15 Crescent Road, Wokingham, Berks, RG40 2DB, England + +*/ + +#include + +#include +#include +#include +#include +#include + +const char *progname; + +#define HDF_HEADER_LENGTH 0x80 + +enum { + + HDF_SIGNATURE_OFFSET = 0x00, + HDF_VERSION_OFFSET = 0x07, + HDF_COMPACT_OFFSET = 0x08, + HDF_DATA_OFFSET_OFFSET = 0x09, + HDF_IDENTITY_OFFSET = 0x16, + +}; + +static const char *HDF_SIGNATURE = "RS-IDE\x1a"; +static const size_t HDF_SIGNATURE_LENGTH = 7; +static const char HDF_VERSION = '\x10'; +static const size_t HDF_DATA_OFFSET = 0x80; + +enum { + + IDENTITY_CYLINDERS_OFFSET = 0x02, + IDENTITY_HEADS_OFFSET = 0x06, + IDENTITY_SECTORS_OFFSET = 0x0c, + +}; + +#define CHUNK_LENGTH 1 << 20 + +int +parse_options( int argc, char **argv, size_t *cylinders, size_t *heads, + size_t *sectors, int *compact, int *sparse, + const char **filename ) +{ + int c; + + while( ( c = getopt( argc, argv, "cs" ) ) != -1 ) { + + switch( c ) { + + case 'c': *compact = 1; break; + case 's': *sparse = 0; break; + + } + } + + if( argc - optind < 4 ) { + fprintf( stderr, + "%s: usage: %s [-c] [-s] \n", + progname, progname ); + return 1; + } + + *cylinders = atoi( argv[ optind++ ] ); + *heads = atoi( argv[ optind++ ] ); + *sectors = atoi( argv[ optind++ ] ); + *filename = argv[ optind++ ]; + + return 0; +} + +int +write_header( FILE *f, size_t cylinders, size_t heads, size_t sectors, + int compact, const char *filename ) +{ + char hdf_header[ HDF_HEADER_LENGTH ], *identity; + size_t bytes; + + memset( hdf_header, 0, HDF_HEADER_LENGTH ); + + memcpy( &hdf_header[ HDF_SIGNATURE_OFFSET ], HDF_SIGNATURE, + HDF_SIGNATURE_LENGTH ); + hdf_header[ HDF_VERSION_OFFSET ] = HDF_VERSION; + hdf_header[ HDF_COMPACT_OFFSET ] = compact; + hdf_header[ HDF_DATA_OFFSET_OFFSET ] = ( HDF_DATA_OFFSET ) & 0xff; + hdf_header[ HDF_DATA_OFFSET_OFFSET + 1 ] = ( HDF_DATA_OFFSET >> 8 ) & 0xff; + + identity = &hdf_header[ HDF_IDENTITY_OFFSET ]; + + identity[ IDENTITY_CYLINDERS_OFFSET ] = ( cylinders ) & 0xff; + identity[ IDENTITY_CYLINDERS_OFFSET + 1 ] = ( cylinders >> 8 ) & 0xff; + + identity[ IDENTITY_HEADS_OFFSET ] = ( heads ) & 0xff; + identity[ IDENTITY_HEADS_OFFSET + 1 ] = ( heads >> 8 ) & 0xff; + + identity[ IDENTITY_SECTORS_OFFSET ] = ( sectors ) & 0xff; + identity[ IDENTITY_SECTORS_OFFSET + 1 ] = ( sectors >> 8 ) & 0xff; + + bytes = fwrite( hdf_header, 1, HDF_HEADER_LENGTH, f ); + if( bytes != HDF_HEADER_LENGTH ) { + fprintf( stderr, + "%s: could write only %lu header bytes out of %lu to '%s'\n", + progname, (unsigned long)bytes, (unsigned long)HDF_HEADER_LENGTH, + filename ); + return 1; + } + + return 0; +} + +int +write_data( FILE *f, size_t cylinders, size_t heads, size_t sectors, + int compact, int sparse, const char *filename ) +{ + size_t data_size; + + data_size = cylinders * heads * sectors * ( compact ? 0x100 : 0x200 ); + + if( sparse ) { + + if( fseek( f, data_size - 1, SEEK_CUR ) ) { + fprintf( stderr, "%s: error seeking in '%s': %s\n", progname, filename, + strerror( errno ) ); + return 1; + } + + if( fputc( '\0', f ) == EOF ) { + fprintf( stderr, "%s: error terminating null to '%s'\n", progname, + filename ); + return 1; + } + + } else { + + char buffer[ CHUNK_LENGTH ]; + size_t total_written; + + memset( buffer, 0, CHUNK_LENGTH ); + total_written = 0; + + while( data_size ) { + + char buffer[ CHUNK_LENGTH ]; + size_t bytes_to_write, bytes_written; + + bytes_to_write = data_size > CHUNK_LENGTH ? CHUNK_LENGTH : data_size; + + bytes_written = fwrite( buffer, 1, bytes_to_write, f ); + if( bytes_written != bytes_to_write ) { + fprintf( stderr, "%s: could write only %lu bytes out of %lu to '%s'", + progname, (unsigned long)total_written + bytes_written, + (unsigned long)data_size, filename ); + return 1; + } + + total_written += bytes_to_write; + data_size -= bytes_to_write; + } + } + + return 0; +} + +int +main( int argc, char **argv ) +{ + size_t cylinders, heads, sectors; + int compact, sparse; + const char *filename; + FILE *f; + int error; + + progname = argv[0]; + + compact = 0; + sparse = 1; + error = parse_options( argc, argv, &cylinders, &heads, §ors, &compact, + &sparse, &filename ); + if( error ) return error; + + f = fopen( filename, "wb" ); + if( !f ) { + fprintf( stderr, "%s: error opening '%s': %s\n", progname, filename, + strerror( errno ) ); + return 1; + } + + error = write_header( f, cylinders, heads, sectors, compact, filename ); + if( error ) return error; + + error = write_data( f, cylinders, heads, sectors, compact, sparse, + filename ); + if( error ) return error; + + return 0; +} diff --git a/hacking/ChangeLog b/hacking/ChangeLog index 987ff0c..e591c48 100644 --- a/hacking/ChangeLog +++ b/hacking/ChangeLog @@ -94,3 +94,5 @@ 20040223 Merge changes from fuse-utils_0_6_2 to HEAD. 20040223 TAG: fuse-utils_0_6_2-merge-1 20040616 acconfig.h,configure.in: remove use of acconfig.h. +20040616 .cvsignore,createhdf.c,Makefile.am: add createhdf utility for + creating empty .hdf files.