tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

RT-11 filesystem support for makefs



Hello,

I added DEC RT-11 filesystem support to makefs, working from manuals on
bitsavers.org [1][2], sources of PUTR [3] and arff [4], and advice from
those who actually used the PDP-11; the images are accepted by RT-11 5.3
in SIMH.  It's still work in progress, please review it.

I did not find documentation for certain features (the INIT/RESTORE data
area, bad block relocation table, how to write boot blocks...).

Number of directory segments is chosen automatically, depending on the
size of filesystem, and is also settable via option.  I'm not sure that
'extra words in directory entry' feature is useful, so it's not there.
Filesystem is not autosized yet, '-s' option is required.

Volume and Owner IDs are fixed (makefs doesn't support string options).
Timestamps can be written with or without 'age' field, and if a date
cannot be represented in RT-11 format, it is written as zero ('no
date').

[1] AA-PD6PA-TC_RT-11_Volume_and_File_Formats_Manual_Aug91.pdf
[2] AA-PE7VA-TC_RT-11_Device_Handlers_Manual_Aug91.pdf
[3] http://www.dbit.com/pub/putr/putr.asm
[4] ftp://ftp.mrynet.com/pub/os/UNIX/4.2BSD/etc/arff.c

--
Sergey Svishchev
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

Attachment: pgpY4zG0zmRvj.pgp
Description: PGP signature



Home | Main Index | Thread Index | Old Index