Skip to content

Instantly share code, notes, and snippets.

@shattered
Created April 26, 2013 05:00
Show Gist options
  • Select an option

  • Save shattered/5465119 to your computer and use it in GitHub Desktop.

Select an option

Save shattered/5465119 to your computer and use it in GitHub Desktop.
RT-11 filesystem support in NetBSD's makefs utility (WIP)
diff --exclude .git -ruN makefs/Makefile makefs1/Makefile
--- makefs/Makefile 2011-07-19 02:52:37.000000000 +0400
+++ makefs1/Makefile 2013-04-20 19:10:45.000000000 +0400
@@ -6,7 +6,7 @@
.include <bsd.own.mk>
PROG= makefs
-SRCS= cd9660.c ffs.c v7fs.c \
+SRCS= cd9660.c ffs.c rt11fs.c v7fs.c \
getid.c \
makefs.c misc.c \
pack_dev.c \
@@ -22,6 +22,7 @@
.include "${.CURDIR}/cd9660/Makefile.inc"
.include "${.CURDIR}/ffs/Makefile.inc"
+.include "${.CURDIR}/rt11fs/Makefile.inc"
.include "${.CURDIR}/v7fs/Makefile.inc"
.if !defined(HOSTPROG)
diff --exclude .git -ruN makefs/makefs.8 makefs1/makefs.8
--- makefs/makefs.8 2012-01-28 06:35:46.000000000 +0400
+++ makefs1/makefs.8 2013-04-20 17:27:49.000000000 +0400
@@ -201,6 +201,8 @@
ISO 9660 file system.
.It Sy v7fs
7th Edition(V7) file system.
+.It Sy rt11fs
+RT-11 file system.
.El
.It Fl x
Exclude file system nodes not explicitly listed in the specfile.
diff --exclude .git -ruN makefs/makefs.c makefs1/makefs.c
--- makefs/makefs.c 2012-01-28 06:35:46.000000000 +0400
+++ makefs1/makefs.c 2013-04-15 21:56:20.000000000 +0400
@@ -73,6 +73,8 @@
{ "ffs", ffs_prep_opts, ffs_parse_opts, ffs_cleanup_opts, ffs_makefs },
{ "cd9660", cd9660_prep_opts, cd9660_parse_opts, cd9660_cleanup_opts,
cd9660_makefs},
+ { "rt11fs", rt11fs_prep_opts, rt11fs_parse_opts, rt11fs_cleanup_opts,
+ rt11fs_makefs },
{ "v7fs", v7fs_prep_opts, v7fs_parse_opts, v7fs_cleanup_opts,
v7fs_makefs },
{ .type = NULL },
diff --exclude .git -ruN makefs/makefs.h makefs1/makefs.h
--- makefs/makefs.h 2012-01-28 06:35:46.000000000 +0400
+++ makefs1/makefs.h 2013-04-15 20:58:17.000000000 +0400
@@ -172,6 +172,11 @@
void cd9660_cleanup_opts(fsinfo_t *);
void cd9660_makefs(const char *, const char *, fsnode *, fsinfo_t *);
+void rt11fs_prep_opts(fsinfo_t *);
+int rt11fs_parse_opts(const char *, fsinfo_t *);
+void rt11fs_cleanup_opts(fsinfo_t *);
+void rt11fs_makefs(const char *, const char *, fsnode *, fsinfo_t *);
+
void v7fs_prep_opts(fsinfo_t *);
int v7fs_parse_opts(const char *, fsinfo_t *);
void v7fs_cleanup_opts(fsinfo_t *);
diff --exclude .git -ruN makefs/rt11fs/Makefile.inc makefs1/rt11fs/Makefile.inc
--- makefs/rt11fs/Makefile.inc 1970-01-01 03:00:00.000000000 +0300
+++ makefs1/rt11fs/Makefile.inc 2013-04-19 00:51:15.000000000 +0400
@@ -0,0 +1,7 @@
+.PATH: ${.CURDIR}/rt11fs
+
+SRCS+= rt11fs_rad50.c
+.if !defined(HOSTPROG)
+LDADD+= -lz
+DPADD+= ${LIBZ}
+.endif
diff --exclude .git -ruN makefs/rt11fs/rt11fs_rad50.c makefs1/rt11fs/rt11fs_rad50.c
--- makefs/rt11fs/rt11fs_rad50.c 1970-01-01 03:00:00.000000000 +0300
+++ makefs1/rt11fs/rt11fs_rad50.c 2013-04-20 17:57:35.000000000 +0400
@@ -0,0 +1,101 @@
+/*-
+ * All rights reserved.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <zlib.h>
+
+#include "makefs.h"
+#include "rt11fs_makefs.h"
+#include "rt11fs/rt11fs_rad50.h"
+
+/* taken from 4.2BSD's arff.c */
+
+static char table[256] = {
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
+30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
+29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
+29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 0, 29, 29, 29, 27, 29, 29, 29, 29, 29, 29, 29, 29, 29, 28, 29,
+30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 29, 29, 29, 29, 29, 29,
+29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29, 29,
+29, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 29, 29, 29, 29 };
+
+#define Ain1 03100
+#define Ain2 050
+
+void
+rad50 (const char *cp, uint16_t *out)
+{
+ int m;
+ uint16_t temp;
+
+ for (m = 0; *cp; m++) {
+ temp = Ain1 * table[(int)*cp++];
+ if (*cp!=0) {
+ temp += Ain2 * table[(int)*cp++];
+ if(*cp!=0)
+ temp += table[(int)*cp++];
+ }
+ out[m] = htole16(temp);
+ }
+}
+
+void
+srad50 (char *name, uint16_t *rname)
+{
+ int m;
+ char *cp;
+ char file[7], ext[4];
+
+ /*
+ * Find end of pathname
+ */
+ for (cp = name; *cp++; )
+ ;
+ while (cp >= name && *--cp != '/')
+ ;
+ cp++;
+ /*
+ * Change to rad50
+ */
+ for (m = 0; *cp; ) {
+ file[m++] = *cp++;
+ if (*cp == '.') {
+ cp++;
+ break;
+ }
+ if (m > 5) {
+ break;
+ }
+ }
+ file[m] = 0;
+ for (m = 0; *cp; ) {
+ ext[m++] = *cp++;
+ if (*cp == '.' || m > 2)
+ break;
+ }
+ ext[m]=0;
+ rname[0] = rname[1] = rname[2] = 0;
+ rad50((const char *)file, rname);
+ rad50((const char *)ext, rname+2);
+}
diff --exclude .git -ruN makefs/rt11fs/rt11fs_rad50.h makefs1/rt11fs/rt11fs_rad50.h
--- makefs/rt11fs/rt11fs_rad50.h 1970-01-01 03:00:00.000000000 +0300
+++ makefs1/rt11fs/rt11fs_rad50.h 2013-04-20 17:57:35.000000000 +0400
@@ -0,0 +1,13 @@
+/*-
+ * All rights reserved.
+ */
+
+#ifndef _RT11FS_RAD50_H
+#define _RT11FS_RAD50_H
+
+#include <sys/endian.h>
+
+void rad50 (const char *, uint16_t *);
+void srad50 (char *, uint16_t *);
+
+#endif
diff --exclude .git -ruN makefs/rt11fs.c makefs1/rt11fs.c
--- makefs/rt11fs.c 1970-01-01 03:00:00.000000000 +0300
+++ makefs1/rt11fs.c 2013-04-25 23:33:28.000000000 +0400
@@ -0,0 +1,404 @@
+/*-
+ * All rights reserved.
+ */
+
+#if HAVE_NBTOOL_CONFIG_H
+#include "nbtool_config.h"
+#endif
+
+#include <sys/endian.h>
+#include <sys/param.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <util.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "makefs.h"
+#include "rt11fs_makefs.h"
+#include "rt11fs/rt11fs_rad50.h"
+
+static int rt11fs_create_image(const char *, fsinfo_t *);
+static int rt11fs_estimate(const char *, fsnode *, fsinfo_t *);
+static int rt11fs_populate(const char *, fsnode *, fsinfo_t *);
+void rt11fs_name(char *, uint16_t *, int *);
+void rt11fs_date(time_t, uint16_t *, int *);
+
+rt11fs_opt_t rt11fs_opts;
+static struct rt_dir rt11fs_dir[RT_DIRSEGS];
+static struct rt_home rt11fs_home;
+
+void
+rt11fs_name(char *name, uint16_t * rtnamep, int *errp)
+{
+ srad50(name, rtnamep);
+ *errp = 0;
+}
+
+void
+rt11fs_date(time_t mtime, uint16_t * rtdatp, int *errp)
+{
+ struct tm *rtp;
+
+ *errp = 0;
+
+ rtp = localtime(&mtime);
+ if (!rtp) {
+ *errp = errno;
+ return;
+ }
+ if (rtp->tm_year < 72) {
+ *rtdatp = 0;
+ return;
+ }
+ if (rtp->tm_year > (rt11fs_opts.y2k_date ? 199 : 103)) {
+ *rtdatp = 0;
+ return;
+ }
+
+ *rtdatp = (rtp->tm_year - 72) % 32;
+ *rtdatp |= rtp->tm_mday << 5;
+ *rtdatp |= (rtp->tm_mon + 1) << 10;
+ *rtdatp |= ((rtp->tm_year - 72) / 32) << 14;
+ /*
+ 15-14 :2 Age (0-3)
+ 13-10 :4 Month (1-12)
+ 9-5 :5 Day (1-31)
+ 4-0 :5 Year minus 1972 minus 32*Age
+ */
+}
+
+void
+rt11fs_prep_opts(fsinfo_t * fsopts)
+{
+
+ fsopts->fs_specific = &rt11fs_opts;
+}
+
+void
+rt11fs_cleanup_opts(fsinfo_t * fsopts)
+{
+ /* NO-OP */
+}
+
+int
+rt11fs_parse_opts(const char *option, fsinfo_t * fsopts)
+{
+ static option_t rt11fs_options[] = {
+ {"sys_version", &rt11fs_opts.sys_version, 3, 5,
+ "Home block version"},
+ {"dir_segments", &rt11fs_opts.dir_segments, 1, 31,
+ "Number of directory segments"},
+ {"y2k_date", &rt11fs_opts.y2k_date, 0, 1,
+ "Y2K-aware date format"},
+ {.name = NULL}
+ };
+
+ set_option(rt11fs_options, option, "1");
+
+ return 1;
+}
+
+static int
+rt11fs_create_image(const char *image, fsinfo_t * fsopts)
+{
+ uint16_t *p, sum;
+ int m;
+ char tmp[13];
+
+ assert(image != NULL);
+ assert(fsopts != NULL);
+
+ rt11fs_home.rt_clsize = htole16(1);
+ rt11fs_home.rt_dirblk = htole16(RT_DIRBLK);
+ rad50("V3A", &rt11fs_home.rt_sysver); /* V05 and V4A also exist */
+ snprintf(tmp, 13, "%-12s", "RT11A");
+ memcpy(rt11fs_home.rt_volid, tmp, 12);
+ snprintf(tmp, 13, "%-12s", "DECRT11A");
+ memcpy(rt11fs_home.rt_sysid, tmp, 12);
+ snprintf(tmp, 13, "%-12s", "makefs(8)");
+ memcpy(rt11fs_home.rt_owner, tmp, 12);
+
+ sum = 0;
+ p = (uint16_t *) (void *) &rt11fs_home;
+ for (m = 0; m < 255; m++)
+ sum += le16toh(*p++);
+
+ rt11fs_home.rt_cksum = htole16(sum);
+
+ if ((fsopts->fd = open(image, O_RDWR | O_CREAT | O_TRUNC, 0666)) == -1) {
+ warn("Can't open `%s' for writing", image);
+ return -1;
+ }
+ if (lseek(fsopts->fd, fsopts->maxsize - 1, SEEK_SET) == -1) {
+ warn("Can't seek `%s' to %lld", image, fsopts->size - 1);
+ return -1;
+ }
+ if (write(fsopts->fd, "\0", 1) != 1) {
+ warn("Can't write `%s'", image);
+ return -1;
+ }
+ if (lseek(fsopts->fd, RT_SECSIZE, SEEK_SET) == -1) {
+ warn("Can't seek `%s' to home block", image);
+ return -1;
+ }
+ if (write(fsopts->fd, (void *) &rt11fs_home, RT_SECSIZE) != RT_SECSIZE) {
+ warn("Can't write home block to `%s'", image);
+ return -1;
+ }
+ return fsopts->fd;
+}
+
+static int
+rt11fs_estimate(const char *dir, fsnode * root, fsinfo_t * fsopts)
+{
+ fsnode *cur;
+ int failed;
+ off_t size;
+
+ assert(dir != NULL);
+ assert(root != NULL);
+ assert(fsopts != NULL);
+
+ failed = 0;
+
+ if (fsopts->maxsize > RT_MAXSIZE) {
+ errx(EXIT_FAILURE, "maxsize of %lld is greater than maximum supported of 32M.",
+ fsopts->maxsize);
+ }
+
+/* from PUTR.ASM:
+rtnseg dw 512d ;Up to 512 blocks
+ dw 1 ;we get 1 segment.
+ dw 2048d ;Up to 2048 blocks
+ dw 4 ;we get 4 segments.
+ dw 12288d ;Up to 12288 blocks
+ dw 16d ;we get 16 segments.
+ dw -1 ;Over that
+ dw 31d ;we get 31 segments (max allowed).
+*/
+ if (rt11fs_opts.dir_segments == 0) {
+ if (fsopts->maxsize <= 512 * RT_SECSIZE)
+ rt11fs_opts.dir_segments = 1;
+ else if (fsopts->maxsize <= 2048 * RT_SECSIZE)
+ rt11fs_opts.dir_segments = 4;
+ else if (fsopts->maxsize <= 12288 * RT_SECSIZE)
+ rt11fs_opts.dir_segments = 16;
+ else
+ rt11fs_opts.dir_segments = 31;
+ };
+ fsopts->size = RT_SECSIZE * (6 + 2 * rt11fs_opts.dir_segments);
+
+ for (cur = root; cur != NULL; cur = cur->next) {
+ switch (cur->type & S_IFMT) {
+ case S_IFREG:
+ size = (cur->inode->st.st_size + 511) & ~511;
+ fsopts->size += size;
+ fsopts->inodes++;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* leave 1 entry for EMPTY.FIL */
+ if (fsopts->inodes > (rt11fs_opts.dir_segments * RT_DIRENTS - 1)) {
+ errx(EXIT_FAILURE, "`%s' inode count of %lld is larger than the maximum of %d.",
+ dir, fsopts->inodes, rt11fs_opts.dir_segments * RT_DIRENTS);
+ }
+ if (fsopts->maxsize > 0 && fsopts->size > fsopts->maxsize) {
+ errx(EXIT_FAILURE, "`%s' size of %lld is larger than the maxsize of %lld.",
+ dir, fsopts->size, fsopts->maxsize);
+ }
+ return failed ? 2 : 0;
+}
+
+/*
+- open 1st directory segment (populate word 4)
+- for each file:
+ - fill directory entry (status word = E.PERM)
+ - write file data to image
+ - find next directory entry in this segment
+ - if none available, close this segment (populate word 1 and write
+ E.EOS into last word, if available) and open a new segment
+- close last and 1st (populate words 0 and 2) directory segments
+- write directory to disk
+*/
+static int
+rt11fs_populate(const char *dir, fsnode * root, fsinfo_t * fsopts)
+{
+ int error, failed, rt11fs_file, rt11fs_segment, fd, m, x;
+ size_t blk_nr, blocks;
+ char *name, empty_fil[10];
+ uint8_t *buf;
+ off_t blk_offset, bytes_read, bytes_written;
+ fsnode *cur;
+ struct rt_ent *entry;
+
+ assert(dir != NULL);
+ assert(root != NULL);
+ assert(fsopts != NULL);
+
+ error = failed = rt11fs_file = rt11fs_segment = m = x = 0;
+ strncpy(empty_fil, "EMPTY.FIL", 10);
+
+ buf = emalloc(RT_BUFSIZE);
+ name = emalloc(PATH_MAX);
+
+ blk_nr = RT_DIRBLK + rt11fs_opts.dir_segments * 2;
+ if (debug & DEBUG_WALK_DIR)
+ printf("rt11fs_populate_dir: data starts at block %d\n", blk_nr);
+
+ /* open 1st directory segment */
+ rt11fs_dir[rt11fs_segment].rt_axhead.rt_numseg = rt11fs_opts.dir_segments;
+ rt11fs_dir[rt11fs_segment].rt_axhead.rt_stfile = blk_nr;
+
+ for (cur = root; cur != NULL; cur = cur->next) {
+ switch (cur->type & S_IFMT) {
+ case S_IFREG:
+ blocks = ((size_t) cur->inode->st.st_size + RT_SECSIZE - 1) / RT_SECSIZE;
+ if (debug & DEBUG_WALK_DIR)
+ printf("rt11fs_populate_dir: <%s> %lld bytes (%d blocks)\n",
+ cur->name, cur->inode->st.st_size, blocks);
+ entry = &rt11fs_dir[rt11fs_segment].rt_ents[rt11fs_file];
+ entry->rt_stat = RT_E_PERM;
+ if (!(cur->inode->st.st_mode & S_IWUSR))
+ entry->rt_stat |= RT_E_READ;
+ entry->rt_len = (uint16_t) blocks;
+ rt11fs_name(cur->name, &entry->rt_name[0], &error);
+ if (error)
+ break;
+ rt11fs_date(cur->inode->st.st_mtime, &entry->rt_date, &error);
+ if (error)
+ break;
+
+ /* ready to store the file */
+ snprintf(name, PATH_MAX - 1, "%s/%s", dir, cur->name);
+ fd = open(name, O_RDONLY, 0444);
+ if (fd == -1) {
+ warn("rt11fs_populate: open");
+ break;
+ }
+ blk_offset = blk_nr * RT_SECSIZE;
+ do {
+ bytes_read = read(fd, buf, RT_BUFSIZE);
+ if (bytes_read == -1) {
+ warn("rt11fs_populate: read");
+ break;
+ }
+ bytes_written = pwrite(fsopts->fd, buf, RT_BUFSIZE, blk_offset);
+ if (bytes_written == -1) {
+ warn("rt11fs_populate: write");
+ break;
+ }
+ blk_offset += bytes_written;
+ } while (bytes_read > 0);
+ close(fd);
+
+ blk_nr += blocks;
+ if (debug & DEBUG_WALK_DIR)
+ printf("rt11fs_populate_dir: OK, seg %d (of %d) ent %d\n",
+ rt11fs_segment, rt11fs_opts.dir_segments, rt11fs_file);
+
+ if (++rt11fs_file == RT_DIRENTS) {
+ /* close this segment */
+ rt11fs_dir[rt11fs_segment].rt_eos = RT_E_EOS;
+ /* open next one, if available */
+ if ((rt11fs_opts.dir_segments - rt11fs_segment) > 1) {
+ rt11fs_dir[rt11fs_segment].rt_axhead.rt_nxtseg = rt11fs_segment + 2;
+ rt11fs_segment += 1;
+ rt11fs_dir[rt11fs_segment].rt_axhead.rt_stfile = blk_nr;
+ rt11fs_file = 0;
+ }
+ }
+ break;
+ default:
+ if ((debug & DEBUG_WALK_DIR) && strcmp(cur->name, "."))
+ printf("rt11fs_populate_dir: can't handle file <%s> of type %x\n",
+ cur->name, cur->type & S_IFMT);
+ break;
+ }
+ }
+
+ /* add E.MPTY entry, if there's space for it, and then close the segment */
+ if (rt11fs_segment < rt11fs_opts.dir_segments) {
+ rt11fs_dir[rt11fs_segment].rt_ents[rt11fs_file].rt_stat = RT_E_MPTY;
+ /* name is irrelevant */
+ rt11fs_name(empty_fil, &rt11fs_dir[rt11fs_segment].rt_ents[rt11fs_file].rt_name[0], &error);
+ rt11fs_dir[rt11fs_segment].rt_ents[rt11fs_file].rt_len = (uint16_t) ((fsopts->maxsize / RT_SECSIZE) - blk_nr);
+ if (++rt11fs_file == RT_DIRENTS)
+ rt11fs_dir[rt11fs_segment].rt_eos = RT_E_EOS;
+ else
+ rt11fs_dir[rt11fs_segment].rt_ents[rt11fs_file].rt_stat = RT_E_EOS;
+ }
+ /* close 1st segment (populate word 2), write directory */
+ rt11fs_dir[0].rt_axhead.rt_lstseg = rt11fs_segment + 1;
+
+ /* byte-swap if necessary */
+#if BYTE_ORDER == BIG_ENDIAN
+ for (m = 0; m < rt11fs_opts.dir_segments; m++) {
+ HTOLE16(rt11fs_dir[m].rt_axhead.rt_numseg);
+ HTOLE16(rt11fs_dir[m].rt_axhead.rt_nxtseg);
+ HTOLE16(rt11fs_dir[m].rt_axhead.rt_lstseg);
+ HTOLE16(rt11fs_dir[m].rt_axhead.rt_entpad);
+ HTOLE16(rt11fs_dir[m].rt_axhead.rt_stfile);
+ HTOLE16(rt11fs_dir[m].rt_eos);
+ for (x = 0; x < RT_DIRENTS; x++) {
+ HTOLE16(rt11fs_dir[m].rt_ents[x].rt_stat);
+ HTOLE16(rt11fs_dir[m].rt_ents[x].rt_len);
+ HTOLE16(rt11fs_dir[m].rt_ents[x].rt_date);
+ }
+ }
+#endif
+
+ blocks = rt11fs_opts.dir_segments * sizeof(struct rt_dir);
+ if (pwrite(fsopts->fd, (void *) &rt11fs_dir, blocks, RT_SECSIZE * RT_DIRBLK) != blocks) {
+ warn("Can't write directory (%d, %p, %d, %d)", fsopts->fd, (void *) &rt11fs_dir, blocks, RT_SECSIZE * RT_DIRBLK);
+ failed = 1;
+ }
+ return failed ? 2 : 0;
+}
+
+void
+rt11fs_makefs(const char *image, const char *dir, fsnode * root, fsinfo_t * fsopts)
+{
+ struct timeval start;
+
+ assert(image != NULL);
+ assert(dir != NULL);
+ assert(root != NULL);
+ assert(fsopts != NULL);
+
+ printf("Estimating `%s'\n", image);
+ TIMER_START(start);
+ if (rt11fs_estimate(dir, root, fsopts)) {
+ warnx("Image file `%s' not estimated", image);
+ }
+ TIMER_RESULTS(start, "rt11fs_estimate");
+
+ printf("Creating `%s'\n", image);
+ TIMER_START(start);
+ if (rt11fs_create_image(image, fsopts) == -1) {
+ errx(EXIT_FAILURE, "Image file `%s' not created", image);
+ }
+ TIMER_RESULTS(start, "rt11fs_create_image");
+
+ printf("Populating `%s'\n", image);
+ TIMER_START(start);
+ if (rt11fs_populate(dir, root, fsopts)) {
+ errx(EXIT_FAILURE, "Image file `%s' not populated", image);
+ }
+ TIMER_RESULTS(start, "rt11fs_populate");
+
+ if (close(fsopts->fd) == -1) {
+ err(EXIT_FAILURE, "Closing `%s'", image);
+ }
+ fsopts->fd = -1;
+
+ printf("Image `%s' complete\n", image);
+}
diff --exclude .git -ruN makefs/rt11fs_makefs.h makefs1/rt11fs_makefs.h
--- makefs/rt11fs_makefs.h 1970-01-01 03:00:00.000000000 +0300
+++ makefs1/rt11fs_makefs.h 2013-04-20 22:00:24.000000000 +0400
@@ -0,0 +1,90 @@
+/*-
+ * All rights reserved.
+ */
+
+#ifndef _RT11FS_MAKEFS_H
+#define _RT11FS_MAKEFS_H
+
+typedef struct {
+ int dir_segments;
+ int sys_version;
+ int y2k_date;
+} rt11fs_opt_t;
+
+#define RT_BUFSIZE 16384
+
+#define RT_SECSIZE 512 /* block size */
+#define RT_MAXSIZE 65536*RT_SECSIZE/* actually 65535 */
+
+#define RT_DIRBLK 6 /* directory's starting block */
+#define RT_DIRSEGS 31 /* max # of directory segments */
+#define RT_DIRENTS 72 /* # of directory entries per segment */
+
+extern rt11fs_opt_t rt11fs_opts;
+
+#define RT_E_TENT 000400 /* Tentative file */
+#define RT_E_MPTY 001000 /* Empty area */
+#define RT_E_PERM 002000 /* Permanent file */
+#define RT_E_EOS 004000 /* End-of-segment marker */
+#define RT_E_READ 040000 /* 5.6+: Protected by monitor from write operations */
+#define RT_E_PROT 100000 /* Protected permanent file */
+#define RT_E_PRE 000020 /* ?.?+: Prefix block indicator */
+
+struct rt_head {
+ int16_t rt_numseg; /* # of segments available */
+ int16_t rt_nxtseg; /* # of next logical segment */
+ int16_t rt_lstseg; /* highest seg currently open */
+ int16_t rt_entpad; /* extra words/directory entry */
+ int16_t rt_stfile; /* block # where files begin */
+} __packed;
+
+struct rt_ent {
+ uint16_t rt_stat; /* type of entry, or end of seg */
+ uint16_t rt_name[3]; /* name, 3 words in rad50 form */
+ uint16_t rt_len; /* length of file */
+ char rt_chan; /* only used in temporary files */
+ char rt_job; /* only used in temporary files */
+ uint16_t rt_date; /* creation date; w/ Y2K support as of 5.7 */
+} __packed;
+
+struct rt_dir {
+ struct rt_head rt_axhead;
+ struct rt_ent rt_ents[RT_DIRENTS];
+ uint16_t rt_eos; /* end of segment */
+ char _dirpad[4];
+} __packed;
+
+/*
+000-201 Bad block replacement table
+202-203 ?
+204-251 INITIALIZE/RESTORE data area
+252-273 BUP information area
+274-677 ?
+700-701 (Reserved for Digital, must be zero)
+702-703 (Reserved for Digital, must be zero)
+704-721 ?
+722-723 Pack cluster size (= 1)
+724-725 Block number of first directory segment (= 6)
+726-727 System version (RAD50 "V3A")
+730-743 Volume Identification ("RT11A" and seven spaces)
+744-757 Owner name
+760-773 System Identification ("DECRT11A" and four spaces)
+774-775 ?
+776-777 Checksum (optional?)
+
+PDP-11 is little-endian in 16-bit words.
+*/
+struct rt_home {
+ char rt_bbt[0202];
+ char _pad1[0520];
+ uint16_t rt_clsize;
+ uint16_t rt_dirblk;
+ uint16_t rt_sysver;
+ char rt_volid[12];
+ char rt_owner[12];
+ char rt_sysid[12];
+ char _pad2[2];
+ uint16_t rt_cksum;
+} __packed;
+
+#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment