mirror of
https://github.com/open-simh/simtools.git
synced 2026-02-03 07:11:29 +00:00
file systems. It supports reading and writing as well as a number
of other operations, such as octal dump, file system initialize,
and file system check ("clean").
This was originally maintained as a Subversion repository at
svn://akdesign.dyndns.org/flx/branches/V2.6.
as suggested by Timothe Litt on the SIMH mailing list.
302 lines
7.9 KiB
C
302 lines
7.9 KiB
C
/* handler for "put" command */
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include "flx.h"
|
|
#include "fldef.h"
|
|
#include "doput.h"
|
|
#include "fip.h"
|
|
#include "filename.h"
|
|
#include "fileio.h"
|
|
#include "scancmd.h"
|
|
|
|
typedef struct {
|
|
const char *ext;
|
|
const char *rts;
|
|
} rtsent;
|
|
|
|
const rtsent rtstbl[] = {
|
|
{ "tsk", "...rsx" },
|
|
{ "sav", "rt11 " },
|
|
{ "4th", "forth " },
|
|
{ "bas", "basic " },
|
|
{ "tec", "teco " },
|
|
{ "com", "dcl " },
|
|
{ "alc", "algol " },
|
|
{ "wps", "wpsedt" },
|
|
{ NULL, NULL }};
|
|
|
|
/* check for extension match against runtime system runnable extensions.
|
|
* Return TRUE and rts name if a match, false and zeroes otherwise.
|
|
*/
|
|
|
|
static int checkrts (firqb *f, word16 *rtsname)
|
|
{
|
|
const rtsent *r;
|
|
|
|
for (r = rtstbl; r->ext != NULL; r++) {
|
|
if (strncmp (&(f->cname[7]), r->ext, 3) == 0) {
|
|
cvtnametor50 (r->rts, rtsname);
|
|
return (TRUE);
|
|
}
|
|
}
|
|
rtsname[0] = rtsname[1] = 0;
|
|
return (FALSE);
|
|
}
|
|
|
|
static void putname (void *name) {
|
|
fputs ((char *) name, stdout);
|
|
}
|
|
|
|
void doput (int argc, char **argv)
|
|
{
|
|
char *p, *pp;
|
|
FILE *inf;
|
|
long newsize;
|
|
int newclu;
|
|
word16 rtsname[2];
|
|
char *inspec, *outspec;
|
|
firqb outf;
|
|
firqb tmpf;
|
|
long savelbn;
|
|
int arg, j;
|
|
const char *mode;
|
|
int binmode;
|
|
char answer;
|
|
long bytes, totalbytes, files, insize;
|
|
word dirne;
|
|
byte defprot;
|
|
struct stat sbuf;
|
|
ufdrms1 rms1;
|
|
ufdrms1 *a1;
|
|
ufdrms2 rms2;
|
|
ufdrms2 *a2;
|
|
|
|
if (argc < 2) {
|
|
printf ("Usage: %s put file... dest\n", progname);
|
|
return;
|
|
}
|
|
outspec = argv[--argc];
|
|
if (sw.size == NULL) newsize = 0;
|
|
else {
|
|
newsize = strtoul (sw.size, &p, 10);
|
|
if (*p != '\0') {
|
|
printf ("Invalid size %s\n", sw.size);
|
|
return;
|
|
}
|
|
}
|
|
if (sw.contig == NULL && newsize != 0) {
|
|
newsize = 0;
|
|
printf ("-size switch ignored, -contiguous not specified\n");
|
|
}
|
|
if (!parse (outspec, &outf)) {
|
|
printf ("Invalid destination spec %s\n", outspec);
|
|
return;
|
|
}
|
|
if ((outf.flags & f_name) == 0) {
|
|
for (j = 0; j < 6; j++) outf.name[j] = '?';
|
|
outf.flags |= f_name | f_namw;
|
|
}
|
|
if ((outf.flags & f_ext) == 0) {
|
|
outf.name[7] = '?';
|
|
outf.name[8] = '?';
|
|
outf.name[9] = '?';
|
|
outf.flags |= f_ext | f_extw;
|
|
}
|
|
if (sw.tree == NULL && (outf.flags & f_ppnw) != 0) {
|
|
printf ("Wildcard PPN without -tree not allowed in %s\n",
|
|
outspec);
|
|
return;
|
|
}
|
|
rmountrw (); /* mount disk R/W */
|
|
if (sw.clusiz == NULL) newclu = pcs;
|
|
else {
|
|
newclu = strtol (sw.clusiz, &p, 10);
|
|
if (newclu < 0) {
|
|
newclu = -newclu;
|
|
if (newclu < pcs) newclu = pcs;
|
|
}
|
|
if (*p != '\0' || newclu < pcs || newclu > 128 ||
|
|
(newclu & (-newclu)) != newclu) {
|
|
rumountrw (); /* remember to dismount */
|
|
printf ("Invalid clustersize %s\n", sw.clusiz);
|
|
return;
|
|
}
|
|
}
|
|
if (sw.tree == NULL) {
|
|
if ((dirne = initfilescan (&outf, gfdatrtbl)) == 0) {
|
|
rumountrw (); /* remember to dismount */
|
|
printf ("Account does not exist %s\n", outspec);
|
|
return;
|
|
}
|
|
readlk (dirne);
|
|
if ((savelbn = allocufd (dirne, &outf)) == 0) { /* allocate UFD if needed */
|
|
rumountrw (); /* remember to dismount */
|
|
printf ("No room to allocate UFD\n");
|
|
return;
|
|
}
|
|
}
|
|
files = 0;
|
|
totalbytes = 0;
|
|
for (arg = 0; arg < argc; arg++) {
|
|
inspec = argv[arg]; /* pick up a name */
|
|
mergename (inspec, &outf, sw.tree != NULL);
|
|
/* construct output name */
|
|
if (outf.cproj == 0 && outf.cprog == 0) {
|
|
printf ("Bad directory spec from input filespec %s\n", inspec);
|
|
continue;
|
|
}
|
|
answer = doquery (putname, inspec);
|
|
if (answer == 'q') break;
|
|
if (answer == 'n') continue;
|
|
if (sw.ascii != NULL) binmode = FALSE;
|
|
else if (sw.bswitch != NULL) binmode = TRUE;
|
|
else binmode = !textfile (outf.cname);
|
|
if (binmode) mode = "rb";
|
|
else mode = "r";
|
|
if (sw.debug != NULL) printf ("put mode %s\n", mode);
|
|
if ((inf = fopen (inspec, mode)) == NULL) {
|
|
printf ("Can't open %s\n", inspec);
|
|
perror (progname);
|
|
continue; /* skip this one */
|
|
}
|
|
if (fstat (fileno(inf), &sbuf)) { /* get info about input file */
|
|
printf ("Can't stat input file %s", inspec);
|
|
perror (progname);
|
|
fclose (inf); /* close input */
|
|
continue; /* and carry on */
|
|
}
|
|
insize = UP(sbuf.st_size,BLKSIZE) / BLKSIZE;
|
|
if (sw.tree != NULL) {
|
|
memcpy (&tmpf, &outf, sizeof (firqb));
|
|
tmpf.proj = tmpf.cproj;
|
|
tmpf.prog = tmpf.cprog;
|
|
dirne = initfilescan (&tmpf, gfdatrtbl); /* does PPN exist yet? */
|
|
if (dirne == 0) {
|
|
if (!makedir (&outf, pcs)) {
|
|
printf ("Cannot create PPN [%d,%d]\n",
|
|
outf.cproj, outf.cprog);
|
|
fclose (inf);
|
|
continue;
|
|
}
|
|
if (plevel > RDS0) {
|
|
fbread (curgfd + gfdatrtbl);
|
|
dirne = fibufw[outf.cprog];
|
|
readlktbl (dirne);
|
|
} else {
|
|
dirne = prevppnlink;
|
|
readlk (dirne);
|
|
}
|
|
}
|
|
if ((savelbn = allocufd (dirne, &outf)) == 0) {
|
|
printf ("No room to allocate UFD [%d,%d]\n",
|
|
outf.cproj, outf.cprog);
|
|
fclose (inf);
|
|
continue;
|
|
}
|
|
}
|
|
fbread (savelbn); /* read output directory */
|
|
readlk2 (0); /* read UFD label */
|
|
prevlink = 0; /* start there */
|
|
nextlink = use(ufdlabel,0)->ulnk; /* and initialize scan */
|
|
memcpy (&tmpf, &outf, sizeof (firqb));
|
|
memcpy (tmpf.name, outf.cname, NAMELEN);
|
|
if (nextfileindir (&tmpf)) { /* file exists... */
|
|
if (protfile (&tmpf)) {
|
|
fclose (inf); /* protected file, skip */
|
|
continue;
|
|
}
|
|
if (sw.prot != NULL) {
|
|
printf ("File ");
|
|
printcurname (&tmpf);
|
|
printf (" exist, not replaced\n");
|
|
fclose (inf);
|
|
continue;
|
|
}
|
|
delfile (&tmpf); /* now really delete the file */
|
|
fbread (savelbn); /* read output directory */
|
|
readlk2 (0); /* read UFD label */
|
|
prevlink = 0; /* start there */
|
|
nextlink = use(ufdlabel,0)->ulnk; /* and initialize scan */
|
|
memcpy (tmpf.name, outf.cname, NAMELEN);
|
|
nextfileindir (&tmpf); /* find end of directory */
|
|
}
|
|
outf.clusiz = newclu;
|
|
if (sw.contig == 0) outf.size = 0;
|
|
else {
|
|
if (newsize == 0) outf.size = insize;
|
|
else outf.size = newsize;
|
|
}
|
|
defprot = 60; /* default not runnable */
|
|
if (checkrts (&outf, rtsname)) {
|
|
if (newsize >> 16) { /* if large file */
|
|
printf ("warning: can't set rts for large file ");
|
|
printcurname (&outf);
|
|
outf.newprot &= ~up_run; /* never runnable */
|
|
} else defprot = 124; /* default is now runnable */
|
|
}
|
|
if ((outf.flags & f_prot) == 0) outf.newprot = defprot;
|
|
if (outf.size) outf.stat = us_nox;
|
|
else outf.stat = 0;
|
|
a1 = NULL; /* assume no attributes */
|
|
a2 = NULL;
|
|
memset (&rms1, 0, sizeof(rms1)); /* and clear them in case */
|
|
memset (&rms2, 0, sizeof(rms2));
|
|
if (sw.rmsvar != NULL || sw.rmsfix != NULL ||
|
|
sw.rmsstm != NULL) {
|
|
a1 = &rms1;
|
|
if (sw.rmsvar != NULL) {
|
|
a1->fa_typ = rf_var | fo_seq;
|
|
a2 = &rms2;
|
|
memset (&rms2, 0, sizeof(rms2));
|
|
a2->fa_msz = 512; /* dummy value */
|
|
}
|
|
if (sw.rmsstm != NULL) a1->fa_typ = rf_stm | fo_seq;
|
|
if (sw.rmsfix != NULL) {
|
|
a1->fa_typ = rf_fix | fo_seq;
|
|
a2 = &rms2;
|
|
a1->fa_rsz = strtoul (sw.rmsfix, &pp, 10);
|
|
if (*pp != '\0') a1->fa_rsz = 0;
|
|
a2->fa_msz = a1->fa_rsz;
|
|
insize = (insize / (a1->fa_rsz / BLKSIZE)) *
|
|
(a1->fa_rsz / BLKSIZE);
|
|
insize++;
|
|
}
|
|
a1->fa_siz[0] = a1->fa_eof[0] = insize >> 16;
|
|
a1->fa_siz[1] = a1->fa_eof[1] = insize & 0xffff;
|
|
a1->fa_eofb = 0;
|
|
}
|
|
if (crefile (&outf, rtsname, a1, a2)) {
|
|
bytes = putfile (inf, &outf, binmode);
|
|
if (bytes < 0 || (bytes == 0 && outf.size != 0)) {
|
|
bytes = -bytes;
|
|
printf ("Failure copying %s to ", inspec);
|
|
printcurname (&outf);
|
|
printf (" -- %ld bytes copied in ", bytes);
|
|
if (binmode) printf ("block mode\n");
|
|
else printf ("line mode\n");
|
|
} else if (sw.verbose) {
|
|
printf ("%s =>> ", inspec);
|
|
printcurname (&outf);
|
|
printf (" (%ld bytes) in ", bytes);
|
|
if (binmode) printf ("block mode\n");
|
|
else printf ("line mode\n");
|
|
}
|
|
files++;
|
|
totalbytes += bytes;
|
|
} else {
|
|
printf ("No room to create file ");
|
|
printcurname (&outf);
|
|
printf ("\n");
|
|
}
|
|
fclose (inf);
|
|
}
|
|
if (sw.verbose != NULL)
|
|
printf ("Total files: %ld, total bytes: %ld\n", files, totalbytes);
|
|
rumountrw (); /* done with R/W disk */
|
|
}
|