Tenkte denne var grei å ha med også :-)
This commit is contained in:
parent
e2b433e4b4
commit
aaee3363c4
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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