add first WEGA commands

This commit is contained in:
Oliver Lehmann 1989-02-03 07:49:07 +00:00
parent 2adeef252b
commit 47af93dcbc
3 changed files with 1764 additions and 0 deletions

View File

@ -0,0 +1,46 @@
/**************************************************************************
**************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone: sa.cat.c
Bearbeiter : P. Hoge
Datum : 04/01/87 11:15:40
Version : 1.1
**************************************************************************
**************************************************************************/
/* standalone cat */
char buf[0x200];
main()
{
register c, i, t;
do {
printf("File: ");
gets(buf, 100);
if (buf[0] == 0)
exit(1);
i = open(buf, 0);
} while (i <= 0);
for (t=0; (c=getc(i)) != -1;) {
if (c == 0x0a || (c >= 0x20 && c < 0x7f)) {
putchar(c);
t = ++t & 0x0007;
}
if (c == 0x09) {
do {
putchar(0x20);
t = ++t & 0x0007;
}while (t != 0);
}
}
exit(0);
}

View File

@ -0,0 +1,971 @@
/******************************************************************************
*******************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1986
KOMMANDO install.c
Bearbeiter: N. Taege
Datum: 6.1.88
Version: 3.0
*******************************************************************************
******************************************************************************/
/* notwendig: -rw-r--r-- 1 bin system 2188 Mar 5 13:53 /lib/libb.a */
#include "sys/param.h"
#include "sys/ino.h"
#include "sys/inode.h"
#include "sys/filsys.h"
#include "sys/fblk.h"
#include "sys/dir.h"
/*--------------------------------------------- Konstanten ------------------*/
#define LCONT 15 /* max. Laenge der CONTENTS */
/*--------------------------------------------- Variable ------------------*/
int fsi, fdi, fdo; /* fopen-Werte von Source und Destination */
char *contp, CONT[LCONT*BSIZE]; /* CONTENTS - Puffer */
char CON[] = "CONTENTS";
char conline[50]; /* CONTENTS-Zeile */
char fddname[40] = "ud(0,0)"; /* floppy-disk-driver- & udos-file-name */
char hddname[20] = "md(0,0)"; /* hard-disk-driver-name (/usr) */
char estring[10]; /* Eingabe-Zeichenkette */
union {
struct fblk fb;
char pad1[BSIZE];
} fbuf;
union {
struct filsys fs;
char pad2[BSIZE];
} filsys;
struct dinode pin; /* inode der parent-Directory */
struct dinode iin; /* inode des zu installierenden Files */
long time; /* Zeit in Sekunden ab 1970 */
static int dmsize[12] = /* Tage/Monat (kumulierend) */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
long zdb[12]; /* Blocknummern im inode */
long adb[128]; /* einfach indirekt Adressblock */
long iadb[128]; /* zweifach indirekt Adressblock */
daddr_t aadb, aiadb; /* Blocknummern der Adressbloecke */
int padb, piadb, pzdb; /* Pointer in den Adressbloecken */
ino_t parinumb, inumb, oldinumb;
daddr_t apardir;
char pardir[BSIZE], parinob[BSIZE], inob[BSIZE];
int ppnidb;
int abfr; /* 0 = abfragen, 1 = a, 2 = A, 3 = q, 4 = Q */
char *aeintr; /* Adr(Dir.-Eintrag) */
daddr_t alloc();
long getnum();
ino_t sun(), alloci();
unsigned int get2b();
unsigned long get3b();
/*--------------------------------------------- Funktion ------------------*/
/*
* Das Standalone Modul sa.install dient der Installation der File-Systeme
* auf der Hard-Disk des P8000
*/
/*---------------------------------------------------------------------------*/
main()
{
register i;
indate(); /* Datum eingeben */
rmopen(0); /* remote open mit Abfrage */
for (i=1; i<5; i++) {
printf("\noutput file system : ");
gets(hddname, sizeof hddname);
if (hddname[0] == '\0') {
hddname[0] = 'm';
printf("%s\n", hddname); }
fdo = open(hddname, 1);
fdi = open(hddname, 0);
if (fdo<0 || fdi<0)
printf("cannot open %s\n", hddname);
else break; }
if (i == 5) exit(0);
for (i=0; i<128; pardir[i++]=0); /* parent-Directory loeschen */
rdfs((long)1, (char *)&filsys); /* read Superblock */
rddisk:
abfr = 0;
while (*contp != '\0') {
switch (*contp) {
case '/':
/*
* Directory - Definitions - Zeile
*/
if (abfr == 4) {
getstr(); /* bei eingegebenem 'Q' : Zeile ueberspringen */
break; }
if (abfr == 1 || abfr == 3) abfr = 0; /* 'a'- und 'q'-Mode beenden */
wpar(); /* write parent-Directory-Block u. inode */
parinumb = 2;
rindi(); /* read root-inode-Block u. 1.root-Directory-Block */
printf("%s\n", contp);
contp++;
rdloop:
if (*contp == '\0') {
contp++;
break; }
holdn(); /* Dir.-Namen aus CONT-Zeilenstueck in conline holen */
parinumb = sun(0); /* Directory-Namen in pardir suchen */
if (parinumb == 0) {
printf("\ndirectory %s not found\n", conline);
insend(); }
rindi(); /* Lese inode-Block u. 1.Directory-Block */
goto rdloop;
case 'l':
/*
* nlink - Zeile
*/
if (testab() == 0) break;
getstr();
getstr();
if (sun(1)) {
printf("\nlink-file: %s already exist; cannot overwrite !\n", conline);
break; }
iin.di_nlink++;
cfilend();
break;
case 'd':
case 'b':
case 'c':
case '-':
case 'n':
/*
* create - file - Zeile
*/
if (testab() == 0) break;
cfile();
break;
default:
printf("syntax error in CONTENTS\n");
printf("last instruction: %s\n",conline);
printf("next characters (hexadecimal): %x ", *contp++ & 0xFF);
printf("%x %x ", *contp++ & 0xFF, *contp++ & 0xFF);
printf("%x %x etc.\n", *contp++ & 0xFF, *contp++ & 0xFF);
insend();
}
}
loopnd:
printf("\n\007next input disk ? (y/n) : ");
gets(estring, sizeof estring);
switch (estring[0]) {
case 'Y':
case 'y':
rmopen(1); /* remote open ohne Eingabe */
goto rddisk;
case 'N':
case 'n':
insend();
default:
goto loopnd; }
}
/*---------------------------------------------------------------------------*/
/*
* Aussprung aus sa.install
*/
/*---------------------------------------------------------------------------*/
insend()
{
wpar(); /* write Parent-Dir. */
filsys.s_time = time; /* setze Superblock-Zeit */
wtfs((long)1, (char *)&filsys); /* write Superblock */
exit(0);
}
/*---------------------------------------------------------------------------*/
/*
* Lese Block (bno) von der Hard-Disk in den Puffer (bf)
*/
/*---------------------------------------------------------------------------*/
rdfs(bno, bf)
daddr_t bno;
char *bf;
{
register n;
lseek(fdi, bno*BSIZE, 0);
n = read(fdi, bf, BSIZE);
if (n != BSIZE) {
printf("read error: %ld\n", bno);
insend(); }
}
/*---------------------------------------------------------------------------*/
/*
* Schreibe Puffer (bf) in den Block (bno) der Hard-Disk
*/
/*---------------------------------------------------------------------------*/
wtfs(bno, bf)
daddr_t bno;
char *bf;
{
register n;
lseek(fdo, bno*BSIZE, 0);
n = write(fdo, bf, BSIZE);
if (n != BSIZE) {
printf("write error: %ld\n", bno);
insend(); }
}
/*---------------------------------------------------------------------------*/
/*
* Stelle einen freien Block (= Return-Wert) zu Verfuegung
*/
/*---------------------------------------------------------------------------*/
daddr_t
alloc()
{
register i;
register daddr_t bno;
filsys.s_tfree--;
bno = filsys.s_free[--filsys.s_nfree];
if (bno == 0) {
printf("\nout of free space\n");
insend(); }
if (filsys.s_nfree == 0) {
rdfs(bno, (char *)&fbuf);
filsys.s_nfree = fbuf.df_nfree;
for (i=0; i < NICFREE; i++)
filsys.s_free[i] = fbuf.df_free[i];
}
return(bno);
}
/*---------------------------------------------------------------------------*/
/*
* Speichere einen freigewordenen Block zurueck in die Freiblock-Liste
*/
/*---------------------------------------------------------------------------*/
bfree(bno)
register daddr_t bno;
{
register i;
filsys.s_tfree++;
if (filsys.s_nfree == NICFREE) {
clear(&fbuf, BSIZE);
fbuf.df_nfree = filsys.s_nfree;
for (i=0; i < NICFREE; i++)
fbuf.df_free[i] = filsys.s_free[i];
wtfs(bno, (char *)&fbuf);
filsys.s_nfree = 0; }
filsys.s_free[filsys.s_nfree++] = bno;
}
/*---------------------------------------------------------------------------*/
/*
* open remote
*/
/*---------------------------------------------------------------------------*/
rmopen(out)
register out;
{
register size, c, i;
for (i=1; i<5; i++) {
if (out == 0) {
printf("\ninput file system : ");
gets(fddname, sizeof fddname); }
if (fddname[0] == '\0') {
fddname[0] = 'u';
printf("%s\n", fddname); }
adname(CON);
fsi = open(fddname, 0);
if (fsi<0) {
printf("cannot open %s\n", fddname);
out = 0; }
else break; }
if (i == 5) insend();
size = 0;
for (i=1; i <= LCONT; i++) {
c = read(fsi, &CONT[size], BSIZE);
if (c < 0) insend();
size += c;
if (c < BSIZE) break; }
if (i > LCONT) {
printf("\nCONTENTS to long\n");
insend(); }
close(fsi);
for (i=0; i <= size; i++)
if (CONT[i] == '\r' || CONT[i] == '\n') CONT[i] = '\0';
for (--i; i < LCONT*BSIZE; i++) CONT[i] = '\0';
contp = CONT;
}
/*---------------------------------------------------------------------------*/
/*
* Eingabe des Datums
* Gueltig: 1.1.70 - 18.1.2038
*/
/*---------------------------------------------------------------------------*/
indate()
{
int year, month, day, hour;
loop:
printf("Enter Date (MM/DD/YY) : ");
gets(estring, sizeof estring);
month = getdat(1);
day = getdat(2);
year = getdat(3);
hour = 6; /* -1h fuer localtime und timezone */
if (month<1 || month>12 || day<1 || day>31)
goto loop;
time = 0;
if (year%4 == 0 && month > 2) ++dmsize[month-1];
if (year < 70) year += 100;
time = (year-69)/4;
time += 365*(year-70)+dmsize[month-1];
time += day - 1;
if (time > 24854) {
printf("can only create date from 1/1/(19)70 to 1/18/(20)38\n");
goto loop; }
time = 24*time + hour;
time = 60*60*time;
}
getdat(k)
int k;
{
register i, c, n;
n = 0;
for (i=0; c=estring[i]; i++) {
if (k-1 == 0) {
if (c == '/') return(n);
if (c < '0' || c > '9') return(-1);
n = n*10 + (c-'0'); }
else if (c == '/') k--; }
return(n);
}
/*---------------------------------------------------------------------------*/
/*
* Haenge UDOS-Dateinamen (*pt) an Drivernamen (fddname) an
*/
/*---------------------------------------------------------------------------*/
adname(pt)
char *pt;
{
register i;
for (i=0; (fddname[i] != ')') && (i < 20); i++);
do { i++;
fddname[i] = *pt;
pt++;
} while (*pt != '\0' && *pt != ' ');
fddname[++i] = '\0';
}
/*---------------------------------------------------------------------------*/
/*
* Lese Inode und zugehoerigen 1.Directory-Block
*/
/*---------------------------------------------------------------------------*/
rindi()
{
rdfs((long)((parinumb-1)>>3)+2, parinob);
copy(&pin, parinob+(parinumb-1)%8*64);
ppnidb = 1;
apardir = get3b(pin.di_addr);
rdfs(apardir, pardir);
}
/*---------------------------------------------------------------------------*/
/*
* Hole Dir.-Namen aus der Dir.-Definition-Zeile (CONT) in Puffer (conline)
*/
/*---------------------------------------------------------------------------*/
holdn()
{
register i;
for (i=0; i < 50; i++) {
conline[i] = *(contp++);
if (*contp == '/' || *contp == '\0') {
conline[i+1] = '\0';
if (*contp == '/') contp++;
break; }
}
}
/*---------------------------------------------------------------------------*/
/*
* Suche Namen (conline) in den 10 dir. Bloecken der Directory (pardir)
*/
/*---------------------------------------------------------------------------*/
ino_t
sun(c)
register c;
{
register i, j, k;
register ino_t inonb;
long z;
loop:
k=1;
for (i=0; i<32; i++) {
if ((inonb = get2b(aeintr = &pardir[i*16])) == 0) return(0);
k=0;
for (j=0; j<15; j++) {
if (pardir[i*16+2+j] != conline[j]) {
k++;
break; }
if (conline[j] == '\0') break; }
if (k == 0) return(inonb); }
if (ppnidb <= 10) {
if ((z = get3b(&pin.di_addr[3*ppnidb])) == 0) {
if (c==0) return(0); /* nur suchen */
wtfs(apardir, pardir); /* creiere neuen Block*/
z=alloc();
rdfs(z,pardir);
for (j=0; j<BSIZE; j++) pardir[j]=0;
ltol3(&pin.di_addr[3*ppnidb], &z, 1); }
else rdfs(z, pardir);
ppnidb++;
apardir = z;
goto loop; }
else {
/* Directory hat mehr als 10 Bloecke (= 318 Files) */
printf("\ndirectory too long !\n");
insend(); }
return(0);
}
/*---------------------------------------------------------------------------*/
/*
* Schreibe parent-Directory-Block und parent-Inode
*/
/*---------------------------------------------------------------------------*/
wpar()
{
if (parinumb && oldinumb) {
if (pardir[0] || pardir[1]) { /* beim 1.Mal ist pardir 0 */
wtfs(apardir, pardir);
if (((parinumb-1)>>3) != ((oldinumb-1)>>3)) {
wtfs((long)((oldinumb-1)>>3)+2, inob);
rdfs((long)((parinumb-1)>>3)+2, parinob);
copy(parinob+(parinumb-1)%8*64, &pin);
wtfs((long)((parinumb-1)>>3)+2, parinob); }
else {
copy(inob+(parinumb-1)%8*64, &pin);
wtfs((long)((oldinumb-1)>>3)+2, inob); }
} }
}
/*---------------------------------------------------------------------------*/
/*
* Test der Zelle abfr und Reaktion darauf
*/
/*---------------------------------------------------------------------------*/
testab()
{
if (abfr > 2) {
while (*contp != '\0') ++contp;
contp++;
return(0); }
printf("%s", contp);
if (abfr) printf("\n");
else {
loop:
printf(" (n/y/a/A/q/Q) ? : ");
gets(estring, sizeof estring);
switch (estring[0]) {
case 'a':
abfr = 1;
goto caseY;
case 'A':
abfr = 2;
case 'y':
case 'Y':
caseY:
return(1);
case 'q':
abfr = 3;
goto caseN;
case 'Q':
abfr = 4;
case 'n':
case 'N':
caseN:
while (*contp != '\0') ++contp;
contp++;
return(0);
default:
goto loop;
}
}
return(1); /* fuer 'a' und 'A' */
}
/*---------------------------------------------------------------------------*/
/*
* Directories und special-Files creieren und regular-Files laden
*/
/*---------------------------------------------------------------------------*/
cfile()
{
char db[BSIZE];
register i, c, nullfile;
ino_t dupinumb;
struct dinode dupin;
nullfile = 0;
for (i=0; i<BSIZE; db[i++]=0); /* loesche Datenpuffer 'db' */
clear(&iin, 64); /* loesche Strucktur 'iin' */
iin.di_atime = iin.di_mtime = iin.di_ctime = time;
padb = piadb = pzdb = 0;
for (i=0; i<12; zdb[i++]=0);
getstr();
if (conline[0] == 'n') {
conline[0] = '-';
nullfile++; }
iin.di_mode = gmode(conline[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
iin.di_mode |= gmode(conline[1], "-u" , 0, ISUID, 0, 0);
iin.di_mode |= gmode(conline[2], "-g" , 0, ISGID, 0, 0);
iin.di_mode |= gmode(conline[3], "-t" , 0, ISVTX, 0, 0);
for (i=4; i<7; i++) {
c = conline[i];
if (c < '0' || c > '7') {
printf("\nbad octal digit %x in %s\n", c, conline);
insend(); }
iin.di_mode |= (c-'0')<<(18-3*i); }
iin.di_uid = getnum();
iin.di_gid = getnum();
iin.di_nlink = 1;
inumb = alloci();
switch (iin.di_mode & IFMT) {
case IFREG:
getstr(); /* UDOS-Filename */
adname(conline);
if (*--contp) getstr(); /* wega-Filename */
else contp++;
if (dupinumb = sun(1)) {
rdfs((long)((dupinumb-1)>>3)+2, db);
copy(&dupin, db+(dupinumb-1)%8*64);
if (dupin.di_nlink) {
printf("file: %s already exist\n", conline);
loop:
printf("overwrite (y/n/q) ? : ");
gets(estring, sizeof estring);
switch (estring[0]) {
case 'y':
pin.di_size -= 0x10;
if (dupin.di_nlink != 1)
iin.di_nlink = dupin.di_nlink;
bfinfree(dupin.di_addr);
if (((dupinumb-1)>>3) != ((oldinumb-1)>>3)) {
db[(dupinumb-1)%8*64] = 0;
db[(dupinumb-1)%8*64+1] = 0;
wtfs((long)((dupinumb-1)>>3)+2, db); }
else {
inob[(dupinumb-1)%8*64] = 0;
inob[(dupinumb-1)%8*64+1] = 0; }
ifree(inumb); /* set inumber free */
inumb = dupinumb;
break;
case 'q':
abfr = 3; /* Abbruch fuer akt. Dir. */
case 'n':
ifree(inumb);
return;
default:
goto loop;
} } }
if (nullfile) break;
loopopen:
fsi = open(fddname, 0);
/* Achtung: ab 'open' bis 'close' ist kein E/A-Verkehr ueber tty moeglich !!! */
if (fsi<0) {
loopno:
printf("repeat (y/n/q) ? : ");
gets(estring, sizeof estring);
switch (estring[0]) {
case 'y':
goto loopopen;
case 'q':
abfr = 3; /* Abbruch fuer akt. Dir. */
case 'n':
ifree(inumb);
return;
default:
goto loopno; } }
while ((i=read(fsi, db, BSIZE)) > 0) {
iin.di_size += i;
newblk(db); }
close(fsi);
if (i < 0) {
if (piadb) wtfs(aiadb, iadb);
if (padb) wtfs(aadb, adb);
if (pzdb) ltol3(iin.di_addr, zdb, pzdb);
bfinfree(iin.di_addr);
loopre:
printf("repeat (y/n/q) ? : ");
gets(estring, sizeof estring);
switch (estring[0]) {
case 'y':
iin.di_size = 0;
padb = piadb = pzdb = 0;
for (i=0; i<12; zdb[i++]=0);
goto loopopen;
case 'q':
abfr = 3; /* Abbruch fuer akt. Dir. */
case 'n':
ifree(inumb);
return;
default:
goto loopre; } }
ltol3(iin.di_addr, zdb, pzdb);
if (padb) wtfs(aadb, adb);
if (piadb) wtfs(aiadb, iadb);
break;
case IFBLK:
case IFCHR:
i = getnum() & 0xFF; /* majory number */
c = getnum() & 0xFF; /* minory number */
iin.di_addr[1] = i;
iin.di_addr[2] = c;
getstr();
if(sun(1)) {
printf("\nspecial-file: %s already exist; cannot overwrite !\n", conline);
ifree(inumb);
return; }
break;
case IFDIR:
getstr();
if (sun(1)) {
printf("\ndirectory: %s already exist; cannot overwrite !\n", conline);
ifree(inumb);
return; }
entry(&inumb, ".", db);
entry(&parinumb, "..", &db[16]);
newblk(db);
ltol3(iin.di_addr, zdb, pzdb);
iin.di_nlink++;
iin.di_size = 0x20;
++pin.di_nlink;
break;
default:
printf("\ndi_mode - Fehler\n");
insend(); }
cfilend();
}
/*---------------------------------------------------------------------------*/
/*
* cfile-Ende-Behandlung
*/
/*---------------------------------------------------------------------------*/
cfilend()
{
if (oldinumb && (((inumb-1)>>3) != (oldinumb-1)>>3))
wtfs((long)((oldinumb-1)>>3)+2, inob);
if (((inumb-1)>>3) != ((oldinumb-1)>>3))
rdfs((long)((inumb-1)>>3)+2, inob);
copy(inob+(inumb-1)%8*64, &iin);
oldinumb = inumb;
pin.di_size += 0x10;
entry(&inumb, conline, aeintr);
}
/*---------------------------------------------------------------------------*/
/*
* Uebertrage akt. Teil einer Anweisung von CONT nach conline[]
*/
/*---------------------------------------------------------------------------*/
getstr()
{
register i;
register char c;
loop:
switch (c = *contp++) {
case ' ':
goto loop; }
i = 0;
do { conline[i++] = c ; c = *contp++; }
while (c != ' ' && c != '\0');
conline[i] = '\0';
}
/*---------------------------------------------------------------------------*/
/*
* Eintragen des Parameters m0,...,m3 in den Return-Wert
*/
/*---------------------------------------------------------------------------*/
gmode(c, s, m0, m1, m2, m3)
char c;
register char *s;
{
if (c == s[0])
return(m0);
if (c == s[1])
return(m1);
if (c == s[2])
return(m2);
if (c == s[3])
return(m3);
printf("\nbad charakter %x in %s\n", c, conline);
insend();
return(0);
}
/*---------------------------------------------------------------------------*/
/*
* Dezimale Eingabekonvertierung aus conline
*/
/*---------------------------------------------------------------------------*/
long
getnum()
{
register i, c;
register long n;
getstr();
n = 0;
for (i=0; c=conline[i]; i++) {
if (c < '0' || c > '9') {
printf("\nbad decimal digit %x in %s\n", c, conline);
insend(); }
n = n*10 + (c-'0'); }
return(n);
}
/*---------------------------------------------------------------------------*/
/*
* Loesche strukturierten Puffer *pt der Laenge l
*/
/*---------------------------------------------------------------------------*/
clear(pt, l)
register l;
register char *pt;
{
register i;
for (i=0; i<l; *pt++ = '\0', i++);
}
/*---------------------------------------------------------------------------*/
/*
* Copiere Inode (str1) := (str2)
*/
/*---------------------------------------------------------------------------*/
copy(str1, str2)
register char *str1, *str2;
{
register i;
for (i=0; i<64; *str1++ = *str2++, i++);
}
/*---------------------------------------------------------------------------*/
/*
* Gebe im Return-Wert freie inode-Nr. zurueck
*/
/*---------------------------------------------------------------------------*/
ino_t
alloci()
{
register i, j, k;
register ino_t inr;
char bf[BSIZE];
filsys.s_tinode--;
if (filsys.s_ninode == 0) { /* inode Liste fuellen */
for (i=0; i<filsys.s_isize; i++) {
if (i == (oldinumb-1)>>3)
for (j=0; j<BSIZE; j++) bf[j] = inob[j];
else rdfs((long)i+2, bf);
for (j=0; j<8; j++) {
if (get2b(&bf[64*j]) == 0) {
filsys.s_ninode++;
k = 100-filsys.s_ninode;
filsys.s_inode[k] = j+1+i*8;
if (filsys.s_ninode == 100)
goto holinr; } } }
printf("\nout of free inodes\n");
insend(); }
holinr: /* hole inode-Nr. */
inr = filsys.s_inode[--filsys.s_ninode];
return(inr);
}
/*---------------------------------------------------------------------------*/
/*
* Gebe eine freigewordene inode zurueck in die Frei-inode-Liste
*/
/*---------------------------------------------------------------------------*/
ifree(inb)
register ino_t inb;
{
filsys.s_tinode++;
if (filsys.s_ninode == NICINOD) return;
filsys.s_inode[filsys.s_ninode++] = inb;
}
/*---------------------------------------------------------------------------*/
/*
* Gebe Bloecke aus inode wieder frei
*/
/*---------------------------------------------------------------------------*/
bfinfree(pnt)
register pnt;
{
daddr_t bn;
register i, j;
long addrb[12], bf[128], ibf[128];
l3tol(addrb, pnt, 12);
for (i=0; i<10; i++) {
if (bn = addrb[i]) bfree(bn);
else return; }
if (bn = addrb[10]) {
rdfs(bn, bf);
bfree(bn);
for (i=0; i<128; i++) {
if (bn = bf[i]) bfree(bn);
else return; } }
else return;
if (bn = addrb[11]) {
rdfs(bn, ibf);
bfree(bn);
for (i=0; i<128; i++) {
if (bn = ibf[i]) {
rdfs(bn, bf);
bfree(bn);
for (j=0; j<128; j++) {
if (bn = bf[j]) bfree(bn);
else return; } }
else return; } }
}
/*---------------------------------------------------------------------------*/
/*
* Speicher Block (db) auf Hard-Disk und notiere es im inode (ib)
*/
/*---------------------------------------------------------------------------*/
newblk(db)
char *db;
{
register i;
register daddr_t bno;
bno = alloc();
wtfs(bno, db);
for (i=0; i<BSIZE; db[i++]=0);
if (pzdb < 10) { /* direkte Bloecke */
zdb[pzdb++] = bno;
return; }
/* dreifach indirekt wird nicht realisiert */
if (piadb == 0 && padb == 0 && pzdb == 12) {
printf("\nfile to long\n");
insend(); }
/* Start: zweifach indirekt */
if (piadb == 0 && padb == 0 && pzdb == 11) {
aiadb = alloc();
for (i=0; i<128; iadb[i++]=0);
zdb[pzdb++] = aiadb; }
/* Start: einfach indirekt */
if (padb == 0) {
aadb = alloc();
for (i=0; i<128; adb[i++]=0);
if (pzdb == 12) iadb[piadb++] = aadb; /* auch bei zweifach indirekt */
else zdb[pzdb++] = aadb; }
adb[padb++] = bno;
if (piadb == 128) {
wtfs(aiadb, iadb);
piadb = 0; }
if (padb == 128) {
wtfs(aadb, adb);
padb = 0; }
}
/*---------------------------------------------------------------------------*/
/*
* Eintragen des Filenamen (incl. inode-Nummer) in die Directory
*/
/*---------------------------------------------------------------------------*/
entry(inum, str, direa)
register char *inum, *str, *direa;
{
register i, j;
j = 0;
*direa++ = *inum++;
*direa++ = *inum;
for (i=0; i<14; i++) {
if (*str == '\0' || j == 1)
{ *direa++ = '\0'; j = 1; }
else *direa++ = *str++; }
}
/*---------------------------------------------------------------------------*/
/*
* Hole aus einem char-Buffer 2 oder 3 Byte
*/
/*---------------------------------------------------------------------------*/
unsigned
get2b(e)
char *e;
{
register unsigned i;
i = (*e << 8) | (*(e+1) & 0xFF);
return(i);
}
unsigned long
get3b(e)
char *e;
{
register unsigned long i;
i = ((unsigned long)*e << 16) & 0xFF0000;
i |= ((unsigned long)*(e+1) << 8) & 0xFF00;
i |= (unsigned long)*(e+2) & 0xFF;
return(i);
}

View File

@ -0,0 +1,747 @@
/***************************************************************************
***************************************************************************
W E G A - Quelle (C) ZFT/KEAW Abt. Basissoftware - 1985
Standalone: sa.mkfs.c
Bearbeiter: P. Bala / P.Hoge
Datum: 04/01/87 11:16:06
Version: 1.1
***************************************************************************
Hinweise:
mkfs kann sowohl als Standalone- als auch als Kommandoversion
generiert werden (Konstante STANDALONE =1 bzw. 0).
***************************************************************************
***************************************************************************/
/*--------------------------------------------------------------------------
*
* Aufbau eines Filesystems-Prototyps
* Aufruf im Kommando: mkfs filsys proto/size [ m n ]
* Bei Standalone-Version erfolgt Parameter-Angabe ueber Konsole
*
*--------------------------------------------------------------------------
*/
/*------------------------------------------------- Konstanten -------------*/
#define STANDALONE 1
#define NIPB (BSIZE/sizeof(struct dinode))
#define NDIRECT (BSIZE/sizeof(struct direct))
#define LADDR 10 /* Anzahl der Direktadressen im Inode */
#define MAXFN 72 /* Anzahl Blocks per Disk-Zyinder */
#define VERSATZ 1 /* kein Blockversatz */
/*---------------------------------------------------------------------------*/
#ifndef STANDALONE
#include <stdio.h>
#include <s.out.h>
#endif
#include <sys/param.h>
#include <sys/ino.h>
#include <sys/inode.h>
#include <sys/filsys.h>
#include <sys/fblk.h>
#include <sys/dir.h>
/*------------------------------------------------------- Variable --------*/
time_t utime;
#ifndef STANDALONE
FILE *fin;
#else
int fin;
#endif
int fsi;
int fso;
char *charp;
char buf[BSIZE];
union {
struct fblk fb;
char pad1[BSIZE];
} fbuf;
#ifndef STANDALONE
struct s_exec head;
#endif
char string[50];
union {
struct filsys fs;
char pad2[BSIZE];
} filsys;
char *fsys;
char *proto;
int f_n = MAXFN;
int f_m = VERSATZ; /* Standard-Blockversatz */
int error;
ino_t ino;
long getnum();
daddr_t alloc();
/*-------------------------------------------------------------------------
*
* Haupt - Programm
*
*-------------------------------------------------------------------------
*/
main(argc, argv)
char *argv[];
{
register int f, c;
register long n;
#ifndef STANDALONE
time(&utime);
if(argc < 3) {
printf("usage: mkfs filsys proto/size [ m n ]\n");
exit(1);
}
fsys = argv[1];
proto = argv[2];
#else
/* Definiere Filesystem-Groesse ueber Konsole */
{
static char protos[60];
printf("file system size: ");
gets(protos, sizeof protos);
proto = protos;
}
#endif
#ifdef STANDALONE
{
char fsbuf[100];
/* Definiere Name und Nr. des 1. Blocks des Filesystems ueber Konsole */
do {
printf("file system: ");
gets(fsbuf, sizeof fsbuf);
fso = open(fsbuf, 1);
fsi = open(fsbuf, 0);
} while (fso < 0 || fsi < 0);
}
fin = 0;
argc = 0;
#else
fso = creat(fsys, 0666);
if(fso < 0) {
printf("%s: cannot create\n", fsys);
exit(1);
}
fsi = open(fsys, 0);
if(fsi < 0) {
printf("%s: cannot open\n", fsys);
exit(1);
}
fin = fopen(proto, "r");
#endif
/* Festlegen der Anzahl der inode-Bloecke des Filesystems */
if(fin == 0) {
n = 0;
for(f=0; c=proto[f]; f++) {
if(c<'0' || c>'9') {
printf("%s: cannot open\n", proto);
exit(1);
}
n = n*10 + (c-'0');
}
filsys.s_fsize = n;
n = n/25;
if(n <= 0)
n = 1;
if(n > 65500/NIPB)
n = 65500/NIPB;
filsys.s_isize = n + 2;
printf("isize = %d\n", filsys.s_isize*NIPB);
/*
* Kommando-String zur Generierung einer leeren Directory
*/
charp = "d--777 0 0 $ ";
goto f3;
}
#ifndef STANDALONE
getstr();
f = open(string, 0);
if(f < 0) {
printf("%s: cannot open init\n", string);
goto f2;
}
read(f, (char *)&head, sizeof head);
if(head.s_magic != N_MAGIC1) {
printf("%s: bad format\n", string);
goto f1;
}
c = head.s_imsize;
if(c > BSIZE) {
printf("%s: too big\n", string);
goto f1;
}
read(f, buf, c);
wtfs((long)0, buf);
f1:
close(f);
f2:
filsys.s_fsize = getnum();
n = getnum();
n /= NIPB;
filsys.s_isize = n + 3;
#endif
f3:
if(argc >= 5) {
f_m = atoi(argv[3]);
f_n = atoi(argv[4]);
if(f_n <= 0 || f_n >= 1000)
f_n = 1000;
if(f_m <= 0 || f_m > f_n)
f_m = 3;
}
filsys.s_m = f_m;
filsys.s_n = f_n;
printf("m/n = %d %d\n", f_m, f_n);
if(filsys.s_isize >= filsys.s_fsize) {
printf("%ld/%ld: bad ratio\n", filsys.s_fsize, filsys.s_isize-2);
exit(1);
}
filsys.s_tfree = 0;
filsys.s_tinode = 0;
for(c=0; c<BSIZE; c++)
buf[c] = 0;
for(n=2; n!=filsys.s_isize; n++) {
wtfs(n, buf);
filsys.s_tinode += NIPB;
}
ino = 0;
/* Anlegen der Freiblock-Liste des Filesystems */
bflist();
/* Generierung der Root-Directory entspr. der Kommando-String */
cfile((struct inode *)0);
filsys.s_time = utime;
filsys.s_mach = 0;
/* Schreibe Superblock (Blocknr. 1 des Filesystems) auf Disk */
wtfs((long)1, (char *)&filsys);
exit(error);
}
/*-----------------------------------------------------------------------
* Generiere einen File unter wega-Verwaltung anhand einer
* Kommando-String
*-----------------------------------------------------------------------
*/
cfile(par)
register struct inode *par;
{
struct inode in;
int dbc, ibc;
char db[BSIZE];
daddr_t ib[NINDIR];
register int i, f, c;
/*
* Eingabe mode, uid und gid
*/
getstr();
in.i_mode = gmode(string[0], "-bcd", IFREG, IFBLK, IFCHR, IFDIR);
in.i_mode |= gmode(string[1], "-u", 0, ISUID, 0, 0);
in.i_mode |= gmode(string[2], "-g", 0, ISGID, 0, 0);
for(i=3; i<6; i++) {
c = string[i];
if(c<'0' || c>'7') {
printf("%c/%s: bad octal mode digit\n", c, string);
error = 1;
c = 0;
}
in.i_mode |= (c-'0')<<(15-3*i);
}
in.i_uid = getnum();
in.i_gid = getnum();
/* Loesche zugewiesenes inode */
ino++;
in.i_number = ino;
for(i=0; i<BSIZE; i++)
db[i] = 0;
for(i=0; i<NINDIR; i++)
ib[i] = (daddr_t)0;
in.i_nlink = 1;
in.i_size = 0;
for(i=0; i<NADDR; i++)
in.i_addr[i] = (daddr_t)0;
if(par == (struct inode *)0) {
par = &in;
in.i_nlink--;
}
dbc = 0;
ibc = 0;
switch(in.i_mode&IFMT) {
/* regular file
* die in der Kommando-String angegebene Datei wird in das
* Filesystem uebertragen
*/
case IFREG:
/*
* Regular File
* Inhalt ist ein File-Name
*/
getstr();
f = open(string, 0);
if(f < 0) {
printf("%s: cannot open\n", string);
error = 1;
break;
}
while((i=read(f, db, BSIZE)) > 0) {
in.i_size += i;
newblk(&dbc, db, &ibc, ib);
}
close(f);
break;
/* special file
* die in der Kommando-String notierte Devicenr. wird in das
* inode uebernommen
*/
case IFBLK:
case IFCHR:
/*
* Special File
* Inhalt ist eine major/minor - Devicenummer
*/
i = getnum() & 0377;
f = getnum() & 0377;
in.i_addr[0] = (i<<8) | f;
break;
case IFDIR:
/* directory
* Anlegen eines File-Verzeichnisses bei rekursiver Definition
* der in der akt. Directory notierten Files entsprechend der
* Kommando-String.
* Ende der Eintragungen in die akt. Directory, wenn der File-
* Name "$" gefunden wurde
*/
par->i_nlink++;
in.i_nlink++;
entry(in.i_number, ".", &dbc, db, &ibc, ib);
entry(par->i_number, "..", &dbc, db, &ibc, ib);
in.i_size = 2*sizeof(struct direct);
for(;;) {
getstr();
if(string[0]=='$' && string[1]=='\0')
break;
entry(ino+1, string, &dbc, db, &ibc, ib);
in.i_size += sizeof(struct direct);
cfile(&in);
}
break;
}
/* Schreibe inode auf Disk */
if(dbc != 0)
newblk(&dbc, db, &ibc, ib);
iput(&in, &ibc, ib);
}
/*-------------------------------------------------------------------------
* Eintragen einer der drei Parameter m0 .. m3 entsprechend
* dem Kommando-Steuerzeichen in c anhand der vorgegebenen
* Moeglichkeiten s[0] .. s[3]
*-------------------------------------------------------------------------
*/
gmode(c, s, m0, m1, m2, m3)
char c;
register char *s;
{
if(c == s[0])
return(m0);
if(c == s[1])
return(m1);
if(c == s[2])
return(m2);
if(c == s[3])
return(m3);
printf("%c/%s: bad mode\n", c, string);
error = 1;
return(0);
}
/*----------------------------------------------------------------------
* Eingabe-Konvertierung dezimal aus Kommando-String
*----------------------------------------------------------------------
*/
long
getnum()
{
register int i, c;
register long n;
getstr();
n = 0;
for(i=0; c=string[i]; i++) {
if(c<'0' || c>'9') {
printf("%s: bad number\n", string);
error = 1;
return((long)0);
}
n = n*10 + (c-'0');
}
return(n);
}
/*----------------------------------------------------------------------
* Uebertrage akt. Term aus Kommando-String nach string[]
*----------------------------------------------------------------------
*/
getstr()
{
register int i, c;
loop:
switch(c=getch()) {
case ' ':
case '\t':
case '\n':
goto loop;
case '\0':
printf("EOF\n");
exit(1);
case ':':
while(getch() != '\n');
goto loop;
}
i = 0;
do {
string[i++] = c;
c = getch();
} while(c!=' '&&c!='\t'&&c!='\n'&&c!='\0');
string[i] = '\0';
}
/*--------------------------------------------------------------------
* Read Block von Disk
*--------------------------------------------------------------------
*/
rdfs(bno, bf)
daddr_t bno;
char *bf;
{
int n;
lseek(fsi, bno*BSIZE, 0);
n = read(fsi, bf, BSIZE);
if(n != BSIZE) {
printf("read error: %ld\n", bno);
exit(1);
}
}
/*----------------------------------------------------------------------
* Write Block auf Disk
*----------------------------------------------------------------------
*/
wtfs(bno, bf)
daddr_t bno;
char *bf;
{
int n;
lseek(fso, bno*BSIZE, 0);
n = write(fso, bf, BSIZE);
if(n != BSIZE) {
printf("write error: %D\n", bno);
exit(1);
}
}
/*------------------------------------------------------------------------
* Der Return-Wert von alloc ist die Nummer des naechsten Blocks
* aus der Freiblockliste des Superblocks. Ist diese leer, wird
* der naechste Ankerblock in den Superblock gelesen und die Nr.
* des Ankerblocks selbst zurueckgegeben. Ist kein solcher Anker-
* Block mehr vorhanden, wird mkfs beendet
*------------------------------------------------------------------------
*/
daddr_t
alloc()
{
register int i;
register daddr_t bno;
filsys.s_tfree--;
bno = filsys.s_free[--filsys.s_nfree];
if(bno == 0) {
printf("out of free space\n");
exit(1);
}
if(filsys.s_nfree <= 0) {
rdfs(bno, (char *)&fbuf);
filsys.s_nfree = fbuf.df_nfree;
for(i=0; i<NICFREE; i++)
filsys.s_free[i] = fbuf.df_free[i];
}
return(bno);
}
/*-----------------------------------------------------------------------
* Eintragen der Blocknr. bno in die Freiblockliste des Superblocks
* Ist dieses Teil voll, so wird der akt. freizugebende Block als
* Ankerblock benutzt, um die volle Freiblockliste des Superblocks
* auf die Disk auszulagern
*-----------------------------------------------------------------------
*/
bfree(bno)
register daddr_t bno;
{
register int i;
filsys.s_tfree++;
if(filsys.s_nfree >= NICFREE) {
fbuf.df_nfree = filsys.s_nfree;
for(i=0; i<NICFREE; i++)
fbuf.df_free[i] = filsys.s_free[i];
wtfs(bno, (char *)&fbuf);
filsys.s_nfree = 0;
}
filsys.s_free[filsys.s_nfree++] = bno;
}
/*---------------------------------------------------------------------
* Eintragen Filename incl. inode-Nummer in akt. Directory
*---------------------------------------------------------------------
*/
entry(inum, str, adbc, db, aibc, ib)
ino_t inum;
char *str;
register int *adbc, *aibc;
char *db;
daddr_t *ib;
{
register struct direct *dp;
register int i;
dp = (struct direct *)db;
dp += *adbc;
(*adbc)++;
dp->d_ino = inum;
for(i=0; i<DIRSIZ; i++)
dp->d_name[i] = 0;
for(i=0; i<DIRSIZ; i++)
if((dp->d_name[i] = str[i]) == 0)
break;
if(*adbc >= NDIRECT)
newblk(adbc, db, aibc, ib);
}
/*----------------------------------------------------------------------
* Schreibe gefuellten internen Datenblock auf Disk und loesche
* den internen Datenblock
*----------------------------------------------------------------------
*/
newblk(adbc, db, aibc, ib)
register int *adbc, *aibc;
char *db;
daddr_t *ib;
{
register int i;
daddr_t bno;
bno = alloc();
wtfs(bno, db);
for(i=0; i<BSIZE; i++)
db[i] = 0;
*adbc = 0;
ib[*aibc] = bno;
(*aibc)++;
if(*aibc >= NINDIR) {
printf("indirect block full\n");
error = 1;
*aibc = 0;
}
}
/*-----------------------------------------------------------------
* Lies akt. Zeichen von Kommando-String
*-----------------------------------------------------------------
*/
getch()
{
#ifndef STANDALONE
if(charp)
#endif
return(*charp++);
#ifndef STANDALONE
return(getc(fin));
#endif
}
/*---------------------------------------------------------------------
* Aufbau der Freiblock-Liste des akt. Filesystems
*---------------------------------------------------------------------
*/
bflist()
{
struct inode in;
daddr_t ib[NINDIR];
int ibc;
char flg[MAXFN];
int adr[MAXFN];
register int i, j;
register daddr_t f, d;
/* Aufbau der Musterverteilung der freien Bloecke auf
* einem Disk-Zylinder entsprechend des vorgegebenen
* Blockversatzes
*/
for(i=0; i<f_n; i++)
flg[i] = 0;
i = 0;
for(j=0; j<f_n; j++) {
while(flg[i])
i = (i+1)%f_n;
adr[j] = i+1;
flg[i]++;
i = (i+f_m)%f_n;
}
/* Anlegen des inodes 1 (bad blocks)
*/
ino++;
in.i_number = ino;
in.i_mode = IFREG;
in.i_uid = 0;
in.i_gid = 0;
in.i_nlink = 0;
in.i_size = 0;
for(i=0; i<NADDR; i++)
in.i_addr[i] = (daddr_t)0;
for(i=0; i<NINDIR; i++)
ib[i] = (daddr_t)0;
ibc = 0;
/* Markiere Ende der Freiblockliste
* (Adr. Ankerblock = 0)
*/
bfree((daddr_t)0);
/* Generiere Freiblockliste anhand der Musterverteilung
* wobei die definierten inode-Bloecke nicht einbezogen
* werden.
*/
d = filsys.s_fsize-1;
while(d%f_n)
d++;
for(; d > 0; d -= f_n)
for(i=0; i<f_n; i++) {
f = d - adr[i];
if(f < filsys.s_fsize && f >= filsys.s_isize)
if(badblk(f)) {
if(ibc >= NINDIR) {
printf("too many bad blocks\n");
error = 1;
ibc = 0;
}
ib[ibc] = f;
ibc++;
} else
bfree(f);
}
/* Schreibe "bad-blocks"-inode auf Disk
*/
iput(&in, &ibc, ib);
}
/*---------------------------------------------------------------------
* Wandle interne Form des inodes ip in Diskform und Eintragen
* dieser in den zugeordeten inode-Block
*---------------------------------------------------------------------
*/
iput(ip, aibc, ib)
register struct inode *ip;
register int *aibc;
daddr_t *ib;
{
register struct dinode *dp;
daddr_t d;
register int i;
filsys.s_tinode--;
d = itod(ip->i_number);
if(d >= filsys.s_isize) {
if(error == 0)
printf("ilist too small\n");
error = 1;
return;
}
rdfs(d, buf);
dp = (struct dinode *)buf;
dp += itoo(ip->i_number);
dp->di_mode = ip->i_mode;
dp->di_nlink = ip->i_nlink;
dp->di_uid = ip->i_uid;
dp->di_gid = ip->i_gid;
dp->di_size = ip->i_size;
dp->di_atime = utime;
dp->di_mtime = utime;
dp->di_ctime = utime;
switch(ip->i_mode&IFMT) {
/* Fuer regular files und directorys werden die max. 128
* Blocknummern entspr. der unix-Konvention ( 10 direkte
* Adressen, Rest in einem einfach indexierten Ankerblock
* im inode) in eine 3-Byte-Form gewandelt
*/
case IFDIR:
case IFREG:
for(i=0; i<*aibc; i++) {
if(i >= LADDR)
break;
ip->i_addr[i] = ib[i];
}
if(*aibc >= LADDR) {
ip->i_addr[LADDR] = alloc();
for(i=0; i<NINDIR-LADDR; i++) {
ib[i] = ib[i+LADDR];
ib[i+LADDR] = (daddr_t)0;
}
wtfs(ip->i_addr[LADDR], (char *)ib);
}
case IFBLK:
case IFCHR:
ltol3(dp->di_addr, ip->i_addr, NADDR);
break;
default:
printf("bad mode %o\n", ip->i_mode);
exit(1);
}
wtfs(d, buf);
}
badblk(bno)
daddr_t bno;
{
return(0);
}