home *** CD-ROM | disk | FTP | other *** search
- /********************************************************************************/
- /* */
- /* Joinf.c */
- /* Part of Splitf and Joinf distribution */
- /* version 1.13, © 1993-1995 Adam Hamilton */
- /* See the README file for copyright information */
- /* */
- /********************************************************************************/
-
-
- /*********************************/
- /* Include required header files */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include "config.h"
-
-
- /**********************************/
- /* Program macros and definitions */
-
- #define TITLE "File joiner. Version 1.13 - 4th Feburary 1995 by A.Hamilton\n\n"
- #ifndef Bool
- # define Bool char
- #endif
- #define False 0
- #define True !False
- #define MIN(a, b) (a < b ? a : b)
- #define MAX(a, b) (a > b ? a : b)
-
-
-
- /********************************************************************************/
- /* */
- /* Function : usage */
- /* Description : Displays program usage to standard error, and exits. */
- /* Arguments : progname - pointer to character string containing the program */
- /* name. */
- /* Returns : None. */
- /* */
- /********************************************************************************/
-
-
- void usage (char *progname)
- {
- fprintf (stderr, TITLE);
- fprintf (stderr, "Usage : %s [options] <filename>\n\n", progname);
- fprintf (stderr, "Options (can be abbreviated) :\n");
- #ifndef PC
- fprintf (stderr, " -buffersize [buffersize in K] default = 32\n");
- #endif
- fprintf (stderr, " -filename [new filename]\n");
- fprintf (stderr, " -interactive\n");
- fprintf (stderr, " -info\n");
-
- exit (EXIT_FAILURE);
- }
-
-
-
- /********************************************************************************/
- /* */
- /* Function : examine_filename */
- /* Description : Splits filename into component parts. */
- /* Arguments : original_name - character array, filename to be examined. */
- /* name - pointer to a character array in which to store */
- /* file leafname (excluding extention). */
- /* path - pointer to a character array in which to store */
- /* the destination files path. */
- /* Returns : If the destination file has an extention, then return it, */
- /* otherwise return "". */
- /* */
- /********************************************************************************/
-
-
- char *examine_filename (char original_name[], char *name, char *path)
- {
- char main_name[256]; /* Temporary store for leafname. */
- char *original; /* Pointer to start of leafname. */
- char ext[32];
- char *pointer; /* Pointer to any ':' characters found. */
- register int i = -1, n; /* Pointer & counter. */
-
- if (COLON) /* If our system uses ':' in */
- pointer = strrchr (original_name, ':'); /* the file path, then remember */
- else /* where it is. */
- pointer = NULL;
-
- original = strrchr (original_name, SEPARATOR_SEARCH); /* Find the address where the */
- if ((original = MAX (original, pointer)) == NULL) /* leafname starts. */
- original = original_name;
- else {
- original++;
- strncpy (path, original_name, original - original_name); /* Get the path. */
- path[original - original_name] = '\0';
- }
-
- do {
- i++;
- main_name[i] = original[i]; /* Get files leafname */
- } while (main_name[i] != '.' && main_name[i] != '\0'); /* (excluding any extention). */
-
- main_name[i - 2] = '\0'; /* Copy the leafname. */
- strcpy (name, main_name);
-
- if (main_name[i] == '\0') /* If the file doesn't have an */
- return (""); /* extention return an empty string. */
-
- for (n = 0; (ext[n] = original[i]) != '\0'; n++, i++) ; /* Otherwise get the extention */
- return (ext); /* and return it. */
- }
-
-
-
- /********************************************************************************/
- /* */
- /* Function : numtostr */
- /* Description : Converts a number into a 2 didget character string. */
- /* Arguments : number - number to be converted. */
- /* name - pointer to a character array to store the number. */
- /* Returns : None. */
- /* */
- /********************************************************************************/
-
-
- void numtostr (short number, char *name)
- {
- name[0] = (short) (number / 10) + '0';
- name[1] = (number % 10) + '0';
- name[2] = '\0';
- }
-
-
-
- /********************************************************************************/
- /* */
- /* Function : main */
- /* Description : Main control function. */
- /* Arguments : Command line parameters. */
- /* Returns : Exit status. */
- /* */
- /********************************************************************************/
-
-
- int main (int argc, char *argv[])
- {
- char source_filename[256]; /* Source filename. */
- char out_filename[256]; /* Output leafname. */
- char in_path[256]; /* Input path. */
- char file_ext[32]; /* Output extention. */
- char out_name[256]; /* Full output filename. */
- char header[50]; /* Output file header. */
- char fnum[3]; /* Output part number. */
- char *progname; /* Program name. */
- char string[256]; /* Input string. */
- char type[5]; /* Filetype (Acorn systems only). */
- char interactive = 0; /* Interactive status flag. */
- char source_name[256];
- char check_name[256];
-
- short file_number = 0; /* Current part number. */
- short check_number;
- long read_size = 32 * 1024; /* Buffer size (default 32K). */
- long out_position; /* Position within output file. */
- long in_position; /* Position within input file. */
- long bytes_read; /* Number of bytes read. */
- long bytes_written; /* Number of bytes written. */
- long file_length; /* Length of source file. */
- long *buffer; /* Pointer to buffer. */
- int total_number; /* Total number of parts to join. */
- int args; /* Number of command line arguments. */
- int i, n; /* Counters. */
- Bool info = False; /* Display information? */
- FILE *source_file; /* Source file ID. */
- FILE *out_file; /* Output file ID. */
-
- static char splith1[]="Split:"; /* Part 1 header check string. */
- static char splith2[]="Sp:"; /* Part >1 header check string. */
-
-
- #ifdef ACORN
- _kernel_swi_regs regs;
- _kernel_oserror *err;
- #endif
-
- progname = *argv; /* Get the program name. */
-
- in_path[0] = '\0'; /* Set path to CWD. */
- out_filename[0] = '\0'; /* Clear destination filename. */
- source_filename[0] = '\0'; /* Clear source filename. */
-
- args = argc - 1; /* Initialise count of arguments. */
- if (!args) usage (progname); /* If no arguments supplied, show usage.*/
-
- while (args--) {
- argv++; /* Look at next argument. */
-
- if (!strncmp ("-filename", *argv, MAX (2, strlen (*argv)))) { /* -filename */
- if (!args) {
- fprintf (stderr, "Filename required\n\n");
- usage (progname);
- }
- strcpy (out_filename, *++argv); /* Read output filename.*/
- args--;
- }
-
- #ifndef PC
- else if (!strncmp ("-buffersize", *argv, MAX (2, strlen (*argv)))) { /* -buffersize */
- if (!args) {
- fprintf (stderr, "Buffer size required\n\n");
- usage (progname);
- }
- read_size = (long) atoi (*++argv) * 1024; /* Read buffer size. */
- args--;
- }
- #endif
-
- else if (!strncmp ("-interactive", *argv, MAX (2, strlen (*argv)))) /* -interactive */
- interactive = 1;
-
- else if (!strncmp ("-info", *argv, MAX (3, strlen (*argv)))) /* -info */
- info = True;
-
- else {
- strcpy (source_filename, *argv); /* Read source filename.*/
- if (args) usage (progname);
- }
- }
-
- if (source_filename[0] == NULL) {
- fprintf (stderr, "Source filename required\n\n");
- usage (progname);
- }
-
- /* Get file detail from source filename.*/
- strcpy (file_ext, examine_filename (source_filename, source_name, in_path));
-
- source_file = fopen (source_filename, "rb"); /* Open read binary source file. */
- if (source_file == NULL) { /* Report if error, and stop. */
- fprintf (stderr, "Fatal error opening %s for input.\n", source_filename);
- exit (EXIT_FAILURE);
- }
-
- i = 0; /* Initialise counter. */
- while ((header[i++] = fgetc (source_file)) != '|' && i < 300) ; /* Read file header, */
- for (i = 0; i < 6; i++) if (header[i] != splith1[i]) { /* and compare with template. */
- fprintf (stderr,"Fatal error, no split header in file %s\n", source_filename);
- fclose (source_file);
- exit (EXIT_FAILURE);
- }
-
- fseek (source_file, 0L, SEEK_END); /* Set file pointer to end of file, */
- file_length = ftell (source_file); /* get file length */
- fseek (source_file, 0L, SEEK_SET); /* and reset pointer to the start. */
-
- n = 0; /* Initialise counter. */
- #ifdef ACORN
- while (header[i] != '=') { /* Extract output filename, */
- out_name[n++] = (header[i] == '.' ? '/' : header[i]); /* swapping any '.' and '/' */
- i++; /* characters. */
- }
- n++;
- i++;
- #else
- while ((out_name[n++] = header[i++]) != '=') ; /* Just extract the filename, */
- #endif
-
- out_name[--n] = '\0'; /* terminate it properly, */
- if (out_filename[0] == '\0') strcpy (out_filename, out_name); /* and copy. */
-
- n = 0; /* Initialise counter. */
- while ((fnum[n++] = header[i++]) != '=') ; /* Get the total number of */
- fnum[--n] = '\0'; /* parts. */
- total_number = atoi (fnum);
-
- n = 0; /* Initialise counter. */
- while ((type[n++] = header[i++]) != '|') ; /* Read the filetype data. */
- type[--n] = '\0';
-
- if (info) { /* If -info selected, only */
- printf (TITLE); /* print information. */
- printf ("Information :\n\n");
- printf (" Output filename is %s", out_filename);
-
- #ifdef ACORN
- if (type[0] == 't') { /* If the file contains */
- printf (", filetype "); /* filetype data then show it. */
- for (n = 1; type[n] != '\0'; n++)
- printf ("%c", toupper(type[n]));
- }
- #endif
-
- printf ("\n");
- bytes_read = 0;
- }
- else { /* -info not selected, do the joining. */
-
- buffer = (long *) malloc ((size_t) read_size); /* Allocate memory for a buffer. */
- if (buffer == NULL) {
- fprintf (stderr, "Fatal error, unable to allocate memory block of %ld bytes\n", read_size);
- exit (EXIT_FAILURE);
- }
-
- printf ("Using buffer size of %ld bytes.\n", read_size);
-
- #ifdef ACORN
- regs.r[0] = 7; /* Create the file with SWI */
- regs.r[1] = (int) out_filename; /* OS_File 7 */
- regs.r[2] = 0xdeaddead;
- regs.r[3] = 0xdeaddead;
- regs.r[4] = 0;
- regs.r[5] = (int) (file_length * (total_number - 0.5)); /* using an estimated size. */
- if ((err = _kernel_swi (SWI_OS_File, ®s, ®s)) != NULL) {
- fprintf (stderr, "Fatal error opening %s for output:\n-- %s\n", out_filename, err->errmess);
- exit (EXIT_FAILURE);
- }
- #endif
-
- out_file = fopen (out_filename, "wb"); /* Open output file. */
- if (out_file == NULL) { /* Report if error, and stop. */
- fprintf (stderr, "Fatal error opening %s for output.\n", out_filename);
- exit (EXIT_FAILURE);
- }
- }
-
- out_position = 0; /* Initialise output file position pointer. */
-
- for (file_number = 1; file_number <= total_number; file_number++) { /* for each part */
- numtostr (file_number, fnum);
- while (interactive == 1 && file_number > 1) { /* If -interactive selected, */
- printf ("Enter path for %s%s%s (Return for %s) :\n", /* ask for location of next */
- source_name, fnum, file_ext, /* part. */
- in_path[0] == '\0' ? "current directory" : in_path);
-
- gets (string); /* Get output destination. */
- if (strchr (string, ' ') != NULL) {
- printf ("Invalid path name.\n");
- continue;
- }
-
- if (string[0] != '\0') { /* If nothing entered, then use the default. */
- strcpy (in_path, string);
- i = strlen (in_path);
- if (in_path[i - 1] != FILE_SEPARATOR)
- if (!COLON || (COLON && in_path[i - 1] != ':')) {
- in_path[i] = FILE_SEPARATOR;
- in_path[i + 1] = '\0';
- }
-
- }
- interactive = interactive | 2; /* Set flag to say data has been accepted. */
- }
- interactive = interactive & 1; /* Mask off unrequired data. */
-
- /* Create the full input filename. */
- sprintf (source_filename, "%s%s%s%s", in_path, source_name, fnum, file_ext);
-
- if (file_number != 1) { /* If it's not the first part, */
- source_file = fopen (source_filename, "rb"); /* Open read binary file. */
- if (source_file == NULL) { /* Report if error, and stop. */
- fprintf (stderr, "Fatal error opening %s for input.\n", source_filename);
- exit (EXIT_FAILURE);
- }
-
- i = 0; /* Initialise counter. */
- while ((header[i++] = fgetc (source_file)) != '|' && i<300) ; /* Check the header */
- for (i = 0; i < 3; i++) if (header[i] != splith2[i]) { /* with a template. */
- fprintf (stderr,"Fatal error, bad header in file %s\n", source_filename);
- fclose (source_file);
- exit (EXIT_FAILURE);
- }
-
- n = 0; /* Initialise counter. */
- #ifdef ACORN
- while (header[i] != '=') {
- check_name[n++] = (header[i]=='.' ? '/' : header[i]); /* Swap '.' and '/' */
- i++; /* characters and check */
- } /* filename. */
- n++;
- i++;
- #else
- while ((check_name[n++] = header[i++]) != '=') ; /* Just check filename. */
- #endif
-
- check_name[--n] = '\0';
- if (strcmp (out_name, check_name)) { /* Report if error */
- fprintf (stderr,"Fatal error, split file %s does not match.\n", source_filename);
- fclose (source_file);
- exit (EXIT_FAILURE); /* and stop. */
- }
-
- n = 0; /* Initialise counter. */
- while ((fnum[n++] = header[i++]) != '|') ;
- fnum[--n] = '\0';
- check_number = atoi (fnum); /* Get the part number */
- if (check_number != file_number) { /* and make sure it's */
- fprintf (stderr,"Fatal error, incorrect part.\n"); /* one we want. */
- fclose (source_file);
- exit (EXIT_FAILURE);
- }
- }
-
- in_position = (long) i; /* Initialise the input file position pointer. */
-
- fseek (source_file, 0L, SEEK_END); /* Set file pointer to end of file, */
- file_length = ftell (source_file); /* get file length */
- fseek (source_file, in_position, SEEK_SET); /* and reset pointer to start of data. */
-
- if (info) { /* If -info just display information. */
- printf (" %s...%ld bytes\n", source_filename, file_length - in_position);
- bytes_read += file_length - in_position;
- }
- else { /* Otherwise, do the joining. */
- printf ("Reading data from %s.....%ld bytes\n", source_filename, file_length - in_position);
- while (file_length - in_position > 0) { /* If any data */
- bytes_read = fread (buffer, 1, (size_t) read_size, source_file); /* left, read */
- bytes_written = fwrite (buffer, 1, (size_t) bytes_read, out_file); /* and write. */
-
- /* Check we've written the correct amount of data. */
- if (bytes_written < read_size && bytes_written < file_length-in_position) {
- fprintf (stderr, "Fatal error while writing %s\n", out_filename);
- exit (EXIT_FAILURE); /* If unsucessfull, then stop. */
- }
- in_position += bytes_read; /* Update the file position */
- out_position += bytes_written; /* pointers. */
- }
- }
-
- fclose (source_file); /* Close the source file. */
- if (!info && (bytes_written < bytes_read)) {
- fprintf (stderr, "Fatal error while writing %s\n", out_filename);
- exit (EXIT_FAILURE); /* If unsucessfull, stop. */
- }
- }
-
- if (info)
- printf ("\nTotal of %ld bytes contained in %d files.\n", bytes_read, total_number);
-
- else {
- fclose (out_file); /* Close output file */
- free (buffer); /* and free buffer. */
-
- #ifdef ACORN
- if (type[0] == 't') { /* If the file had a type */
- regs.r[0] = 18; /* set the filetype with SWI */
- regs.r[1] = (int) out_filename; /* OS_File 18 */
- sscanf (type, "t%x", ®s.r[2]);
- err = _kernel_swi (SWI_OS_File, ®s, ®s);
- }
- #endif
- /* Report status */
- fprintf (stderr, "%ld bytes written to file %s\n", out_position, out_filename);
- }
- exit (EXIT_SUCCESS); /* and finish. */
- }
-