
/* burt.c - Burst files from a RT-11 volume */
/* Copyright 1994 Syndesis Corporation, by John Foust <jfoust@threedee.com> */
/* March 17, 1998 */

#include <stdio.h>
#include <string.h>

#include "diskdecl.h"

#include "rt11decl.h"
#define PRIMARY
#include "rt11vars.h"


/* Options for file contents translation */

#define XLATE_NOTIME    1   /* -notime : Don't set timestamps */


/* Remove spaces from a string like "UTIL  .SAV" */

void removeSpaces( char *str )
{
char buff[15];
char *srcptr;
char *destptr;


    srcptr = str;
    destptr = buff;
    while (*srcptr != '\0') {

        /* Copy chars if not a space */
        if (*srcptr != ' ') {
            *destptr ++ = *srcptr ++;
        }
        else {
            srcptr ++;
        }
    }
    *destptr = '\0';

    strcpy( str, buff );
}


/* */

int main( int argc, char **argv )
{
USHORT lerr;
int each;
char inname[128];
char newname[16];
FILE *infp;
FILE *outfp;
rtDirRoot dirRoot;
rtFileEntry *eachEntry;
char buff[ 16 ];
USHORT block;
char *lineSpec;
int translate;
BOOL lowercase;
BOOL setTime;
BOOL hasTextExtension;
size_t len;


    infp = NULL;
    outfp = NULL;

    /* Defaults */
    lowercase = FALSE;
    setTime = TRUE;
    doSwab = FALSE;

    if (argc == 1) {
        puts( "Bursts files from RT-11 disk images" );
        puts( "Usage: burt imagefilename [options]" );
     /* puts( "       [-lower] Force filenames to lowercase" ); */
        goto out;
    }

    /* Grab disk image filename */
    if (argc > 1) {
        strcpy( inname, argv[1] );
    }

    /* Look for options */
    if (argc > 2) {
        int each;

        for (each=2; each<argc; each++) {

            /* Don't set timestamps */
            if (strcmp( argv[each], "-notime" ) == 0) {
                translate = XLATE_NOTIME;
            }

            /* make lowercase filenames */
            if (strcmp( argv[each], "-lower" ) == 0) {
                lowercase = TRUE;
            }
        }
    }

    /* Open input file from command line */
    printf( "Directory of RT-11 disk image file '%s'\n\n", inname );
    infp = fopen( inname, "rb" );
    if (infp == NULL) {
        puts("Couldn't open file.");
        goto out;
    }

    /* Read volume info, including 72 file entries */
    if ((lerr=readRT11VolInfo( infp, &dirRoot )) != TE_NOERROR) {
        puts( "Failed on volume info." );
        goto out;
    }

    /* Print volume info header */
    printf( "segs %hu, next %hu, high %hu, filler %hu, begin %hu\n\n",
        dirRoot.segsAvailable, dirRoot.nextSegment, dirRoot.highSegment,
        dirRoot.filler, dirRoot.beginSegment );

    /* Header */
    printf( "              Size  Block   Date\n" );

    /* Format specifier for each line */
    lineSpec = "  %-11s  %3hu  %4hu";

    /* Burst each entry */
    outfp = NULL;
    block = dirRoot.beginSegment;
    eachEntry = &dirRoot.files[0];
    for (each=0; each<RT_NUM_FILES; each++) {

        /* If no more files */
        if (eachEntry->status == RT_ENDMARK) {
            break;
        }
        /* If a temporary file */
        else if (eachEntry->status == RT_TENTATIVE) {
            printf( lineSpec, "<temp>", eachEntry->length, block );
            /* Always have date of 0 */
            printf( "\n" );
        }
        /* If empty space, like at end of list */
        else if (eachEntry->status == RT_EMPTY) {
            printf( lineSpec, "<empty>", eachEntry->length, block );
            /* Always have date of 0 */
            printf( "\n" );
        }
        /* If a permanent file */
        else if (eachEntry->status == RT_PERM) {

            /* Convert RAD-50 filename to ASCII, including extension '.' */
            rad50ToAscii( eachEntry->name[0], &buff[0] );
            rad50ToAscii( eachEntry->name[1], &buff[3] );
            buff[6] = '.';
            rad50ToAscii( eachEntry->name[2], &buff[7] );
            buff[10] = '\0';

            /* Build the file name */
            strcpy( newname, buff );

            /* Print directory-like line */
            printf( lineSpec, buff, eachEntry->length, block );

            /* Print date */
            rtDateStr( eachEntry->date, buff );
            printf( "  %s\n", buff );

            /* Notice if the filename has ".TXT" extension */
            hasTextExtension = FALSE;
            len = strlen( newname );
            if (len > 4) {
                if (strcmp( &newname[ len - 5 ], ".TXT" ) == 0) {
                    hasTextExtension = TRUE;
                }
            }

            /* Could make an option to force filenames to lower-case */
            if (lowercase == TRUE) {
                strLower( newname );
            }

            /* Translate the filename to something WinNT-compatible */
            makeWinNTname( newname );

            /* Remove embedded spaces like "UTIL  .SAV" */
            removeSpaces( newname );

            /* Open the output file */
            outfp = fopen( newname, "wb" );
            if (outfp == NULL) {
                printf( "Couldn't open file '%s' (skipped)\n", newname );
                /* goto out; */
            }

            if (outfp != NULL) {
                int bk;
                char wrbuf[ RT11_BLK_SIZE ];


                /* Seek to current block */
                fseek( infp, (long) RT11_BLK_SIZE * block, SEEK_SET );

                /* Read-write subsequent blocks */
                for (bk=0; bk<eachEntry->length; bk++) {
                    if (fread( &wrbuf[0], (size_t) RT11_BLK_SIZE, (size_t) 1, infp ) != 1) {
                        printf( "Read of block %hd failed\n", bk );
                    }
                    fwrite( &wrbuf[0], (size_t) RT11_BLK_SIZE, (size_t) 1, outfp );
                }

                /* Close the file */
                fclose( outfp );
                outfp = NULL;

                /* Set timestamp of file */
                if (setTime == TRUE) {
                    rtSetTimeStamp( newname, eachEntry );
                }
            }
        }
        else {
            printf( "Unknown status %hu 0x%04hx\n", eachEntry->status, eachEntry->status );
        }

        /* Keep track of which block we're at */
        block += eachEntry->length;

        eachEntry ++;
    }

out:
    if (infp != NULL) {
        fclose( infp );
        infp = NULL;
    }
    if (outfp != NULL) {
        fclose( outfp );
        outfp = NULL;
    }

    return 0;
}


/* Improvements:

  RT-11 text files have DOS-style CR/LF line endings.
  Could have an option to translate them to Unix LF endings.

  Could perform a sanity check to see if the disk looks like RT-11.
  Terak diagnostic self-boot no-OS disks are not RT-11 or UCSD.
*/

