202 lines
4.5 KiB
C++
202 lines
4.5 KiB
C++
/*
|
|
* PathTable.c++
|
|
*
|
|
* Description:
|
|
* Implementation of the PathTable class
|
|
*
|
|
* History:
|
|
* rogerc 04/15/91 Created
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stream.h>
|
|
#include "Block.h"
|
|
#include "PathTable.h"
|
|
#include "util.h"
|
|
|
|
#define VHBLOCK 16
|
|
|
|
#define ISOID 1
|
|
#define HSFSID 9
|
|
|
|
#define ISO_PTSIZE 136
|
|
#define ISO_PTLOC 148
|
|
#define ISO_BLKSIZE 130
|
|
|
|
#define HSFS_PTSIZE 144
|
|
#define HSFS_PTLOC 164
|
|
#define HSFS_BLKSIZE 138
|
|
#define MAXNAMELEN 300;
|
|
|
|
/*
|
|
* This is for the byte layout of the path table as it comes off
|
|
* the disc
|
|
*/
|
|
typedef struct iso_rawpt {
|
|
char pt_len;
|
|
char pt_xattr_len;
|
|
char pt_ext_loc[4];
|
|
char pt_parent[2];
|
|
char pt_name[1];
|
|
} ISO_RAWPT;
|
|
|
|
typedef struct hsfs_rawpt {
|
|
char pt_ext_loc[4];
|
|
char pt_xattr_len;
|
|
char pt_len;
|
|
char pt_parent[2];
|
|
char pt_name[1];
|
|
} HSFS_RAWPT;
|
|
|
|
PathTable::PathTable(char *devscsi, int notranslate)
|
|
{
|
|
Block vh(VHBLOCK, devscsi);
|
|
|
|
if (strncmp(vh + ISOID, "CD001", 5) == 0) {
|
|
disctype = ISO;
|
|
int ptLoc = CHARSTOLONG(vh + ISO_PTLOC);
|
|
int ptSize = CHARSTOLONG(vh + ISO_PTSIZE);
|
|
blockSize = CHARSTOSHORT(vh + ISO_BLKSIZE);
|
|
Block ptBlock(ptLoc, (ptSize + blockSize - 1) / blockSize,
|
|
devscsi);
|
|
|
|
/*
|
|
* Figure out the maximum number of path table records possible, and
|
|
* allocate that many from the free store
|
|
*/
|
|
int maxRecords = ptSize / sizeof (ISO_RAWPT);
|
|
pt = new PT[maxRecords];
|
|
pathCount = 0;
|
|
int bytesSoFar = 0;
|
|
int bytesThisTime;
|
|
|
|
ISO_RAWPT *rawpt = (ISO_RAWPT *)(char *)ptBlock;
|
|
|
|
while (bytesSoFar < ptSize) {
|
|
PT *ptp = pt + pathCount;
|
|
|
|
ptp->pt_parent = CHARSTOSHORT(rawpt->pt_parent) - 1;
|
|
int stlen;
|
|
char *str;
|
|
str = to_unixname(rawpt->pt_name, rawpt->pt_len, notranslate);
|
|
stlen = strlen(str);
|
|
ptp->pt_name = new char[stlen + 1];
|
|
strncpy(ptp->pt_name, str, stlen);
|
|
ptp->pt_name[stlen] = '\0';
|
|
ptp->pt_loc = CHARSTOLONG(rawpt->pt_ext_loc);
|
|
ptp->pt_dirp = new Directory(ptp->pt_loc + rawpt->pt_xattr_len,
|
|
devscsi, notranslate, disctype);
|
|
|
|
bytesThisTime = sizeof (*rawpt) + rawpt->pt_len - 1;
|
|
if (bytesThisTime & 1)
|
|
bytesThisTime++;
|
|
|
|
pathCount++;
|
|
bytesSoFar += bytesThisTime;
|
|
rawpt = (ISO_RAWPT *)((char *)rawpt + bytesThisTime);
|
|
}
|
|
}
|
|
else if (strncmp(vh + HSFSID, "CDROM", 5) == 0) {
|
|
disctype = HSFS;
|
|
int ptLoc = CHARSTOLONG(vh + HSFS_PTLOC);
|
|
int ptSize = CHARSTOLONG(vh + HSFS_PTSIZE);
|
|
blockSize = CHARSTOSHORT(vh + HSFS_BLKSIZE);
|
|
Block ptBlock(ptLoc, (ptSize + blockSize - 1) / blockSize,
|
|
devscsi);
|
|
|
|
/*
|
|
* Figure out the maximum number of path table records possible, and
|
|
* allocate that many from the free store
|
|
*/
|
|
int maxRecords = ptSize / sizeof (HSFS_RAWPT);
|
|
pt = new PT[maxRecords];
|
|
pathCount = 0;
|
|
int bytesSoFar = 0;
|
|
int bytesThisTime;
|
|
|
|
HSFS_RAWPT *rawpt = (HSFS_RAWPT *)(char *)ptBlock;
|
|
|
|
while (bytesSoFar < ptSize) {
|
|
PT *ptp = pt + pathCount;
|
|
|
|
ptp->pt_parent = CHARSTOSHORT(rawpt->pt_parent) - 1;
|
|
int stlen;
|
|
char *str;
|
|
str = to_unixname(rawpt->pt_name, rawpt->pt_len, notranslate);
|
|
stlen = strlen(str);
|
|
ptp->pt_name = new char[stlen + 1];
|
|
strncpy(ptp->pt_name, str, stlen);
|
|
ptp->pt_name[stlen] = '\0';
|
|
ptp->pt_loc = CHARSTOLONG(rawpt->pt_ext_loc);
|
|
ptp->pt_dirp = new Directory(ptp->pt_loc, devscsi, notranslate,
|
|
disctype);
|
|
|
|
bytesThisTime = sizeof (*rawpt) + rawpt->pt_len - 1;
|
|
if (bytesThisTime & 1)
|
|
bytesThisTime++;
|
|
|
|
pathCount++;
|
|
bytesSoFar += bytesThisTime;
|
|
rawpt = (HSFS_RAWPT *)((char *)rawpt + bytesThisTime);
|
|
}
|
|
}
|
|
else {
|
|
cerr << progname << ": invalid disc\n";
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
void
|
|
PathTable::dump()
|
|
{
|
|
for (int i = 0; i < pathCount; i++) {
|
|
printf("name: %s\tcount: %d\tloc: %d\tparent: %d\n",
|
|
pt[i].pt_name, pt[i].pt_count, pt[i].pt_loc, pt[i].pt_parent);
|
|
pt[i].pt_dirp->dump();
|
|
}
|
|
}
|
|
|
|
int
|
|
PathTable::check()
|
|
{
|
|
int err = 0;
|
|
for (int i = 0; i < pathCount; i++)
|
|
if (pt[i].pt_dirp->check())
|
|
err = 1;
|
|
|
|
return (err);
|
|
}
|
|
|
|
PathTable::~PathTable()
|
|
{
|
|
delete pt;
|
|
}
|
|
|
|
Directory *
|
|
PathTable::Dir(char *path)
|
|
{
|
|
char *p = strdup(path);
|
|
char *comp;
|
|
int parent = 0;
|
|
|
|
for (comp = strtok(p, "/"); comp && parent != -1;
|
|
comp = strtok(0, "/"))
|
|
parent = findDir(comp, parent);
|
|
|
|
free(p);
|
|
return parent == -1 ? 0 : pt[parent].pt_dirp;
|
|
}
|
|
|
|
|
|
int
|
|
PathTable::findDir(char *name, int parent)
|
|
{
|
|
for (int i = parent + 1; i < pathCount && parent >= pt[i].pt_parent; i++)
|
|
if (strcmp(name, pt[i].pt_name) == 0 &&
|
|
pt[i].pt_parent == parent)
|
|
return i;
|
|
|
|
return -1;
|
|
}
|