Tenkte denne var grei å ha med også :-)
This commit is contained in:
parent
e2b433e4b4
commit
aaee3363c4
37
tikidisk-src/LESMEG
Normal file
37
tikidisk-src/LESMEG
Normal file
@ -0,0 +1,37 @@
|
||||
tikidisk V1.1, 24 august 2001
|
||||
-----------------------------
|
||||
|
||||
Dette er kildefilene til 'tikidisk'. Denne fila gir en oppskrift på
|
||||
hvordan kompilere. For informasjon om bruk av kommandoen, se
|
||||
tikidisk.txt.
|
||||
|
||||
Jeg gir tillatelse til å bruke og spre disse filene fritt. Ønsker du å
|
||||
gjøre forandringer ser jeg helst at du tar kontakt med meg. Dette
|
||||
fordi jeg ikke anser meg for ferdig med dette programmet enda. Da
|
||||
unngår vi at flere jobber på de samme tingene. Men jeg tar gjerne imot
|
||||
forslag til forbedringer.
|
||||
|
||||
Disse kildefilene skal ikke brukes til kommersielle formål på noen som
|
||||
helst måte, hverken i original eller modifisert form.
|
||||
|
||||
Kompilering:
|
||||
------------
|
||||
|
||||
Kompilering er rett fram. Det du trenger er GCC og GNU-make, eller noe
|
||||
tilsvarende. Skriv kommandoen "make" i samme katalog som kildefilene,
|
||||
og tikidisk kompileres. Dette skal gå smertefritt under alle
|
||||
operativsystemer, bare du har GCC og make. Kildefilene er skrevet i
|
||||
ANSI-C, og skal i teorien kompilere med alle ANSI-C kompilatorer.
|
||||
|
||||
Har du problemer, så ta kontakt med meg.
|
||||
|
||||
Disse filene skal være med:
|
||||
---------------------------
|
||||
|
||||
- tikidisk.c
|
||||
- Makefile
|
||||
- LESMEG
|
||||
- tikidisk.txt
|
||||
|
||||
---
|
||||
Asbjørn Djupdal, djupdal@stud.ntnu.no
|
26
tikidisk-src/Makefile
Normal file
26
tikidisk-src/Makefile
Normal file
@ -0,0 +1,26 @@
|
||||
# Makefile for tikidisk V1.1
|
||||
# Asbjørn Djupdal 2001
|
||||
|
||||
CC = gcc
|
||||
|
||||
CFLAGS = -Wall -O
|
||||
LDFLAGS = -s
|
||||
#LDFLAGS = -s -noixemul # amiga-versjon uten ixemul.library
|
||||
#LDFLAGS = -s -mno-cygwin # win32-versjon uten cygwin.dll
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Regler
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# Alle objektfiler som skal linkes
|
||||
OBJECTS = tikidisk.o
|
||||
|
||||
tikidisk : $(OBJECTS)
|
||||
$(CC) -o $@ $(OBJECTS) $(LDFLAGS)
|
||||
|
||||
tikidisk.o : tikidisk.c Makefile
|
||||
$(CC) -c $< $(CFLAGS)
|
||||
|
||||
.PHONY : clean
|
||||
clean :
|
||||
rm -f tikidisk tikidisk.exe *.o
|
805
tikidisk-src/tikidisk.c
Normal file
805
tikidisk-src/tikidisk.c
Normal file
@ -0,0 +1,805 @@
|
||||
/* tikidisk.c V1.1
|
||||
*
|
||||
* CP/M-2.2 filsystem som jobber mot TIKI-100 diskettfiler
|
||||
*
|
||||
* Burde fungere med alle CP/M-2.2 diskettfiler, bare riktige diskparametre oppgis.
|
||||
* Foreløpig kjenner programmet bare igjen TIKI-100 diskettfiler.
|
||||
*
|
||||
* Copyright (c) Asbjørn Djupdal 2001
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
typedef short boolean;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE ~0
|
||||
#endif
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#define DISK90K 1*40*18*128
|
||||
#define DISK200K 1*40*10*512
|
||||
#define DISK400K 2*40*10*512
|
||||
#define DISK800K 2*80*10*512
|
||||
|
||||
/* protos */
|
||||
int main (int argc, char *argv[]);
|
||||
|
||||
void saveFile (byte *entry);
|
||||
void addFile (char *efn, byte user);
|
||||
void delFile (char *ffn, byte user);
|
||||
|
||||
byte *getEntry (int entryNumber);
|
||||
byte *getExtent (byte *entry, int extentNumber);
|
||||
byte *getMatch (char *ffn, byte user);
|
||||
byte *getSector (int sectorNumber);
|
||||
|
||||
int getExtentNumber (byte *entry);
|
||||
void setExtentNumber (byte *entry, int extentNumber);
|
||||
int getBytesInEntry (byte *entry);
|
||||
void setBytesInEntry (byte *entry, int bytesInExtent);
|
||||
int getBlockNumber (byte *entry, int alNumber);
|
||||
void setBlockNumber (byte *entry, int alNumber, int blockNumber);
|
||||
|
||||
void getFilename (char *filename, byte *entry);
|
||||
int getFilesize (byte *entry);
|
||||
byte getUsernumber (byte *entry);
|
||||
void getAttribs (char *attribs, byte *entry);
|
||||
void setNameAndUser (byte *ffnEntry, char *ffn, byte user);
|
||||
|
||||
void buildBAM (void);
|
||||
int allocateBlock (void);
|
||||
|
||||
boolean entryNotDeleted (byte *entry);
|
||||
void deleteEntry (byte *entry);
|
||||
boolean entryEquals (byte *ffnEntry, byte *entry);
|
||||
char legalChar (char c);
|
||||
char *stripPath (char *ffn);
|
||||
|
||||
/* globals */
|
||||
byte diskImage[DISK800K]; /* her legges diskettfil */
|
||||
boolean *bam = NULL; /* Block Availability Map */
|
||||
|
||||
int numberOfEntries; /* antall kataloginnganger */
|
||||
int systemSectors; /* antall sektorer med bootkode */
|
||||
int sectorSize; /* bytes pr. sektor */
|
||||
int *convertSectorNumber; /* tabell som mapper sektornummer */
|
||||
int sectorsPerTrack; /* antall sektorer pr. spor */
|
||||
int exm; /* antall bytes pr. AL */
|
||||
int bytesPerAL; /* blokkstørrelse */
|
||||
int blockSize; /* bytes pr. blokk */
|
||||
int sectorsPerBlock; /* sektorer pr. blokk */
|
||||
int numberOfBlocks; /* antall blokker (untatt systemsektorer) */
|
||||
int directoryBlocks; /* antall blokker brukt av kataloginnganger */
|
||||
int numberOfALs; /* antall ALs pr. kataloginngang */
|
||||
|
||||
int convertSectorNumber18[18] = {0, 5, 10, 15, 2, 7, 12, 17, 4, 9, 14, 1, 6, 11, 16, 3, 8, 13};
|
||||
int convertSectorNumber10[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
|
||||
/* functions */
|
||||
int main (int argc, char *argv[]) {
|
||||
int size;
|
||||
byte user;
|
||||
|
||||
if (argc < 4) {
|
||||
fprintf (stderr, "tikidisk V1.1 Copyright (c) Asbjørn Djupdal 2001\n"
|
||||
"\n"
|
||||
"Brukes: tikidisk <diskfil> {lxad}[brukernummer] <filnavn...>\n"
|
||||
" l = list filer\n"
|
||||
" x = hent ut filer\n"
|
||||
" a = legg til filer\n"
|
||||
" d = slett filer\n"
|
||||
"\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
{ /* les diskfil */
|
||||
FILE *diskImageFp;
|
||||
|
||||
if (!(diskImageFp = fopen (argv[1], "rb"))) {
|
||||
fprintf (stderr, "Kan ikke åpne diskfil %s\n", argv[1]);
|
||||
exit (1);
|
||||
}
|
||||
size = fread (diskImage, 1, DISK800K, diskImageFp);
|
||||
fclose (diskImageFp);
|
||||
}
|
||||
|
||||
/* sett diskparametre */
|
||||
switch (size) {
|
||||
case DISK90K:
|
||||
convertSectorNumber = convertSectorNumber18;
|
||||
numberOfEntries = 32;
|
||||
systemSectors = 3 * 18;
|
||||
sectorSize = 128;
|
||||
sectorsPerTrack = 18;
|
||||
exm = 0;
|
||||
bytesPerAL = 1;
|
||||
blockSize = 1024;
|
||||
numberOfBlocks = 83;
|
||||
directoryBlocks = 1;
|
||||
break;
|
||||
case DISK200K:
|
||||
convertSectorNumber = convertSectorNumber10;
|
||||
numberOfEntries = 64;
|
||||
systemSectors = 20;
|
||||
sectorSize = 512;
|
||||
sectorsPerTrack = 10;
|
||||
exm = 0;
|
||||
bytesPerAL = 1;
|
||||
blockSize = 1024;
|
||||
numberOfBlocks = 190;
|
||||
directoryBlocks = 2;
|
||||
break;
|
||||
case DISK400K:
|
||||
convertSectorNumber = convertSectorNumber10;
|
||||
numberOfEntries = 128;
|
||||
systemSectors = 20;
|
||||
sectorSize = 512;
|
||||
sectorsPerTrack = 10;
|
||||
exm = 1;
|
||||
bytesPerAL = 1;
|
||||
blockSize = 2048;
|
||||
numberOfBlocks = 195;
|
||||
directoryBlocks = 2;
|
||||
break;
|
||||
case DISK800K:
|
||||
convertSectorNumber = convertSectorNumber10;
|
||||
numberOfEntries = 128;
|
||||
systemSectors = 20;
|
||||
sectorSize = 512;
|
||||
sectorsPerTrack = 10;
|
||||
exm = 0;
|
||||
bytesPerAL = 2;
|
||||
blockSize = 2048;
|
||||
numberOfBlocks = 395;
|
||||
directoryBlocks = 2;
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "Ikke en gyldig diskfil\n");
|
||||
exit (1);
|
||||
}
|
||||
sectorsPerBlock = blockSize / sectorSize;
|
||||
numberOfALs = 16 / bytesPerAL;
|
||||
|
||||
{ /* finn brukernummer */
|
||||
char *ptr;
|
||||
|
||||
user = (byte)strtol (argv[2] + 1, &ptr, 10);
|
||||
if (ptr == argv[2] + 1) { /* brukernummer ikke angitt */
|
||||
user = (byte)'?';
|
||||
} else if (user > 15) {
|
||||
fprintf (stderr, "Ulovlig brukernummer\n");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* utfør kommando */
|
||||
switch (*argv[2]) {
|
||||
case 'l': {
|
||||
/* list filer */
|
||||
int files = 0;
|
||||
int bytes = 0;
|
||||
byte *entry;
|
||||
|
||||
if ((entry = getMatch (argv[3], user))) {
|
||||
do {
|
||||
char filename[13];
|
||||
char attribs[4];
|
||||
int filesize = getFilesize (entry);
|
||||
|
||||
getFilename (filename, entry);
|
||||
getAttribs (attribs, entry);
|
||||
printf (" %6d %s %02d: %s\n", filesize, attribs, getUsernumber (entry), filename);
|
||||
files++;
|
||||
bytes += filesize;
|
||||
} while ((entry = getMatch (NULL, 0)));
|
||||
}
|
||||
printf ("%d filer, %d bytes\n", files, bytes);
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
/* lagre filer */
|
||||
int i = 3;
|
||||
|
||||
while (argv[i]) {
|
||||
byte *entry;
|
||||
|
||||
if ((entry = getMatch (argv[i], user))) {
|
||||
do {
|
||||
saveFile (entry);
|
||||
} while ((entry = getMatch (NULL, 0)));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'a': {
|
||||
/* legg til filer */
|
||||
int i = 3;
|
||||
|
||||
if (user == (byte)'?') {
|
||||
user = 0;
|
||||
}
|
||||
|
||||
while (argv[i]) {
|
||||
addFile (argv[i], user);
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
/* slett filer */
|
||||
int i = 3;
|
||||
|
||||
while (argv[i]) {
|
||||
delFile (argv[i], user);
|
||||
i++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf (stderr, "Ulovlig kommando\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
/* lagre diskfil */
|
||||
if ((*argv[2] == 'a') || (*argv[2] == 'd')) {
|
||||
FILE *diskImageFp;
|
||||
|
||||
if ((diskImageFp = fopen (argv[1], "wb"))) {
|
||||
fwrite (diskImage, 1, size, diskImageFp);
|
||||
fclose (diskImageFp);
|
||||
}
|
||||
}
|
||||
|
||||
free (bam);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Trekker ut fil fra diskettfil og lagrer på disk
|
||||
*
|
||||
* entry: en ekstent til filen som skal lagres
|
||||
*/
|
||||
void saveFile (byte *entry) {
|
||||
char filename[13];
|
||||
FILE *fp;
|
||||
|
||||
getFilename (filename, entry);
|
||||
|
||||
if ((fp = fopen (filename, "wb"))) {
|
||||
int extentNumber = 0;
|
||||
|
||||
printf ("Henter ut %02d:%s...\n", getUsernumber (entry), filename);
|
||||
|
||||
/* gå gjennom alle extenter */
|
||||
while ((entry = getExtent (entry, extentNumber++))) {
|
||||
boolean done = FALSE;
|
||||
int blockNumber;
|
||||
int alNumber = 0;
|
||||
int bytesRemaining = getBytesInEntry (entry);
|
||||
|
||||
/* gå gjennom alle blokker */
|
||||
while (!done && (alNumber < numberOfALs)) {
|
||||
if ((blockNumber = getBlockNumber (entry, alNumber))) {
|
||||
int i;
|
||||
|
||||
/* lagre sektorer i blokk */
|
||||
for (i = 0; i < sectorsPerBlock; i++) {
|
||||
int sectorNumber = ((blockNumber * blockSize) / sectorSize) + systemSectors + i;
|
||||
|
||||
if (bytesRemaining) {
|
||||
int bytesToWrite = (bytesRemaining < sectorSize ? bytesRemaining : sectorSize);
|
||||
|
||||
fwrite (getSector (sectorNumber), 1, bytesToWrite, fp);
|
||||
bytesRemaining -= bytesToWrite;
|
||||
} else {
|
||||
done = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
alNumber++;
|
||||
}
|
||||
}
|
||||
fclose (fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Henter inn fil fra disk og legger inn i diskettfil
|
||||
*
|
||||
* efn: entydig filnavn til fil som skal legges til
|
||||
* user: entydig brukernummer som fil skal lagres under
|
||||
*/
|
||||
void addFile (char *efn, byte user) {
|
||||
FILE *fp;
|
||||
byte *entry = NULL;
|
||||
int extentNumber = 0;
|
||||
int alNumber = 0;
|
||||
int sectorNumber = 0;
|
||||
int bytesInExtent = 0;
|
||||
byte *sectorData;
|
||||
boolean done = FALSE;
|
||||
|
||||
if (!(fp = fopen (efn, "rb"))) {
|
||||
fprintf (stderr, "Kan ikke åpne %s\n", efn);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(sectorData = malloc (sectorSize))) {
|
||||
fprintf (stderr, "Ikke nok minne\n");
|
||||
free (bam);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
delFile (stripPath (efn), user);
|
||||
|
||||
buildBAM();
|
||||
|
||||
printf ("Legger til %02d:%s...\n", user, efn);
|
||||
|
||||
while (!done) {
|
||||
int bytesRead = fread (sectorData, 1, sectorSize, fp);
|
||||
|
||||
if (bytesRead) {
|
||||
|
||||
/* finn ledig kataloginngang */
|
||||
if (!(bytesInExtent % (numberOfALs * blockSize))) {
|
||||
int entryNumber = 0;
|
||||
|
||||
if (entry) setBytesInEntry (entry, bytesInExtent);
|
||||
|
||||
do {
|
||||
if (entryNumber >= numberOfEntries) {
|
||||
fprintf (stderr, "Ikke nok ledige kataloginnganger\n");
|
||||
free (sectorData);
|
||||
free (bam);
|
||||
exit (1);
|
||||
}
|
||||
entry = getEntry (entryNumber);
|
||||
entryNumber++;
|
||||
} while (entryNotDeleted (entry));
|
||||
|
||||
memset (entry, 0, 32);
|
||||
setNameAndUser (entry, stripPath (efn), user);
|
||||
setExtentNumber (entry, extentNumber++);
|
||||
alNumber = 0;
|
||||
bytesInExtent = 0;
|
||||
}
|
||||
|
||||
/* finn ledig blokk */
|
||||
if (!(bytesInExtent % blockSize)) {
|
||||
int blockNumber;
|
||||
|
||||
if (!(blockNumber = allocateBlock())) {
|
||||
fprintf (stderr, "Ikke nok ledige blokker\n");
|
||||
free (sectorData);
|
||||
free (bam);
|
||||
exit (1);
|
||||
}
|
||||
setBlockNumber (entry, alNumber++, blockNumber);
|
||||
sectorNumber = ((blockNumber * blockSize) / sectorSize) + systemSectors;
|
||||
}
|
||||
|
||||
/* skriv til sektor */
|
||||
memcpy (getSector (sectorNumber++), sectorData, sectorSize);
|
||||
bytesInExtent += bytesRead;
|
||||
|
||||
} else {
|
||||
done = TRUE;
|
||||
setBytesInEntry (entry, bytesInExtent);
|
||||
}
|
||||
}
|
||||
free (sectorData);
|
||||
}
|
||||
|
||||
/* Sletter filer fra diskettfil
|
||||
*
|
||||
* ffn: flertydig filnavn til filer som skal slettes
|
||||
* user: flertydig brukernummer til filer som skal slettes
|
||||
*/
|
||||
void delFile (char *ffn, byte user) {
|
||||
byte *entry;
|
||||
|
||||
if ((entry = getMatch (ffn, user))) {
|
||||
/* gå gjennom alle entries (filer) */
|
||||
do {
|
||||
int extentNumber = 0;
|
||||
byte *extent;
|
||||
char filename[13];
|
||||
|
||||
getFilename (filename, entry);
|
||||
|
||||
printf ("Sletter %02d:%s...\n", getUsernumber (entry), filename);
|
||||
|
||||
/* slett alle extenter til filen */
|
||||
while ((extent = getExtent (entry, extentNumber++))) {
|
||||
deleteEntry (extent);
|
||||
}
|
||||
} while ((entry = getMatch (NULL, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
/* Gir peker til entry i diskettfil
|
||||
*
|
||||
* entryNumber: nummer på entry som skal returneres
|
||||
*/
|
||||
byte *getEntry (int entryNumber) {
|
||||
int dirSector = systemSectors + ((entryNumber * 32) / sectorSize);
|
||||
int offsetInSector = (entryNumber * 32) % sectorSize;
|
||||
|
||||
return getSector (dirSector) + offsetInSector;
|
||||
}
|
||||
|
||||
/* Gir peker til extent i diskettfil, eller NULL derom ikke funnet
|
||||
*
|
||||
* entry: en allerede kjent extent
|
||||
* extentNumber: nummer til ønsket extent
|
||||
*/
|
||||
byte *getExtent (byte *entry, int extentNumber) {
|
||||
int entryNumber;
|
||||
|
||||
for (entryNumber = 0; entryNumber < numberOfEntries; entryNumber++) {
|
||||
byte *curEntry = getEntry (entryNumber);
|
||||
|
||||
if (entryNotDeleted (curEntry) && entryEquals (entry, curEntry) &&
|
||||
(getExtentNumber (curEntry) == extentNumber)) {
|
||||
return curEntry;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Gir peker til neste fil (extent 0) som passer, eller NULL dersom ikke flere passer
|
||||
*
|
||||
* ffn: flertydig filnavn til filer som skal finnes
|
||||
* Angi ffn kun første gang funksjonen kalles. For å finne de resterende filer
|
||||
* som passer, kall funksjonen med ffn = NULL
|
||||
* user: flertydig brukernummer til filer som skal finnes
|
||||
*/
|
||||
byte *getMatch (char *ffn, byte user) {
|
||||
static byte ffnEntry[12];
|
||||
static int entryNumber;
|
||||
|
||||
if (ffn != NULL) {
|
||||
entryNumber = 0;
|
||||
setNameAndUser (ffnEntry, ffn, user);
|
||||
}
|
||||
|
||||
while (entryNumber < numberOfEntries) {
|
||||
byte *entry = getEntry (entryNumber);
|
||||
entryNumber++;
|
||||
if (entryNotDeleted (entry) && entryEquals (ffnEntry, entry) && (getExtentNumber (entry) == 0)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Gir peker til stedet der data for angitt sektor befinner seg
|
||||
*
|
||||
* sectorNumber: nummer på sektor som ønskes
|
||||
*/
|
||||
byte *getSector (int sectorNumber) {
|
||||
int realSectorNumber = (sectorNumber / sectorsPerTrack) * sectorsPerTrack +
|
||||
convertSectorNumber[sectorNumber % sectorsPerTrack];
|
||||
return diskImage + realSectorNumber * sectorSize;
|
||||
}
|
||||
|
||||
/* Gir nummeret på extent (fra EX og S2 feltene)
|
||||
*
|
||||
* entry: kataloginngang man ønsker extentnummeret til
|
||||
*/
|
||||
int getExtentNumber (byte *entry) {
|
||||
return (*(entry + 14) * 32 + *(entry + 12)) / (exm + 1);
|
||||
}
|
||||
|
||||
/* Setter nummer på extent (til EX og S2 feltene)
|
||||
*
|
||||
* entry: kataloginngang man skal sette extentnummeret til
|
||||
* extentNumber: extentnummeret som skal settes
|
||||
*/
|
||||
void setExtentNumber (byte *entry, int extentNumber) {
|
||||
*(entry + 14) = extentNumber / 32;
|
||||
*(entry + 12) = ((extentNumber % 32) * (exm + 1));
|
||||
}
|
||||
|
||||
/* Gir antall bytes lagret i extent (fra RC og EX feltene)
|
||||
*
|
||||
* entry: extent man ønsker størrelsen til
|
||||
*/
|
||||
int getBytesInEntry (byte *entry) {
|
||||
return ((*(entry + 12) & exm) * 128 + *(entry + 15)) * 128;
|
||||
}
|
||||
|
||||
/* Setter antall bytes lagret i extent (til RC og EX feltene)
|
||||
*
|
||||
* entry: kataloginngang man skal sette størrelsen til
|
||||
* bytesInExtent: antall bytes som skal settes
|
||||
*/
|
||||
void setBytesInEntry (byte *entry, int bytesInExtent) {
|
||||
int recordsInExtent = bytesInExtent / 128;
|
||||
|
||||
if (bytesInExtent % 128) recordsInExtent++;
|
||||
|
||||
if (recordsInExtent % 0x80) {
|
||||
*(entry + 15) = recordsInExtent % 0x80;
|
||||
} else {
|
||||
*(entry + 15) = 0x80;
|
||||
}
|
||||
if (recordsInExtent > 0x80) {
|
||||
*(entry + 12) += (recordsInExtent / 0x80);
|
||||
}
|
||||
}
|
||||
|
||||
/* Gir nummeret på blokken som befinner seg i en AL
|
||||
*
|
||||
* entry: kataloginngang
|
||||
* alNumber: nummer på AL man ønsker blokknummeret til
|
||||
*/
|
||||
int getBlockNumber (byte *entry, int alNumber) {
|
||||
int al1 = *(entry + 16 + (alNumber * bytesPerAL));
|
||||
int al2 = *(entry + 16 + (alNumber * bytesPerAL) + 1);
|
||||
|
||||
return (bytesPerAL == 1 ? al1 : al1 + (al2 * 256));
|
||||
}
|
||||
|
||||
/* Setter nummer på blokk i an AL
|
||||
*
|
||||
* entry: kataloginngang
|
||||
* alNumber: nummer på AL
|
||||
* blockNumber: nummer på blokk
|
||||
*/
|
||||
void setBlockNumber (byte *entry, int alNumber, int blockNumber) {
|
||||
if (bytesPerAL < 2) {
|
||||
*(entry + 16 + alNumber) = blockNumber;
|
||||
} else {
|
||||
*(entry + 16 + (alNumber * 2)) = blockNumber;
|
||||
*(entry + 16 + (alNumber * 2) + 1) = blockNumber / 256;
|
||||
}
|
||||
}
|
||||
|
||||
/* Kopierer filnavn fra en kataloginngang til en streng
|
||||
*
|
||||
* filename: streng som filnavn skal kopieres til
|
||||
* entry: kataloginngang man ønsker filnavnet til
|
||||
*/
|
||||
void getFilename (char *filename, byte *entry) {
|
||||
int i = 0, j = 0;
|
||||
|
||||
entry++;
|
||||
/* kopier filnavn */
|
||||
while ((i < 8) && (*entry != ' ')) {
|
||||
filename[i++] = legalChar (*entry++);
|
||||
}
|
||||
entry += 8 - i;
|
||||
filename[i++] = '.';
|
||||
/* kopier filtype */
|
||||
while ((j++ < 3) && (*entry != ' ')) {
|
||||
filename[i++] = legalChar ((*entry++) & 0x7f);
|
||||
}
|
||||
filename[i] = '\0';
|
||||
}
|
||||
|
||||
/* Gir størrelsen på en fil
|
||||
*
|
||||
* entry: en extent til fila man ønsker størrelsen til
|
||||
*/
|
||||
int getFilesize (byte *entry) {
|
||||
int filesize = 0;
|
||||
boolean done = FALSE;
|
||||
int extentNumber = 0;
|
||||
|
||||
while (!done) {
|
||||
if (!(entry = getExtent (entry, extentNumber++))) {
|
||||
done = TRUE;
|
||||
} else {
|
||||
filesize += getBytesInEntry (entry);
|
||||
}
|
||||
}
|
||||
return filesize;
|
||||
}
|
||||
|
||||
/* Gir brukernummeret til en kataloginngang
|
||||
*
|
||||
* entry: kataloginngang man ønsker brukernummeret til
|
||||
*/
|
||||
byte getUsernumber (byte *entry) {
|
||||
return *entry;
|
||||
}
|
||||
|
||||
/* Lager en streng som representerer attributtene til en kataloginngang
|
||||
*
|
||||
* attribs: streng som attributtinfo skal skrives til
|
||||
* entry: kataloginngang man ønsker attributtinfo til
|
||||
*/
|
||||
void getAttribs (char *attribs, byte *entry) {
|
||||
*(attribs + 0) = (*(entry + 9)) & 0x80 ? 'l' : '-';
|
||||
*(attribs + 1) = (*(entry + 10)) & 0x80 ? 's' : '-';
|
||||
*(attribs + 2) = (*(entry + 11)) & 0x80 ? 'a' : '-';
|
||||
*(attribs + 3) = '\0';
|
||||
}
|
||||
|
||||
/* Kopierer filnavn og brukernummer inn i en kataloginngang
|
||||
*
|
||||
* ffnEntry: kataloginngang man skal skrive til
|
||||
* ffn: flertydig filnavn som skal skrives fra
|
||||
* user: flertydig brukernummer som skal skrives fra
|
||||
*/
|
||||
void setNameAndUser (byte *ffnEntry, char *ffn, byte user) {
|
||||
int i;
|
||||
|
||||
/* kopier brukernummer */
|
||||
*ffnEntry++ = user;
|
||||
|
||||
/* kopier filnavn */
|
||||
for (i = 0; i < 8; i++, ffnEntry++) {
|
||||
if (*ffn == '*') {
|
||||
*ffnEntry = (byte)'?';
|
||||
} else if (*ffn == '?') {
|
||||
*ffnEntry = (byte)'?';
|
||||
ffn++;
|
||||
} else if (*ffn == '.') {
|
||||
*ffnEntry = (byte)' ';
|
||||
} else if (*ffn == '\0') {
|
||||
*ffnEntry = (byte)' ';
|
||||
} else {
|
||||
*ffnEntry = (byte)legalChar (*ffn);
|
||||
ffn++;
|
||||
}
|
||||
}
|
||||
|
||||
/* finn filtype */
|
||||
if (strchr (ffn, '.')) {
|
||||
ffn = strchr (ffn, '.') + 1;
|
||||
|
||||
/* kopier filtype */
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (*ffn == '*') {
|
||||
*ffnEntry++ = (byte)'?';
|
||||
} else if (*ffn == '?') {
|
||||
*ffnEntry++ = (byte)'?';
|
||||
ffn++;
|
||||
} else if (*ffn == '.') {
|
||||
ffn++;
|
||||
} else if (*ffn == '\0') {
|
||||
*ffnEntry++ = (byte)' ';
|
||||
} else {
|
||||
*ffnEntry++ = (byte)legalChar (*ffn);
|
||||
ffn++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Bygger Block Availability Map for diskettfil
|
||||
*/
|
||||
void buildBAM (void) {
|
||||
int entryNumber;
|
||||
|
||||
free (bam);
|
||||
if (!(bam = malloc (sizeof (boolean) * numberOfBlocks))) {
|
||||
fprintf (stderr, "Ikke nok minne\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
memset (bam, 0, sizeof (boolean) * numberOfBlocks);
|
||||
|
||||
{ /* merk katalogblokker som opptatte */
|
||||
int blockNumber;
|
||||
|
||||
for (blockNumber = 0; blockNumber < directoryBlocks; blockNumber++) {
|
||||
*(bam + blockNumber) = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* gå gjennom alle kataloginnganger */
|
||||
for (entryNumber = 0; entryNumber < numberOfEntries; entryNumber++) {
|
||||
byte *entry = getEntry (entryNumber);
|
||||
|
||||
if (entryNotDeleted (entry)) {
|
||||
int blockNumber;
|
||||
int alNumber = 0;
|
||||
|
||||
/* merk alle blokker som denne kataloginngangen bruker som opptatt */
|
||||
while ((alNumber < numberOfALs) && (blockNumber = getBlockNumber (entry, alNumber))) {
|
||||
*(bam + blockNumber) = TRUE;
|
||||
alNumber++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Allokerer en blokk og gir nummeret på den nye blokken
|
||||
*/
|
||||
int allocateBlock (void) {
|
||||
int blockNumber;
|
||||
|
||||
for (blockNumber = 0; blockNumber < numberOfBlocks; blockNumber++) {
|
||||
if (!*(bam + blockNumber)) {
|
||||
*(bam + blockNumber) = TRUE;
|
||||
return blockNumber;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Gir slettet-status til en kataloginngang
|
||||
* entry: kataloginngang
|
||||
*/
|
||||
boolean entryNotDeleted (byte *entry) {
|
||||
return (*entry < 32);
|
||||
}
|
||||
|
||||
/* Sletter en kataloginngang
|
||||
* entry: kataloginngang
|
||||
*/
|
||||
void deleteEntry (byte *entry) {
|
||||
*entry = 0xe5;
|
||||
}
|
||||
|
||||
/* Sjekker om to kataloginnganger har samme navn og brukernummer
|
||||
*
|
||||
* ffnEntry: kataloginngang med flertydig navn og brukernummer
|
||||
* entry: kataloginngang som ffnEntry skal sjekkes mot
|
||||
*/
|
||||
boolean entryEquals (byte *ffnEntry, byte *entry) {
|
||||
if (((*(ffnEntry + 0) == '?') || (*(ffnEntry + 0) == *(entry + 0))) &&
|
||||
|
||||
((*(ffnEntry + 1) == '?') || (*(ffnEntry + 1) == *(entry + 1))) &&
|
||||
((*(ffnEntry + 2) == '?') || (*(ffnEntry + 2) == *(entry + 2))) &&
|
||||
((*(ffnEntry + 3) == '?') || (*(ffnEntry + 3) == *(entry + 3))) &&
|
||||
((*(ffnEntry + 4) == '?') || (*(ffnEntry + 4) == *(entry + 4))) &&
|
||||
((*(ffnEntry + 5) == '?') || (*(ffnEntry + 5) == *(entry + 5))) &&
|
||||
((*(ffnEntry + 6) == '?') || (*(ffnEntry + 6) == *(entry + 6))) &&
|
||||
((*(ffnEntry + 7) == '?') || (*(ffnEntry + 7) == *(entry + 7))) &&
|
||||
((*(ffnEntry + 8) == '?') || (*(ffnEntry + 8) == *(entry + 8))) &&
|
||||
|
||||
((*(ffnEntry + 9) == '?') || (*(ffnEntry + 9) == *(entry + 9))) &&
|
||||
((*(ffnEntry + 10) == '?') || (*(ffnEntry + 10) == *(entry + 10))) &&
|
||||
((*(ffnEntry + 11) == '?') || (*(ffnEntry + 11) == *(entry + 11)))) {
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Konverterer et tegn til et tegn som kan brukes i alle filnavn på så godt
|
||||
* som alle operativsystem
|
||||
*
|
||||
* c: tegn som skal konverteres
|
||||
*/
|
||||
char legalChar (char c) {
|
||||
const char *legalChars = "_^$~!#&-{}@'";
|
||||
|
||||
if (!strchr (legalChars, c)) {
|
||||
if ((c < 48) || (c > 57 && c < 65) || (c > 90 && c < 97) || (c >122)) {
|
||||
return '#';
|
||||
}
|
||||
}
|
||||
return toupper (c);
|
||||
}
|
||||
|
||||
/* Gir en peker til første tegn i filnavnet (etter evt. sti)
|
||||
*
|
||||
* ffn: filnavn med evt. sti
|
||||
*/
|
||||
char *stripPath (char *ffn) {
|
||||
char *ptr;
|
||||
|
||||
if (!(ptr = strrchr (ffn, '/'))) {
|
||||
if (!(ptr = strrchr (ffn, '\\'))) {
|
||||
if (!(ptr = strrchr (ffn, ':'))) {
|
||||
ptr = ffn - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ptr + 1;
|
||||
}
|
118
tikidisk-src/tikidisk.txt
Normal file
118
tikidisk-src/tikidisk.txt
Normal file
@ -0,0 +1,118 @@
|
||||
tikidisk V1.1, 24 august 2001
|
||||
|
||||
Copyright (c) Asbjørn Djupdal 2001
|
||||
|
||||
Jeg gir tillatelse til å bruke og spre dette verktøyet fritt bortsett
|
||||
fra til kommersielle formål. Det skal aldri tjenes penger på dette
|
||||
produktet.
|
||||
|
||||
|
||||
Kort beskrivelse:
|
||||
-----------------
|
||||
|
||||
Et program som lar deg manipulere TIKI-100 diskettfiler.
|
||||
Støtter alle TIKI-100 diskettfiler.
|
||||
Kildefiler tilgjengelige på min TIKI-100 hjemmeside:
|
||||
http://www.stud.ntnu.no/tiki/
|
||||
|
||||
Bruk:
|
||||
-----
|
||||
|
||||
tikidisk <diskfil> {lxad}[brukernr] <filnavn...>
|
||||
|
||||
Hvor
|
||||
|
||||
{lxad} er en (og bare en) av disse:
|
||||
l = vis liste over filer i diskettfila
|
||||
x = hent ut filer fra diskettfila
|
||||
a = legg filer til diskettfila
|
||||
d = slett filer fra diskettfila
|
||||
|
||||
[brukernr] er brukernummer til filens eier. Dersom denne
|
||||
utelates vil det tilsvare alle brukere for
|
||||
kommandoene 'l','x' og 'd', mens for kommandoen a vil
|
||||
det tilsvare bruker 0.
|
||||
<diskfil> er navn på diskettfilen, må oppgis
|
||||
<filnavn...> er en eller flere filnavn
|
||||
|
||||
Eksempler:
|
||||
----------
|
||||
|
||||
Her er noen eksempler på bruk av 'tikidisk'. Får du ikke disse
|
||||
eksemplene til å virke så les merknad om jokertegn senere i denne
|
||||
teksten.
|
||||
|
||||
tikidisk disk.dsk l *.*
|
||||
- lister hele katalogen til disk.dsk på skjermen
|
||||
|
||||
tikidisk disk.dsk x1 *.*
|
||||
- henter ut alle filer med brukernummer 1 fra disk.dsk
|
||||
|
||||
tikidisk disk.dsk x1 fil1.xxx fil2.xxx
|
||||
- henter ut fil1.xxx og fil2.xxx med brukernummer 1
|
||||
|
||||
tikidisk disk.dsk x *.txt
|
||||
- henter ut alle filer med filtype "txt", uansett brukernummer
|
||||
|
||||
tikidisk disk.dsk a1 fil1.xxx
|
||||
- legger fil1.xxx til disk.dsk med brukernummer 1
|
||||
|
||||
tikidisk disk.dsk a fil1.xxx
|
||||
- legger fil1.xxx til disk.dsk med brukernummer 0
|
||||
|
||||
tikidisk disk.dsk d *.txt
|
||||
- sletter alle filer med filtype "txt" fra disk.dsk
|
||||
|
||||
|
||||
Merk:
|
||||
-----
|
||||
|
||||
- Du godt kan utelate brukernummer. Det vil føre til at for
|
||||
kommandoene 'l','x' og 'd' vil alle filer med riktig filnavn
|
||||
"treffe", uansett hvilket brukernummer de har. For kommandoen 'a'
|
||||
vil programmet benytte brukernummer 0.
|
||||
|
||||
- Jokertegn fungerer akkurat som på en TIKI-100, du kan benytte både *
|
||||
og ?.
|
||||
|
||||
- Noen kommandolinje-systemer (hovedsaklig UNIX-shell) ekspanderer
|
||||
automatisk jokertegn før argumentene sendes til kommandoen. Det
|
||||
fører til at du må ha gåseøyne (") rundt alle argumenter som
|
||||
inneholder jokertegn, unntatt for kommandoen 'a' fordi det der er
|
||||
ønskelig at systemet skal ekspandere jokertegn.
|
||||
|
||||
Eks:
|
||||
tikidisk disk.dsk l "*.*"
|
||||
- lister hele katalogen til disk.dsk
|
||||
|
||||
Format på listing av katalog:
|
||||
-----------------------------
|
||||
|
||||
Ved bruk av l-kommadoen får du en liste som ser slik ut:
|
||||
|
||||
128 --- 00: TEST.FIL
|
||||
256 lsa 01: TEST2.FIL
|
||||
2 filer, 384 bytes
|
||||
|
||||
Det første tallet er filstørrelsen i bytes.
|
||||
Så kommer filattributtene: skrivebeskyttet (l), system (s) og arkivert (a).
|
||||
Neste tall er brukernummer til fila.
|
||||
Til slutt kommer filnavnet.
|
||||
|
||||
Nederst vises antall filer i diskettfila, og totalt antall bytes for alle
|
||||
filene.
|
||||
|
||||
Historie:
|
||||
---------
|
||||
|
||||
* 24 aug 2001 Versjon 1.1
|
||||
- Nesten helt omskrevet
|
||||
- Lagt til støtte for jokertegn
|
||||
- Lagt til støtte for 90k-diskettfiler.
|
||||
- Kildefiler tilgjengelig
|
||||
* 22 jan 2001 Versjon 1.0
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Har du spørsmål eller kommentarer, så ta kontakt med meg:
|
||||
Asbjørn Djupdal, djupdal@stud.ntnu.no
|
Reference in New Issue
Block a user