Interdata_v6/usr/source/wgong/export.c
/*
* export dev filename [recl]
*
* Copy a file to an OS-formatted disc.
* Output file will be indexed, lrecl=recl, blksize 1/1.
*
* Note: no check is made to see whether the OS file already exists --
* this may cause duplicate filenames.
*/
/* OS directory structure */
struct dir {
char fnm[12];
int flba;
int llba;
int keyl;
int date[2];
int counts;
char atrb;
char dbsz;
char ibsz;
char flro;
int csec;
int filler;
};
struct dirblk {
int nextdir;
struct dir dirent[5];
};
/* OS disc information */
int disc; /* fd for OS disc */
int bitmapsector; /* bit map */
int bitmap[19584/32];
int dirsector; /* directory block */
struct dirblk dirbuff;
struct dir *dirp; /* ¤t dir entry */
int indexsector; /* index block */
int indexbuf[64];
int *indexp; /* &next free index */
int offset; /* no. of chars in file */
int recl; /* logical record length of file */
char buffer[256];
main(argc, argv)
char *argv[];
{
register len, i;
if (argc < 3)
error("Usage: export dev filename [recl]");
if ((disc = open(argv[1], 2)) < 0)
error("Can't open %s", argv[1]);
close(0);
if (open(argv[2], 0) != 0)
error("Can't find %s", argv[2]);
if (argc < 4 || (recl = atoi(argv[3])) <= 0)
recl = 256;
getmap();
oscreat(argv[2]);
while ((len = read(0, buffer, 256)) > 0) {
offset =+ len;
while (len < 256)
buffer[len++] = '\0'; /* pad last block with zeroes */
oswrite(buffer);
}
if (len < 0)
error("Input file read error");
/* because of the peculiar way in which os/32 functions, if the
* logical file size is an exact multiple of 256 bytes, an extra
* block must be allocated. I don't know whether this is a bug
* or a feature.
*/
if (recl == 256)
offset = (offset+255)&~0377;
else
offset = (offset/recl)*recl;
if ((offset&0377) == 0)
oswrite(buffer);
osflush();
putmap();
}
/*
* Error exit
*/
error(s, x)
{
printf(s, x);
putchar('\n');
exit(1);
}
/*
* Initialize directory entry and first index block for new OS file
*/
oscreat(name)
{
register struct dir *dp;
dirp = dp = makdir();
zero(dp, sizeof *dp);
packfd(name, dp->fnm);
dp->atrb = 0120; /* indexed file */
dp->ibsz = dp->dbsz = 1; /* blksize 1/1 */
dp->keyl = recl; /* record length */
indexsector = alloc();
dp->flba = indexsector;
indexbuf[0] = 0;
indexp = &indexbuf[2];
}
/*
* Zero a block of memory
*/
zero(addr, len)
char *addr;
{
register char *p;
register n;
p = addr;
for (n=len; n--; *p++ = '\0')
;
}
/*
* Pack a file name into OS directory format, converting lowercase
* letters to uppercase.
*/
packfd(name, dest)
char *name, *dest;
{
register char *p;
register c, i;
i = 0;
for (p=name; (c = *p) != '\0' && c != '.'; p++)
if (i < 8) {
if (c >= 'a' && c <= 'z')
c =+ 'A'-'a';
dest[i++] = c;
}
while(i < 8)
dest[i++] = ' ';
if (c = '.')
for (p++; (c = *p) != '\0'; p++)
if (i < 11) {
if (c>='a' && c<='z')
c =+ 'A'-'a';
dest[i++] = c;
}
while (i < 11)
dest[i++] = ' ';
}
/*
* Get an unused directory entry. If none found, allocate a new
* directory block. Return a pointer to the dir entry.
*/
makdir()
{
register struct dir *dp;
int sector;
seek(disc, 8, 0);
if (read(disc, §or, sizeof sector) <= 0)
error("Volume descriptor read error");
if (sector == 0)
error("No directory entries");
while(sector) {
dirsector = sector;
xseek(disc, dirsector);
if (xread(disc, &dirbuff, sizeof dirbuff))
error("Directory block read error");
for (dp = &dirbuff.dirent[0]; dp < &dirbuff.dirent[5]; dp++)
if ((dp->atrb&020) == 0)
return(dp);
sector = dirbuff.nextdir;
}
xseek(disc, dirsector);
dirsector = alloc();
dirbuff.nextdir = dirsector;
xwrite(disc, &dirbuff, sizeof dirbuff);
zero(&dirbuff, sizeof dirbuff);
return(&dirbuff.dirent[0]);
}
/*
* Write one sector of the OS file
*/
oswrite(buff)
{
register sector;
sector = alloc();
if (indexp >= &indexbuf[64])
nextblk();
*indexp++ = sector;
xseek(disc, sector);
xwrite(disc, buff, 256);
}
/*
* Allocate the next index block
*/
nextblk()
{
register sector;
sector = alloc();
indexbuf[1] = sector;
xseek(disc, indexsector);
xwrite(disc, indexbuf, sizeof indexbuf);
indexbuf[0] = indexsector;
indexsector = sector;
indexp = &indexbuf[2];
}
/*
* Update directory information and flush the last index block
*/
osflush()
{
while (indexp < indexbuf[64])
*indexp++ = 0;
indexbuf[1] = 0;
xseek(disc, indexsector);
xwrite(disc, indexbuf, sizeof indexbuf);
dirp->csec = offset/recl;
dirp->llba = indexsector;
xseek(disc, dirsector);
xwrite(disc, &dirbuff, sizeof dirbuff);
}
/*
* Read bit map
*/
getmap()
{
seek(disc, 20, 0);
if (read(disc, &bitmapsector, sizeof bitmapsector) <= 0)
error("Volume descriptor read error");
xseek(disc, bitmapsector);
if (xread(disc, bitmap, sizeof bitmap))
error("Bit map read error");
}
/*
* Rewrite bit map
*/
putmap()
{
xseek(disc, bitmapsector);
xwrite(disc, bitmap, sizeof bitmap);
}
/*
* Allocate one free sector from the bit map -- return sector number.
*/
alloc()
{
register d, i, b;
for (d=0; d<sizeof bitmap; d++)
if (bitmap[d] != -1) {
for (i=31; bitmap[d]&(b = 1<<i); i--)
;
bitmap[d] =| b;
return(32*d + 31-i);
}
error("Disc full");
}
/*
* OS disc i/o routines
*/
xseek(fd, sect)
{
seek(fd, sect*256, 0);
}
xread(fd, addr, len)
{
return(read(fd, addr, len) <= 0);
}
xwrite(fd, addr, len)
{
if (write(fd, addr, len) != len)
error("Write error");
}