]> Zhao Yanbai Git Server - minix.git/commitdiff
iso9660fs: rewrite ISO 9660 file system server 33/2833/2
authorJean-Baptiste Boric <jblbeurope@gmail.com>
Sun, 3 Aug 2014 17:24:51 +0000 (19:24 +0200)
committerDavid van Moolenbroek <david@minix3.org>
Thu, 18 Sep 2014 13:00:42 +0000 (13:00 +0000)
iso9660fs has been cleaned up and debugged. It now supports:
 * ISO 9660 Level 3,
 * System Use Sharing Protocol (SUSP),
 * Rock Ridge Interchange Protocol (RRIP).

The following Rock Ridge features are supported:
 * POSIX file attributes (PX),
 * POSIX device number (PN),
 * Symbolic links (SL),
 * Alternate file name (NM),
 * Timestamps in 7-byte format (TF).

Change-Id: Ib227411bdda5bc10a957b27ad05fafdc95eca35f

21 files changed:
minix/fs/iso9660fs/Makefile
minix/fs/iso9660fs/buf.h [deleted file]
minix/fs/iso9660fs/const.h
minix/fs/iso9660fs/glo.h
minix/fs/iso9660fs/inc.h
minix/fs/iso9660fs/inode.c
minix/fs/iso9660fs/inode.h
minix/fs/iso9660fs/link.c [new file with mode: 0644]
minix/fs/iso9660fs/main.c
minix/fs/iso9660fs/misc.c
minix/fs/iso9660fs/mount.c
minix/fs/iso9660fs/path.c
minix/fs/iso9660fs/proto.h
minix/fs/iso9660fs/read.c
minix/fs/iso9660fs/stadir.c
minix/fs/iso9660fs/super.c
minix/fs/iso9660fs/super.h
minix/fs/iso9660fs/susp.c [new file with mode: 0644]
minix/fs/iso9660fs/susp_rock_ridge.c [new file with mode: 0644]
minix/fs/iso9660fs/table.c
minix/fs/iso9660fs/utility.c

index d95cfd17aeb825b1401af45acddb730971a3546b..69f05c7d5982828c56e86b99da2f113c733bd1f0 100644 (file)
@@ -1,11 +1,11 @@
 # Makefile for ISO9660 fs
 PROG=  isofs
 SRCS=  main.c table.c mount.c super.c inode.c \
-       utility.c misc.c path.c read.c stadir.c
+       link.c utility.c misc.c path.c read.c susp.c susp_rock_ridge.c stadir.c
 
 DPADD+=        ${LIBBDEV} ${LIBSYS} 
 LDADD+=        -lbdev -lsys -lc -lminixfs 
 
-CPPFLAGS+= -DNR_BUFS=100
+CPPFLAGS+= -DNR_BUFS=100 -Wall
 
 .include <minix.service.mk>
diff --git a/minix/fs/iso9660fs/buf.h b/minix/fs/iso9660fs/buf.h
deleted file mode 100644 (file)
index 39a19ce..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#include <sys/dirent.h>
-
-#define b_data(bp) ((char *) (bp->data))
-
-/* A block is free if b_dev == NO_DEV. */
-
-#define INODE_BLOCK        0                            /* inode block */
-#define DIRECTORY_BLOCK    1                            /* directory block */
index 3174947f19ad9cb7785a55a0711a0e9c3b90ec46..4443afd68c3a8ce21c238e1264ee4ea46d527d0a 100644 (file)
@@ -1,62 +1,51 @@
 
-#define GETDENTS_BUFSIZ        261
+#define GETDENTS_BUFSIZ         1024
 
-#define ISO9660_STANDARD_ID "CD001" /* Standard code for ISO9660 filesystems */
+#define ISO9660_STANDARD_ID     "CD001" /* Standard code for ISO9660 file systems */
 
-#define NR_DIR_RECORDS 256     /* Number of dir records to use at the same
-                                * time. */
-#define NR_ATTR_RECS 256       /* Number of extended attributes that is 
-                                * possible to use at the same time */
-/* #define NR_ID_INODES 1024 */        /* The ISO9660 doesn't save the inode numbers.
-                                * There is a table that assign to every inode
-                                * a particular id. This number defines the 
-                                * maximum number of ids the filesystem can 
-                                * handle */
+#define NR_INODE_RECORDS        64
+#define NR_DIR_EXTENT_RECORDS   NR_INODE_RECORDS * 16
 
-#define NO_ADDRESS (-1)                /* Error constants */
+#define NO_ADDRESS (-1)         /* Error constants */
 #define NO_FREE_INODES (-1)
 
-#define PATH_PENULTIMATE 001   /* parse_path stops at last but one name */
-#define PATH_NONSYMBOLIC 004   /* parse_path scans final name if symbolic */
-
-#define DIR_ENTRY_SIZE       sizeof (struct direct)
-#define NR_DIR_ENTRIES(b)   ((b)/DIR_ENTRY_SIZE)
+#define PATH_PENULTIMATE 001    /* parse_path stops at last but one name */
+#define PATH_NONSYMBOLIC 004    /* parse_path scans final name if symbolic */
 
 /* Below there are constant of the ISO9660 fs */
-
-#define ISO9660_SUPER_BLOCK_POSITION        (32768)
-#define ISO9660_MIN_BLOCK_SIZE          2048
+#define ISO9660_SUPER_BLOCK_POSITION    32768
+#define ISO9660_MIN_BLOCK_SIZE          2048
 
 /* SIZES FIELDS ISO9660 STRUCTURES */
-#define ISO9660_SIZE_STANDARD_ID 5
-#define ISO9660_SIZE_BOOT_SYS_ID 32
-#define ISO9660_SIZE_BOOT_ID 32
-
-#define ISO9660_SIZE_SYS_ID 32
-#define ISO9660_SIZE_VOLUME_ID 32
-#define ISO9660_SIZE_VOLUME_SET_ID 128
-#define ISO9660_SIZE_PUBLISHER_ID 128
-#define ISO9660_SIZE_DATA_PREP_ID 128
-#define ISO9660_SIZE_APPL_ID 128
-#define ISO9660_SIZE_COPYRIGHT_FILE_ID 37
-#define ISO9660_SIZE_ABSTRACT_FILE_ID 37
-#define ISO9660_SIZE_BIBL_FILE_ID 37
-
-#define ISO9660_SIZE_VOL_CRE_DATE 17
-#define ISO9660_SIZE_VOL_MOD_DATE 17
-#define ISO9660_SIZE_VOL_EXP_DATE 17
-#define ISO9660_SIZE_VOL_EFF_DATE 17
-
-#define ISO9660_SIZE_ESCAPE_SQC 32
-#define ISO9660_SIZE_PART_ID 32
-
-#define ISO9660_SIZE_SYSTEM_USE 64
+#define ISO9660_SIZE_STANDARD_ID        5
+#define ISO9660_SIZE_BOOT_SYS_ID        32
+#define ISO9660_SIZE_BOOT_ID            32
+
+#define ISO9660_SIZE_SYS_ID             32
+#define ISO9660_SIZE_VOLUME_ID          32
+#define ISO9660_SIZE_VOLUME_SET_ID      128
+#define ISO9660_SIZE_PUBLISHER_ID       128
+#define ISO9660_SIZE_DATA_PREP_ID       128
+#define ISO9660_SIZE_APPL_ID            128
+#define ISO9660_SIZE_COPYRIGHT_FILE_ID  37
+#define ISO9660_SIZE_ABSTRACT_FILE_ID   37
+#define ISO9660_SIZE_BIBL_FILE_ID       37
+
+#define ISO9660_SIZE_DATE17             17
+#define ISO9660_SIZE_DATE7             7
+
+#define ISO9660_SIZE_ESCAPE_SQC         32
+#define ISO9660_SIZE_PART_ID            32
+
+#define ISO9660_SIZE_SYSTEM_USE         64
 
 /* maximum size of length of name file used in dir records */
-#define ISO9660_MAX_FILE_ID_LEN 32
+#define ISO9660_MAX_FILE_ID_LEN         32
+#define ISO9660_RRIP_MAX_FILE_ID_LEN    256
 
-#define END_OF_FILE   (-104)   /* eof detected */
+#define END_OF_FILE                     (-104)  /* eof detected */
 
 /* Miscellaneous constants */
-#define SYS_UID  ((uid_t) 0)   /* uid_t for processes PM and INIT */
-#define SYS_GID  ((gid_t) 0)   /* gid_t for processes PM and INIT */
+#define SYS_UID  ((uid_t) 0)            /* uid_t for processes PM and INIT */
+#define SYS_GID  ((gid_t) 0)            /* gid_t for processes PM and INIT */
+
index 46b0cd9056be378759b2bd7fb61d03573dd86e28..877e9e70acb37c9e265d1cc36966fe9426dbb7e7 100644 (file)
@@ -4,30 +4,32 @@
 #define EXTERN
 #endif
 
+#include <minix/optset.h>
+
 /* The following variables are used for returning results to the caller. */
 
-EXTERN int err_code;           /* temporary storage for error number */
-EXTERN int rdwt_err;           /* status of last disk i/o request */
+EXTERN int err_code;            /* temporary storage for error number */
+EXTERN int rdwt_err;            /* status of last disk i/o request */
 
 EXTERN int(*fs_call_vec[]) (void);
 
-EXTERN message fs_m_in;                /* contains the input message of the request */
-EXTERN message fs_m_out;       /* contains the output message of the 
-                                * request */
+EXTERN message fs_m_in;         /* contains the input message of the request */
+EXTERN message fs_m_out;         /* contains the output message of the request */
 EXTERN int FS_STATE;
 
 EXTERN uid_t caller_uid;
 EXTERN gid_t caller_gid;
 
-EXTERN int req_nr;             /* request number to the server */
+EXTERN int req_nr;              /* request number to the server */
 
-EXTERN short path_processed;      /* number of characters processed */
+EXTERN short path_processed;    /* number of characters processed */
 EXTERN char user_path[PATH_MAX+1];  /* pathname to be processed */
 EXTERN char *vfs_slink_storage;
 EXTERN int symloop;
 
 EXTERN int unmountdone;
 
-EXTERN dev_t fs_dev;    /* the device that is handled by this FS proc */
-EXTERN char fs_dev_label[16]; /* Name of the device driver that is handled */
+EXTERN dev_t fs_dev;            /* the device that is handled by this FS proc */
+EXTERN char fs_dev_label[16];   /* Name of the device driver that is handled */
 
+EXTERN struct opt opt;          /* global mount options */
index 764236477985925c50f6a7ea4517ec8a51af05e0..8bc447cc9ea4fae643fc081baa60ba751a0462e5 100644 (file)
@@ -1,7 +1,7 @@
 
-#define _SYSTEM                1       /* get OK and negative error codes */
+#define _SYSTEM         1       /* get OK and negative error codes */
 
-#define VERBOSE                0       /* display diagnostics */
+#define VERBOSE         0       /* display diagnostics */
 
 #include <sys/types.h>
 #include <lib.h>
 #include <signal.h>
 #include <unistd.h>
 
+#include <stdio.h>
 #include <minix/callnr.h>
 #include <minix/config.h>
 #include <minix/type.h>
 #include <minix/const.h>
 #include <minix/com.h>
+#include <minix/log.h>
 #include <minix/syslib.h>
 #include <minix/sysutil.h>
 #include <minix/bitmap.h>
 #include <string.h>
 #include <unistd.h>
 #include <signal.h>
+#include <time.h>
 #include <sys/param.h>
+#include <sys/syslimits.h>
+#include <sys/types.h>
+#include <sys/dirent.h>
+
+#define b_data(bp) ((char *) (bp->data))
 
 #include "proto.h"
 #include "super.h"
 #include "glo.h"
+
index e3e122fedc6de7d0ad26f562d60d5faefbe826b1..33177204666c340db57d027d1c917e8b6ef6d10a 100644 (file)
 
-/* This file contains all the function that handle the dir records
- * (inodes) for the ISO9660 filesystem.*/
+/*
+ * This file contains all the function that handle the dir records
+ * (inodes) for the ISO9660 filesystem.
+ */
 
 #include "inc.h"
-#include "buf.h"
 #include <minix/vfsif.h>
+#include <sys/stat.h>
 
+static struct inode inodes[NR_INODE_RECORDS];
+static struct buf* fetch_inode(struct dir_extent *extent, size_t *offset);
 
-/*===========================================================================*
- *                             fs_putnode                                   *
- *===========================================================================*/
 int fs_putnode()
 {
-/* Find the inode specified by the request message and decrease its counter. */
-  int count;
-  struct dir_record *dir = NULL;
+       /*
+        * Find the inode specified by the request message and decrease its
+        * counter.
+        */
+       int count = fs_m_in.m_vfs_fs_putnode.count;
+       struct inode *i_node = find_inode(fs_m_in.m_vfs_fs_putnode.inode);
+
+       if (i_node == NULL) {
+               printf("put_inode: trying to free unused inode\n");
+               panic("fs_putnode failed");
+       }
+       if (count <= 0) {
+               printf("put_inode: bad value for count: %d\n", count);
+               panic("fs_putnode failed");
+       }
+       if (count > i_node->i_count) {
+               printf("put_inode: count too high: %d > %d\n", count, i_node->i_count);
+               panic("fs_putnode failed");
+       }
 
-  dir = get_dir_record(fs_m_in.m_vfs_fs_putnode.inode);
-  release_dir_record(dir);
-  
-  count = fs_m_in.m_vfs_fs_putnode.count;
+       i_node->i_count -= count - 1;
+       put_inode(i_node);
+       return OK;
+}
 
-  if (count <= 0) return(EINVAL);
-  
-  if (count > dir->d_count) {
-     printf("put_inode: count too high: %d > %d\n", count, dir->d_count);
-     return(EINVAL);
-  }
+struct inode* alloc_inode()
+{
+       /*
+        * Return a free inode from the pool.
+        */
+       static int i;
+       int end = i;
+       struct inode *i_node;
 
-  if (dir->d_count > 1)
-       dir->d_count = dir->d_count - count + 1;/*Keep at least one reference*/
+       i = (i + 1) % NR_INODE_RECORDS;
+       do {
+               i_node = &inodes[i];
 
-  release_dir_record(dir); /* Actual inode release, might be last reference */
+               if (i_node->i_count == 0) {
+                       free_extent(i_node->extent);
 
-  return(OK);
-}
+                       memset(i_node, 0, sizeof(*i_node));
+                       i_node->i_count = 1;
 
+                       return i_node;
+               }
 
-/*===========================================================================*
- *                             release_dir_record                           *
- *===========================================================================*/
-int release_dir_record(dir)
-struct dir_record *dir;
-{
-/* Release a dir record (decrement the counter) */
-  if (dir == NULL)
-       return(EINVAL);
-
-  if (--dir->d_count == 0) {    
-       if (dir->ext_attr != NULL)
-               dir->ext_attr->count = 0;
-       dir->ext_attr = NULL;
-       dir->d_mountpoint = FALSE;
-
-       dir->d_prior = NULL;
-       if (dir->d_next != NULL)
-               release_dir_record(dir);
-       dir->d_next = NULL;
-  }
-  return(OK);
-}
+               i = (i + 1) % NR_INODE_RECORDS;
+       }
+       while(i != end);
 
+       panic("No free inodes in cache");
+}
 
-/*===========================================================================*
- *                             get_free_dir_record                          *
- *===========================================================================*/
-struct dir_record *get_free_dir_record(void)
+struct inode* find_inode(ino_t i)
 {
-/* Get a free dir record */
-  struct dir_record *dir;
-
-  for(dir = dir_records; dir < &dir_records[NR_ATTR_RECS]; dir++) {
-       if (dir->d_count == 0) {        /* The record is free */
-               dir->d_count = 1;               /* Set count to 1 */
-               dir->ext_attr = NULL;
-               return(dir);
+       /* Get inode from cache. */
+       int cpt;
+       struct inode *i_node;
+
+       if (i == 0)
+               return NULL;
+
+       for (cpt = 0; cpt < NR_INODE_RECORDS; cpt++) {
+               i_node = &inodes[cpt];
+
+               if ((i_node->i_stat.st_ino == i) && (i_node->i_count > 0))
+                       return i_node;
        }
-  }
 
-  return(NULL);
+       return NULL;
 }
 
-
-/*===========================================================================*
- *                             get_dir_record                               *
- *===========================================================================*/
-struct dir_record *get_dir_record(id_dir_record)
-ino_t id_dir_record;
+struct inode* get_inode(ino_t i)
 {
-  struct dir_record *dir = NULL;
-  u32_t address;
-  int i;
-
-  /* Search through the cache if the inode is still present */
-  for(i = 0; i < NR_DIR_RECORDS && dir == NULL; ++i) {
-       if (dir_records[i].d_ino_nr == id_dir_record
-                                        && dir_records[i].d_count > 0) {
-               dir = dir_records + i;
-               dir->d_count++;
+       struct inode *i_node;
+       struct dir_extent *extent;
+
+       if (i == 0)
+               return NULL;
+
+       /* Try to get inode from cache. */
+       i_node = find_inode(i);
+       if (i_node != NULL) {
+               dup_inode(i_node);
+               return i_node;
        }
-  }
 
-  if (dir == NULL) {
-       address = (u32_t)id_dir_record;
-       dir = load_dir_record_from_disk(address);
-  }
+       /*
+        * Inode wasn't in cache, try to load it.
+        * FIXME: a fake extent of one logical block is created for
+        * read_inode(). Reading a inode this way could be problematic if
+        * additional extents are stored behind the block boundary.
+        */
+       i_node = alloc_inode();
+       extent = alloc_extent();
+       extent->location = i / v_pri.logical_block_size_l;
+       extent->length = 1;
+
+       if (read_inode(i_node, extent, i % v_pri.logical_block_size_l, NULL) != OK) {
+               free_extent(extent);
+               put_inode(i_node);
+               return NULL;
+       }
 
-  if (dir == NULL) return(NULL);
-  
-  return(dir);
+       free_extent(extent);
+       return i_node;
 }
 
+void put_inode(struct inode *i_node)
+{
+       if (i_node == NULL)
+               return;
 
-/*===========================================================================*
- *                             get_free_ext_attr                                    *
- *===========================================================================*/
-struct ext_attr_rec *get_free_ext_attr(void) {
-/* Get a free extended attribute structure */
-  struct ext_attr_rec *dir;
-  for(dir = ext_attr_recs; dir < &ext_attr_recs[NR_ATTR_RECS]; dir++) {
-       if (dir->count == 0) {  /* The record is free */
-               dir->count = 1;
-               return(dir);
-       }
-  }
-  
-  return(NULL);
+       if (i_node->i_count <= 0)
+               panic("put_inode: i_count already below 1: %d", i_node->i_count);
+
+       i_node->i_count--;
 }
 
+void dup_inode(struct inode *i_node)
+{
+       if (i_node == NULL)
+               panic("dup_inode: trying to duplicate NULL inode");
+
+       i_node->i_count++;
+}
 
-/*===========================================================================*
- *                             create_ext_attr                              *
- *===========================================================================*/
-int create_ext_attr(struct ext_attr_rec *ext,char *buffer)
+static struct buf* fetch_inode(struct dir_extent *extent, size_t *offset)
 {
-/* Fill an extent structure from the data read on the device */
-  if (ext == NULL) return(EINVAL);
-
-  /* In input we have a stream of bytes that are physically read from the
-   * device. This stream of data is copied to the data structure. */
-  memcpy(&ext->own_id,buffer,sizeof(u32_t));
-  memcpy(&ext->group_id,buffer + 4,sizeof(u32_t));
-  memcpy(&ext->permissions,buffer + 8,sizeof(u16_t));
-  memcpy(&ext->file_cre_date,buffer + 10,ISO9660_SIZE_VOL_CRE_DATE);
-  memcpy(&ext->file_mod_date,buffer + 27,ISO9660_SIZE_VOL_MOD_DATE);
-  memcpy(&ext->file_exp_date,buffer + 44,ISO9660_SIZE_VOL_EXP_DATE);
-  memcpy(&ext->file_eff_date,buffer + 61,ISO9660_SIZE_VOL_EFF_DATE);
-  memcpy(&ext->rec_format,buffer + 78,sizeof(u8_t));
-  memcpy(&ext->rec_attrs,buffer + 79,sizeof(u8_t));
-  memcpy(&ext->rec_length,buffer + 80,sizeof(u32_t));
-  memcpy(&ext->system_id,buffer + 84,ISO9660_SIZE_SYS_ID);
-  memcpy(&ext->system_use,buffer + 116,ISO9660_SIZE_SYSTEM_USE);
-  memcpy(&ext->ext_attr_rec_ver,buffer + 180,sizeof(u8_t));
-  memcpy(&ext->len_esc_seq,buffer + 181,sizeof(u8_t));
-
-  return(OK);
+       struct iso9660_dir_record *dir_rec;
+       struct buf *bp;
+
+       /*
+        * Directory entries aren't allowed to cross a logical block boundary in
+        * ISO 9660, so we keep searching until we find something or reach the
+        * end of the extent.
+        */
+       bp = read_extent_block(extent, *offset / v_pri.logical_block_size_l);
+       while (bp != NULL) {
+               dir_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset % 
+                         v_pri.logical_block_size_l);
+               if (dir_rec->length == 0) {
+                       *offset -= *offset % v_pri.logical_block_size_l;
+                       *offset += v_pri.logical_block_size_l;
+               }
+               else {
+                       break;
+               }
+
+               put_block(bp);
+               bp = read_extent_block(extent, *offset / v_pri.logical_block_size_l);
+       }
+
+       return bp;
 }
 
+int read_inode(struct inode *i_node, struct dir_extent *extent, size_t offset,
+       size_t *new_offset)
+{
+       struct iso9660_dir_record *dir_rec;
+       struct buf *bp;
 
-/*===========================================================================*
- *                             create_ext_attr                              *
- *===========================================================================*/
-int create_dir_record(dir,buffer,address)
-struct dir_record *dir;
-char *buffer;
-u32_t address;
+       /* Find inode. */
+       bp = fetch_inode(extent, &offset);
+       if (bp == NULL)
+               return EOF;
+
+       dir_rec = (struct iso9660_dir_record*)(b_data(bp) + offset % 
+                 v_pri.logical_block_size_l);
+
+       /* Parse basic ISO 9660 specs. */
+       if (check_dir_record(dir_rec, offset % v_pri.logical_block_size_l) != OK) {
+               put_block(bp);
+               return EINVAL;
+       }
+
+       memset(&i_node->i_stat, 0, sizeof(struct stat));
+
+       i_node->i_stat.st_ino = get_extent_absolute_block_id(extent,
+           offset / v_pri.logical_block_size_l) * v_pri.logical_block_size_l +
+           offset % v_pri.logical_block_size_l;
+
+       read_inode_iso9660(i_node, dir_rec);
+
+       /* Parse extensions. */
+       read_inode_susp(i_node, dir_rec, bp, offset % v_pri.logical_block_size_l);
+
+       offset += dir_rec->length;
+       read_inode_extents(i_node, dir_rec, extent, &offset);
+
+       put_block(bp);
+       if (new_offset != NULL)
+               *new_offset = offset;
+       return OK;
+}
+
+void read_inode_iso9660(struct inode *i, const struct iso9660_dir_record *dir_rec)
 {
-/* Fills a dir record structure from the data read on the device */
-/* If the flag assign id is active it will return the id associated;
- * otherwise it will return OK. */
-  short size;
-
-  size = buffer[0];
-  if (dir == NULL) return(EINVAL);
-  
-  /* The data structure dir record is filled with the stream of data
-   * that is read. */
-  dir->length = size;
-  dir->ext_attr_rec_length = *((u8_t*)buffer + 1);
-  memcpy(&dir->loc_extent_l,buffer + 2,sizeof(u32_t));
-  memcpy(&dir->loc_extent_m,buffer + 6,sizeof(u32_t));
-  memcpy(&dir->data_length_l,buffer + 10,sizeof(u32_t));
-  memcpy(&dir->data_length_m,buffer + 14,sizeof(u32_t));
-  memcpy(dir->rec_date,buffer + 18, sizeof(dir->rec_date));
-  dir->file_flags = *((u8_t*)buffer + 25);
-  dir->file_unit_size = *((u8_t*)buffer + 26);
-  dir->inter_gap_size = *((u8_t*)buffer + 27);
-  dir->vol_seq_number = *((u8_t*)buffer + 28);
-  dir->length_file_id = *((u8_t*)buffer + 32);
-  memcpy(dir->file_id,buffer + 33,dir->length_file_id);
-  dir->ext_attr = NULL;
-
-  /* set memory attrs */
-  if ((dir->file_flags & D_TYPE) == D_DIRECTORY)
-       dir->d_mode = I_DIRECTORY;
-  else
-       dir->d_mode = I_REGULAR;
-
-  /* Set permission to read only. Equal for all users. */
-  dir->d_mode |= R_BIT | X_BIT;
-  dir->d_mode |= R_BIT << 3 | X_BIT << 3;
-  dir->d_mode |= R_BIT << 6 | X_BIT << 6;
-
-  dir->d_mountpoint = FALSE;
-  dir->d_next = NULL;
-  dir->d_prior = NULL;
-  dir->d_file_size = dir->data_length_l;
-
-  /* Set physical address of the dir record */
-  dir->d_phy_addr = address;
-  dir->d_ino_nr = address;
-
-  return(OK);
+       char *cp;
+
+       /* Parse first extent. */
+       if (dir_rec->data_length_l > 0) {
+               i->extent = alloc_extent();
+               i->extent->location = dir_rec->loc_extent_l +
+                                     dir_rec->ext_attr_rec_length;
+               i->extent->length = dir_rec->data_length_l /
+                                   v_pri.logical_block_size_l;
+               if (dir_rec->data_length_l % v_pri.logical_block_size_l)
+                       i->extent->length++;
+
+               i->i_stat.st_size = dir_rec->data_length_l;
+       }
+
+       /* Parse timestamps (record date). */
+       i->i_stat.st_atime = i->i_stat.st_mtime = i->i_stat.st_ctime =
+           i->i_stat.st_birthtime = date7_to_time_t(dir_rec->rec_date);
+
+       if ((dir_rec->file_flags & D_TYPE) == D_DIRECTORY) {
+               i->i_stat.st_mode = S_IFDIR;
+               i->i_stat.st_ino = i->extent->location * v_pri.logical_block_size_l;
+       }
+       else
+               i->i_stat.st_mode = S_IFREG;
+       i->i_stat.st_mode |= 0555;
+
+       /* Parse file name. */
+       if (dir_rec->file_id[0] == 0)
+               strcpy(i->i_name, ".");
+       else if (dir_rec->file_id[0] == 1)
+               strcpy(i->i_name, "..");
+       else {
+               memcpy(i->i_name, dir_rec->file_id, dir_rec->length_file_id);
+
+               /* Truncate/ignore file version suffix. */
+               cp = strchr(i->i_name, ';');
+               if (cp != NULL)
+                       *cp = '\0';
+               /* Truncate dot if file has no extension. */
+               if (strchr(i->i_name, '.') + 1 == cp)
+                       *(cp-1) = '\0';
+       }
+
+       /* Initialize stat. */
+       i->i_stat.st_dev = fs_dev;
+       i->i_stat.st_blksize = v_pri.logical_block_size_l;
+       i->i_stat.st_blocks = dir_rec->data_length_l / v_pri.logical_block_size_l;
+       i->i_stat.st_nlink = 1;
 }
 
+void read_inode_extents(struct inode *i, const struct iso9660_dir_record *dir_rec,
+       struct dir_extent *extent, size_t *offset)
+{
+       struct buf *bp;
+       struct iso9660_dir_record *extent_rec;
+       struct dir_extent *cur_extent = i->extent;
+       int done = FALSE;
+
+       /*
+        * No need to search extents if file is empty or has final directory
+        * record flag set.
+        */
+       if (cur_extent == NULL || ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0))
+               return;
+
+       while (!done) {
+               bp = fetch_inode(extent, offset);
+               if (bp == NULL)
+                       return;
+
+               bp = read_extent_block(extent, *offset / v_pri.logical_block_size_l);
+               extent_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset % 
+                            v_pri.logical_block_size_l);
+
+               if (check_dir_record(dir_rec, *offset % v_pri.logical_block_size_l) != OK) {
+                       put_block(bp);
+                       return;
+               }
+
+               /* Extent entries should share the same name. */
+               if ((dir_rec->length_file_id == extent_rec->length_file_id) &&
+                   (memcmp(dir_rec->file_id, extent_rec->file_id, dir_rec->length_file_id) == 0)) {
+                       /* Add the extent at the end of the linked list. */
+                       cur_extent->next = alloc_extent();
+                       cur_extent->next->location = dir_rec->loc_extent_l +
+                                                    dir_rec->ext_attr_rec_length;
+                       cur_extent->next->length = dir_rec->data_length_l /
+                                                  v_pri.logical_block_size_l;
+                       if (dir_rec->data_length_l % v_pri.logical_block_size_l)
+                               cur_extent->next->length++;
+
+                       i->i_stat.st_size += dir_rec->data_length_l;
+                       i->i_stat.st_blocks += cur_extent->next->length;
+
+                       cur_extent = cur_extent->next;
+                       *offset += extent_rec->length;
+               }
+               else
+                       done = TRUE;
+
+               /* Check if not last extent bit is not set. */
+               if ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0)
+                       done = TRUE;
+
+               put_block(bp);
+       }
+}
 
-/*===========================================================================*
- *                     load_dir_record_from_disk                            *
- *===========================================================================*/
-struct dir_record *load_dir_record_from_disk(address)
-u32_t address;
+void read_inode_susp(struct inode *i, const struct iso9660_dir_record *dir_rec,
+       struct buf *bp, size_t offset)
 {
-/* This function load a particular dir record from a specific address
- * on the device */
-  int block_nr, offset, block_size, new_pos;
-  struct buf *bp;
-  struct dir_record *dir, *dir_next, *dir_parent, *dir_tmp;
-  char name[NAME_MAX + 1];
-  char old_name[NAME_MAX + 1];
-  u32_t new_address, size;
-
-  block_size = v_pri.logical_block_size_l; /* Block size */
-  block_nr = address / block_size; /* Block number from the address */
-  offset = address % block_size; /* Offset starting from the block */
-
-  bp = get_block(block_nr);    /* Read the block from the device */
-  if (bp == NULL)
-       return(NULL);
-
-  dir = get_free_dir_record(); /* Get a free record */
-  if (dir == NULL)
-       return(NULL);
-
-  /* Fill the dir record with the data read from the device */
-  create_dir_record(dir,b_data(bp) + offset, address);
-
-  /* In case the file is composed of more file sections, load also the
-   * next section into the structure */
-  new_pos = offset + dir->length;
-  dir_parent = dir;
-  new_address = address + dir->length;
-  while (new_pos < block_size) {
-       dir_next = get_free_dir_record();
-       create_dir_record(dir_next, b_data(bp) + new_pos, new_address);
-
-       if (dir_next->length > 0) {
-               strncpy(name,dir_next->file_id,dir_next->length_file_id);
-               name[dir_next->length_file_id] = '\0';
-               strncpy(old_name, dir_parent->file_id,
-                       dir_parent->length_file_id);
-               old_name[dir_parent->length_file_id] = '\0';
-      
-               if (strcmp(name, old_name) == 0) {
-                       dir_parent->d_next = dir_next;
-                       dir_next->d_prior = dir_parent;
-
-                       /* Link the dir records */
-                       dir_tmp = dir_next;
-                       size = dir_tmp->data_length_l;
-
-                       /* Update the file size */
-                       while (dir_tmp->d_prior != NULL) {
-                               dir_tmp = dir_tmp->d_prior;
-                               size += dir_tmp->data_length_l;
-                               dir_tmp->d_file_size = size;
-                       }
-
-                       new_pos += dir_parent->length;
-                       new_address += dir_next->length;
-                       dir_parent = dir_next;
-               } else {                        /* This is another inode. */
-                       release_dir_record(dir_next);
-                       new_pos = block_size;
-               }      
-       } else {                                /* record not valid */
-               release_dir_record(dir_next);
-               new_pos = block_size;           /* Exit from the while */
+       int susp_offset, susp_size;
+       struct rrii_dir_record rrii_data;
+
+       susp_offset = 33 + dir_rec->length_file_id;
+       /* Get rid of padding byte. */
+       if(dir_rec->length_file_id % 2 == 0) {
+               susp_offset++;
+       }
+
+       if(dir_rec->length - susp_offset >= 4) {
+               susp_size = dir_rec->length - susp_offset;
+
+               /* Initialize rrii_dir_record structure with known, sane data. */
+               memcpy(rrii_data.mtime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
+               memcpy(rrii_data.atime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
+               memcpy(rrii_data.ctime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
+               memcpy(rrii_data.birthtime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
+
+               rrii_data.d_mode = i->i_stat.st_mode;
+               rrii_data.uid    = 0;
+               rrii_data.gid    = 0;
+               rrii_data.rdev   = NO_DEV;
+               rrii_data.file_id_rrip[0] = '\0';
+               rrii_data.slink_rrip[0]   = '\0';
+
+               parse_susp_buffer(&rrii_data, b_data(bp)+offset+susp_offset, susp_size);
+
+               /* Copy back data from rrii_dir_record structure. */
+               i->i_stat.st_atime = date7_to_time_t(rrii_data.atime);
+               i->i_stat.st_ctime = date7_to_time_t(rrii_data.ctime);
+               i->i_stat.st_mtime = date7_to_time_t(rrii_data.mtime);
+               i->i_stat.st_birthtime = date7_to_time_t(rrii_data.birthtime);
+
+               i->i_stat.st_mode = rrii_data.d_mode;
+               i->i_stat.st_uid  = rrii_data.uid;
+               i->i_stat.st_gid  = rrii_data.gid;
+               i->i_stat.st_rdev = rrii_data.rdev;
+
+               if (rrii_data.file_id_rrip[0] != '\0')
+                       strlcpy(i->i_name, rrii_data.file_id_rrip, ISO9660_RRIP_MAX_FILE_ID_LEN);
+               if (rrii_data.slink_rrip[0] != '\0')
+                       strlcpy(i->s_link, rrii_data.slink_rrip, ISO9660_RRIP_MAX_FILE_ID_LEN);
        }
-  }
+}
 
-  put_block(bp);               /* Release the block read. */
-  return(dir);
+int check_dir_record(const struct iso9660_dir_record *d, size_t offset)
+{
+       /* Run some consistency check on a directory entry. */
+       if ((d->length < 33) || (d->length_file_id < 1))
+               return EINVAL;
+       if (d->length_file_id + 32 > d->length)
+               return EINVAL;
+       if (offset + d->length > v_pri.logical_block_size_l)
+               return EINVAL;
+
+       return OK;
 }
 
index d0e7bddcfe69e36013d3a9eb91769943b45cd4fd..19ce1953e2b24b3ce52aaf118550d1200ca7bdb3 100644 (file)
@@ -1,67 +1,71 @@
 #include "const.h"
+#include <sys/stat.h>
 
-struct dir_record {
-  u8_t length;                 /* The length of the record */
-  u8_t ext_attr_rec_length;
-  u32_t loc_extent_l;          /* The same data (in this case loc_extent)is */
-  u32_t loc_extent_m;          /* saved in two ways. The first puts the le- */
-  u32_t data_length_l;         /* ast significant byte first, the second */
-  u32_t data_length_m;         /* does the opposite */
-  u8_t rec_date[7];            /* => recording date */
-  u8_t file_flags;             /* => flags of the file */
-  u8_t file_unit_size;         /* set of blocks in interleave mode */
-  u8_t inter_gap_size;         /* gap between file units in interleave mode */
-  u32_t vol_seq_number;                /* volume sequence number: not used */
-  u8_t length_file_id;         /* Length name file */
-  char file_id[ISO9660_MAX_FILE_ID_LEN]; /* file name */
-  struct ext_attr_rec *ext_attr;
+struct iso9660_dir_record {
+       /*
+        * ISO standard directory record.
+        */
+       u8_t length;                    /* The length of the record */
+       u8_t ext_attr_rec_length;
+       u32_t loc_extent_l;             /* The same data (in this case loc_extent)is */
+       u32_t loc_extent_m;             /* saved in two ways. The first puts the le- */
+       u32_t data_length_l;            /* ast significant byte first, the second */
+       u32_t data_length_m;            /* does the opposite */
+       u8_t rec_date[7];               /* => recording date */
+       u8_t file_flags;                /* => flags of the file */
+       u8_t file_unit_size;            /* set of blocks in interleave mode */
+       u8_t inter_gap_size;            /* gap between file units in interleave mode */
+       u32_t vol_seq_number;           /* volume sequence number: not used */
+       u8_t length_file_id;            /* Length name file */
+       char file_id[ISO9660_MAX_FILE_ID_LEN]; /* file name */
+} __attribute__((packed));
 
-  /* Memory attrs */
-  u8_t d_count;                        /* Count if the dir_record is in use or not */
-  mode_t d_mode;                       /* file type, protection, etc. */
-/*   struct hash_idi_entry *id; */     /* id associated */
-  u32_t d_phy_addr;            /* physical address of this dir record */
-  ino_t d_ino_nr;              /* inode number (identical to the address) */
-  char d_mountpoint;           /* true if mounted on */
-  struct dir_record *d_next;   /* In case the file consists in more file sections
-                                  this points to the next one */
-  struct dir_record *d_prior;  /* The same as before, this points to the dir parent */
-  u32_t d_file_size;           /* Total size of the file */
+struct rrii_dir_record {
+       /*
+        * Rock Ridge directory record extensions.
+        */
+       u8_t mtime[7];          /* stat.st_mtime */
+       u8_t atime[7];          /* stat.st_atime */
+       u8_t ctime[7];          /* stat.st_ctime */
+       u8_t birthtime[7];      /* stat.st_birthtime */
 
-} dir_records[NR_DIR_RECORDS];
+       mode_t d_mode;          /* file mode */
+       uid_t uid;              /* user ID of the file's owner */
+       gid_t gid;              /* group ID of the file's group */
+       dev_t rdev;             /* device ID */
 
-struct ext_attr_rec {
-  u32_t own_id;
-  u32_t group_id;
-  u16_t permissions;
-  char file_cre_date[ISO9660_SIZE_VOL_CRE_DATE];
-  char file_mod_date[ISO9660_SIZE_VOL_MOD_DATE];
-  char file_exp_date[ISO9660_SIZE_VOL_EXP_DATE];
-  char file_eff_date[ISO9660_SIZE_VOL_EFF_DATE];
-  u8_t rec_format;
-  u8_t rec_attrs;
-  u32_t rec_length;
-  char system_id[ISO9660_SIZE_SYS_ID];
-  char system_use[ISO9660_SIZE_SYSTEM_USE];
-  u8_t ext_attr_rec_ver;
-  u8_t len_esc_seq;
+       char file_id_rrip[ISO9660_RRIP_MAX_FILE_ID_LEN];        /* file name */
+       char slink_rrip[ISO9660_RRIP_MAX_FILE_ID_LEN];          /* symbolic link */
+} ;
 
-  int count;
-} ext_attr_recs[NR_ATTR_RECS];
+struct dir_extent {
+       /*
+        * Extent (contiguous array of logical sectors).
+        */
+       char in_use;
+       u32_t location;
+       u32_t length;
+       struct dir_extent *next;
+} ;
 
-#define D_DIRECTORY 0x2
-#define D_TYPE 0x8E
-
-/* Vector with all the ids of the dir records */
-/* PUBLIC struct hash_idi_entry { */
-/*   u32_t h_phy_addr; */
-/*   struct dir_record *h_dir_record; */
-/* } hash_idi[NR_ID_INODES]; */
+struct inode {
+       int i_count;                    /* usage counter of this inode */
+       int i_mountpoint;               /* flag for inode being used as a mount point */
+       int ea_length;                  /* total size of extended attributes in bytes */
+       struct stat i_stat;             /* inode properties */
+       struct dir_extent *extent;      /* first extent of file */
+       char i_name[NAME_MAX];          /* inode name */
+       char s_link[NAME_MAX];          /* symbolic link target */
+} ;
 
-/* PUBLIC int size_hash_idi; */
+struct opt {
+       /*
+        * Global mount options.
+        */
+       int norock;                     /* Bool: dont use Rock Ridge */
+} ;
 
-/* #define ID_DIR_RECORD(id) id - hash_idi + 1 */
-#define ID_DIR_RECORD(dir) dir->d_ino_nr
+#define D_DIRECTORY 0x2
+#define D_NOT_LAST_EXTENT 0x80
+#define D_TYPE 0x8E
 
-/* #define ASSIGN_ID 1 */
-/* #define NOT_ASSIGN_ID 0 */
diff --git a/minix/fs/iso9660fs/link.c b/minix/fs/iso9660fs/link.c
new file mode 100644 (file)
index 0000000..7e7d2a7
--- /dev/null
@@ -0,0 +1,36 @@
+#include "inc.h"
+#include <minix/com.h>
+#include <minix/vfsif.h>
+#include <fcntl.h>
+#ifdef __NBSD_LIBC
+#include <stddef.h>
+#endif
+#include "proto.h"
+
+int fs_rdlink()
+{
+       struct inode *i_node; /* target inode */
+       int r;                /* return value */
+       size_t copylen;
+
+       /* Try to get inode according to its index */
+       i_node = find_inode(fs_m_in.m_vfs_fs_rdlink.inode);
+       if (i_node == NULL) 
+               return EINVAL; /* no inode found */
+
+       if(!S_ISLNK(i_node->i_stat.st_mode))
+               r = EACCES;
+       else {
+               /* Passed all checks */
+               copylen = MIN( (size_t) fs_m_in.m_vfs_fs_rdlink.mem_size, NAME_MAX);
+
+               r = sys_safecopyto(VFS_PROC_NR,
+                                  (cp_grant_id_t) fs_m_in.m_vfs_fs_rdlink.grant,
+                                  (vir_bytes) 0,
+                                  (vir_bytes) i_node->s_link,
+                                  copylen);
+       }
+
+       return r;
+}
+
index 0836c6a69163da2cd242b3e2b11fc723817e5cbe..d0b53ebe48c4688dc8a40235760a9f92f916f361 100644 (file)
@@ -1,5 +1,7 @@
-/* This file contains the main directory for the server. It waits for a 
- * request and then send a response. */
+/*
+ * This file contains the main function for the server. It waits for a request
+ * and then send a response.
+ */
 
 #include "inc.h"
 #include <minix/vfsif.h>
@@ -15,64 +17,67 @@ static void sef_local_startup(void);
 static int sef_cb_init_fresh(int type, sef_init_info_t *info);
 static void sef_cb_signal_handler(int signo);
 
-/*===========================================================================*
- *                             main                                         *
- *===========================================================================*/
-int main(void) {
-  endpoint_t who_e;
-  int ind, error, transid;
+static struct optset optset_table[] = {
+       { "norock",             OPT_BOOL,   &opt.norock,        TRUE    },
+       { NULL,         0,          NULL,                       0       }
+};
 
-  /* SEF local startup. */
-  sef_local_startup();
+int main(int argc, char *argv[]) {
+       endpoint_t who_e;
+       int ind, error, transid;
 
-  for (;;) {
+       /* SEF local startup. */
+       env_setargs(argc, argv);
+       sef_local_startup();
 
-       /* Wait for request message. */
-       get_work(&fs_m_in);
+       while (TRUE) {
+               /* Wait for request message. */
+               get_work(&fs_m_in);
 
-       transid = TRNS_GET_ID(fs_m_in.m_type);
-       fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type);
-       if (fs_m_in.m_type == 0) {
-               assert(!IS_VFS_FS_TRANSID(transid));
-               fs_m_in.m_type = transid;       /* Backwards compat. */
-               transid = 0;
-       } else
-               assert(IS_VFS_FS_TRANSID(transid));
+               transid = TRNS_GET_ID(fs_m_in.m_type);
+               fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type);
+               if (fs_m_in.m_type == 0) {
+                       assert(!IS_VFS_FS_TRANSID(transid));
+                       fs_m_in.m_type = transid;       /* Backwards compat. */
+                       transid = 0;
+               }
+               else
+                       assert(IS_VFS_FS_TRANSID(transid));
 
-       error = OK;
+               error = OK;
 
-       caller_uid = -1;        /* To trap errors */
-       caller_gid = -1;
+               caller_uid = -1;        /* To trap errors */
+               caller_gid = -1;
 
-       who_e = fs_m_in.m_source;       /* source of the request */
+               who_e = fs_m_in.m_source;       /* source of the request */
 
-       if (who_e != VFS_PROC_NR) { /* If the message is not for us just 
-                                   * continue */
-               continue;
-       }
+               if (who_e != VFS_PROC_NR) { /* If the message is not for us just 
+                                           * continue */
+                       continue;
+               }
 
-       req_nr = fs_m_in.m_type;
-
-       if (req_nr < FS_BASE) {
-               fs_m_in.m_type += FS_BASE;
                req_nr = fs_m_in.m_type;
-       }
 
-       ind = req_nr-FS_BASE;
-
-       if (ind < 0 || ind >= NREQS) {
-               error = EINVAL; 
-       } else
-               error = (*fs_call_vec[ind])(); /* Process the request calling
-                                               * the appropriate function. */
-
-       fs_m_out.m_type = error; 
-       if (IS_VFS_FS_TRANSID(transid)) {
-               /* If a transaction ID was set, reset it */
-               fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type, transid);
+               if (req_nr < FS_BASE) {
+                       fs_m_in.m_type += FS_BASE;
+                       req_nr = fs_m_in.m_type;
+               }
+
+               ind = req_nr - FS_BASE;
+
+               if (ind < 0 || ind >= NREQS)
+                       error = EINVAL; 
+               else
+                       error = (*fs_call_vec[ind])(); /* Process the request calling
+                                                       * the appropriate function. */
+
+               fs_m_out.m_type = error; 
+               if (IS_VFS_FS_TRANSID(transid)) {
+                       /* If a transaction ID was set, reset it */
+                       fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type, transid);
+               }
+               reply(who_e, &fs_m_out);        /* returns the response to VFS */
        }
-       reply(who_e, &fs_m_out);        /* returns the response to VFS */
-  }
 }
 
 /*===========================================================================*
@@ -80,68 +85,64 @@ int main(void) {
  *===========================================================================*/
 static void sef_local_startup()
 {
-  /* Register init callbacks. */
-  sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_fail);
+       /* Initialize the Minix file server. */
+       int i;
+
+       /* Defaults */
+       opt.norock = FALSE;
+
+       /* If we have been given an options string, parse options here. */
+       for (i = 1; i < env_argc - 1; i++)
+               if (!strcmp(env_argv[i], "-o"))
+                       optset_parse(optset_table, env_argv[++i]);
+
+       /* Register init callbacks. */
+       sef_setcb_init_fresh(sef_cb_init_fresh);
+       sef_setcb_init_restart(sef_cb_init_fail);
 
-  /* No live update support for now. */
+       /* No live update support for now. */
 
-  /* Register signal callbacks. */
-  sef_setcb_signal_handler(sef_cb_signal_handler);
+       /* Register signal callbacks. */
+       sef_setcb_signal_handler(sef_cb_signal_handler);
 
-  /* Let SEF perform startup. */
-  sef_startup();
+       /* Let SEF perform startup. */
+       sef_startup();
 
-  lmfs_buf_pool(10);
+       lmfs_buf_pool(10);
 }
 
-/*===========================================================================*
- *                         sef_cb_init_fresh                                *
- *===========================================================================*/
 static int sef_cb_init_fresh(int type, sef_init_info_t *info)
 {
-/* Initialize the iso9660fs server. */
-
-/*    hash_init(); */                  /* Init the table with the ids */
-   setenv("TZ","",1);          /* Used to calculate the time */
+       /* Initialize the iso9660fs server. */
+       setenv("TZ","",1);              /* Used to calculate the time */
 
-   return(OK);
+       return OK;
 }
 
-/*===========================================================================*
- *                             sef_cb_signal_handler                        *
- *===========================================================================*/
 static void sef_cb_signal_handler(int signo)
 {
-  /* Only check for termination signal, ignore anything else. */
-  if (signo != SIGTERM) return;
+       /* Only check for termination signal, ignore anything else. */
+       if (signo != SIGTERM) return;
 
-  /* No need to do a sync, as this is a read-only file system. */
+       /* No need to do a sync, as this is a read-only file system. */
 
-  /* If the file system has already been unmounted, exit immediately.
-   * We might not get another message.
-   */
-  if (unmountdone) exit(0);
+       /*
+        * If the file system has already been unmounted, exit immediately.
+        * We might not get another message.
+        */
+       if (unmountdone) exit(0);
 }
 
-/*===========================================================================*
- *                             get_work                                     *
- *===========================================================================*/
-static void get_work(m_in)
-message *m_in;                         /* pointer to message */
+static void get_work(message *m_in)
 {
-  int s;                                       /* receive status */
-  if (OK != (s = sef_receive(ANY, m_in)))      /* wait for message */
-    panic("sef_receive failed: %d", s);
+       int s;                                          /* receive status */
+       if (OK != (s = sef_receive(ANY, m_in)))         /* wait for message */
+               panic("sef_receive failed: %d", s);
 }
 
-/*===========================================================================*
- *                             reply                                        *
- *===========================================================================*/
-void reply(who, m_out)
-int who;       
-message *m_out;                        /* report result */
+void reply(int who, message *m_out)
 {
-  if (OK != ipc_send(who, m_out))    /* send the message */
-    printf("ISOFS(%d) was unable to send reply\n", sef_self());
+       if (OK != ipc_send(who, m_out))                 /* send the message */
+               printf("ISOFS(%d) was unable to send reply\n", sef_self());
 }
+
index 6749affe5d4ddcd461b50971c0ecd07e7f46ae07..d0ded206dd44adc16c6880a4dc142dbf058633f0 100644 (file)
@@ -3,45 +3,37 @@
 #include <minix/vfsif.h>
 #include <minix/bdev.h>
 
-
-/*===========================================================================*
- *                             fs_sync                                      *
- *===========================================================================*/
 int fs_sync()
 {
-  /* Always mounted read only, so nothing to sync */
-  return(OK);          /* sync() can't fail */
+       /* Always mounted read only, so nothing to sync */
+       return OK;              /* sync() can't fail */
 }
 
-
-/*===========================================================================*
- *                             fs_new_driver                                *
- *===========================================================================*/
 int fs_new_driver(void)
 {
-/* Set a new driver endpoint for this device. */
-  dev_t dev;
-  cp_grant_id_t label_gid;
-  size_t label_len;
-  char label[sizeof(fs_dev_label)];
-  int r;
-
-  dev = fs_m_in.m_vfs_fs_new_driver.device;
-  label_gid = fs_m_in.m_vfs_fs_new_driver.grant;
-  label_len = fs_m_in.m_vfs_fs_new_driver.path_len;
-
-  if (label_len > sizeof(label))
-       return(EINVAL);
-
-  r = sys_safecopyfrom(fs_m_in.m_source, label_gid, (vir_bytes) 0,
-       (vir_bytes) label, label_len);
-
-  if (r != OK) {
-       printf("ISOFS: fs_new_driver safecopyfrom failed (%d)\n", r);
-       return(EINVAL);
-  }
-
-  bdev_driver(dev, label);
-
-  return(OK);
+       /* Set a new driver endpoint for this device. */
+       dev_t dev;
+       cp_grant_id_t label_gid;
+       size_t label_len;
+       char label[sizeof(fs_dev_label)];
+       int r;
+
+       dev       = fs_m_in.m_vfs_fs_new_driver.device;
+       label_gid = fs_m_in.m_vfs_fs_new_driver.grant;
+       label_len = fs_m_in.m_vfs_fs_new_driver.path_len;
+
+       if (label_len > sizeof(label))
+               return EINVAL;
+
+       r = sys_safecopyfrom(fs_m_in.m_source, label_gid, (vir_bytes) 0,
+                            (vir_bytes) label, label_len);
+
+       if (r != OK) {
+               printf("ISOFS: fs_new_driver safecopyfrom failed (%d)\n", r);
+               return EINVAL;
+       }
+
+       bdev_driver(dev, label);
+       return OK;
 }
+
index b852ec9b9c70cb79edf9412a7aa65e5b24cf3ce3..423644d32a38689aafff6752ebe8791dc9a82204 100644 (file)
@@ -4,98 +4,86 @@
 #include "const.h"
 #include "glo.h"
 
-
-/*===========================================================================*
- *                             fs_readsuper                                 *
- *===========================================================================*/
 int fs_readsuper() {
+       cp_grant_id_t label_gid;
+       size_t label_len;
+       int r = OK;
 
-  cp_grant_id_t label_gid;
-  size_t label_len;
-  int r = OK;
-
-  fs_dev    = fs_m_in.m_vfs_fs_readsuper.device;
-  label_gid = fs_m_in.m_vfs_fs_readsuper.grant;
-  label_len = fs_m_in.m_vfs_fs_readsuper.path_len;
+       fs_dev    = fs_m_in.m_vfs_fs_readsuper.device;
+       label_gid = fs_m_in.m_vfs_fs_readsuper.grant;
+       label_len = fs_m_in.m_vfs_fs_readsuper.path_len;
 
-  if (label_len > sizeof(fs_dev_label)) 
-       return(EINVAL);
+       if (label_len > sizeof(fs_dev_label)) 
+               return EINVAL;
 
-  r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label,
+       r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label,
                       label_len);
-  if (r != OK) {
-       printf("ISOFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r);
-       return(EINVAL);
-  }
-
-  /* Map the driver label for this major */
-  bdev_driver(fs_dev, fs_dev_label);
-
-  /* Open the device the file system lives on in read only mode */
-  if (bdev_open(fs_dev, BDEV_R_BIT) != OK) {
-        return(EINVAL);
-  }
-
-  /* Read the superblock */
-  r = read_vds(&v_pri, fs_dev);
-  if (r != OK) {
-       bdev_close(fs_dev);
-       return(r);
-  }
+       if (r != OK) {
+               printf("ISOFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r);
+               return EINVAL;
+       }
+
+       /* Map the driver label for this major */
+       bdev_driver(fs_dev, fs_dev_label);
+
+       /* Open the device the file system lives on in read only mode */
+       if (bdev_open(fs_dev, BDEV_R_BIT) != OK) {
+               return EINVAL;
+       }
+
+       /* Read the superblock */
+       r = read_vds(&v_pri, fs_dev);
+       if (r != OK) {
+               bdev_close(fs_dev);
+               return r;
+       }
+
+       /* Return some root inode properties */
+       fs_m_out.m_fs_vfs_readsuper.inode = v_pri.inode_root->i_stat.st_ino;
+       fs_m_out.m_fs_vfs_readsuper.mode =  v_pri.inode_root->i_stat.st_mode;
+       fs_m_out.m_fs_vfs_readsuper.file_size = v_pri.inode_root->i_stat.st_size;
+       fs_m_out.m_fs_vfs_readsuper.uid = SYS_UID; /* Always root */
+       fs_m_out.m_fs_vfs_readsuper.gid = SYS_GID; /* operator */
+       fs_m_out.m_fs_vfs_readsuper.flags = RES_NOFLAGS;
+
+       return r;
+}
 
-  lmfs_set_blocksize(v_pri.logical_block_size_l, major(fs_dev));
+int fs_mountpoint()
+{
+       /*
+        * This function looks up the mount point, it checks the condition
+        * whether the partition can be mounted on the inode or not.
+        */
 
-  /* Return some root inode properties */
-  fs_m_out.m_fs_vfs_readsuper.inode = ID_DIR_RECORD(v_pri.dir_rec_root);
-  fs_m_out.m_fs_vfs_readsuper.mode = v_pri.dir_rec_root->d_mode;
-  fs_m_out.m_fs_vfs_readsuper.file_size = v_pri.dir_rec_root->d_file_size;
-  fs_m_out.m_fs_vfs_readsuper.uid = SYS_UID; /* Always root */
-  fs_m_out.m_fs_vfs_readsuper.gid = SYS_GID; /* operator */
-  fs_m_out.m_fs_vfs_readsuper.flags = RES_NOFLAGS;
+       struct inode *rip;
+       int r = OK;
 
-  return(r);
-}
+       /* Temporarily open the file. */
+       if ((rip = find_inode(fs_m_in.m_vfs_fs_mountpoint.inode)) == NULL)
+               return EINVAL;
 
+       if (rip->i_mountpoint)
+               r = EBUSY;
 
-/*===========================================================================*
- *                             fs_mountpoint                                *
- *===========================================================================*/
-int fs_mountpoint()
-{
-/* This function looks up the mount point, it checks the condition whether
- * the partition can be mounted on the inode or not. 
- */
-
-  register struct dir_record *rip;
-  int r = OK;
-  
-  /* Temporarily open the file. */
-  if ((rip = get_dir_record(fs_m_in.m_vfs_fs_mountpoint.inode)) == NULL)
-       return(EINVAL);
-
-  if (rip->d_mountpoint)
-       r = EBUSY;
-
-  /* If the inode is not a dir returns error */
-  if ((rip->d_mode & I_TYPE) != I_DIRECTORY)
-       r = ENOTDIR;
-       
-  release_dir_record(rip);
-
-  if (r == OK)
-       rip->d_mountpoint = TRUE;
-
-  return(r);
+       /* If the inode is not a dir returns error */
+       if ((rip->i_stat.st_mode & I_TYPE) != I_DIRECTORY)
+               r = ENOTDIR;
+
+       put_inode(rip);
+
+       if (r == OK)
+               rip->i_mountpoint = TRUE;
+
+       return r;
 }
 
+int fs_unmount(void)
+{
+       release_vol_pri_desc(&v_pri);   /* Release the super block */
+       bdev_close(fs_dev);
+       unmountdone = TRUE;
 
-/*===========================================================================*
- *                             fs_unmount                                   *
- *===========================================================================*/
-int fs_unmount(void) {
-  release_v_pri(&v_pri);       /* Release the super block */
-  bdev_close(fs_dev);
-  unmountdone = TRUE;
-  return(OK);
+       return OK;
 }
 
index 73c55a2fb16d156bb6a174dcca10b8158de079db..30ab4af7cf9262d93042342f4fb9fb87500b71d5 100644 (file)
@@ -2,75 +2,78 @@
 #include <string.h>
 #include <minix/com.h>
 #include <minix/vfsif.h>
-
-#include "buf.h"
+#include <sys/stat.h>
 
 static char *get_name(char *name, char string[NAME_MAX+1]);
+static int ltraverse(struct inode *rip, char *suffix);
 static int parse_path(ino_t dir_ino, ino_t root_ino, int flags, struct
-       dir_record **res_inop, size_t *offsetp);
+       inode **res_inop, size_t *offsetp, int *symlinkp);
 
 
 /*===========================================================================*
  *                             fs_lookup                                    *
  *===========================================================================*/
 int fs_lookup() {
-  cp_grant_id_t grant;
-  int r, len, flags;
-  size_t offset;
-  ino_t dir_ino, root_ino;
-  struct dir_record *dir;
-
-  grant                = fs_m_in.m_vfs_fs_lookup.grant_path;
-  len          = fs_m_in.m_vfs_fs_lookup.path_len;     /* including terminating nul */
-  dir_ino      = fs_m_in.m_vfs_fs_lookup.dir_ino;
-  root_ino     = fs_m_in.m_vfs_fs_lookup.root_ino;
-  flags                = fs_m_in.m_vfs_fs_lookup.flags;
-  caller_uid   = fs_m_in.m_vfs_fs_lookup.uid;
-  caller_gid   = fs_m_in.m_vfs_fs_lookup.gid;
-
-  /* Check length. */
-  if(len > sizeof(user_path)) return(E2BIG);   /* too big for buffer */
-  if(len < 1) return(EINVAL);                  /* too small */
-
-  /* Copy the pathname and set up caller's user and group id */
-  r = sys_safecopyfrom(VFS_PROC_NR, grant, 0, (vir_bytes) user_path, 
-                      (phys_bytes) len);
-  if (r != OK) {
-       printf("ISOFS %s:%d sys_safecopyfrom failed: %d\n",
-               __FILE__, __LINE__, r);
-       return(r);
-  }
-
-  /* Verify this is a null-terminated path. */
-  if(user_path[len-1] != '\0') return(EINVAL);
-
-  /* Lookup inode */
-  dir = NULL;
-  offset = 0;
-  r = parse_path(dir_ino, root_ino, flags, &dir, &offset);
-
-  if (r == ELEAVEMOUNT) {
-       /* Report offset and the error */
-       fs_m_out.m_fs_vfs_lookup.offset = offset;
-       fs_m_out.m_fs_vfs_lookup.symloop = 0;
-       return(r);
-  }
-
-  if (r != OK && r != EENTERMOUNT) return(r);
-
-  fs_m_out.m_fs_vfs_lookup.inode       = ID_DIR_RECORD(dir);
-  fs_m_out.m_fs_vfs_lookup.mode                = dir->d_mode;
-  fs_m_out.m_fs_vfs_lookup.file_size   = dir->d_file_size;
-  fs_m_out.m_fs_vfs_lookup.symloop     = 0;
-  fs_m_out.m_fs_vfs_lookup.uid         = SYS_UID;      /* root */
-  fs_m_out.m_fs_vfs_lookup.gid         = SYS_GID;      /* operator */
-
-  if (r == EENTERMOUNT) { 
-       fs_m_out.m_fs_vfs_lookup.offset = offset;
-       release_dir_record(dir);
-  }
-
-  return(r);
+       cp_grant_id_t grant;
+       int r, len, flags, symlinks = 0;
+       size_t offset = 0;
+       ino_t dir_ino, root_ino;
+       struct inode *dir = 0;
+
+       grant           = fs_m_in.m_vfs_fs_lookup.grant_path;
+       len             = fs_m_in.m_vfs_fs_lookup.path_len;     /* including terminating nul */
+       dir_ino         = fs_m_in.m_vfs_fs_lookup.dir_ino;
+       root_ino        = fs_m_in.m_vfs_fs_lookup.root_ino;
+       flags           = fs_m_in.m_vfs_fs_lookup.flags;
+       caller_uid      = fs_m_in.m_vfs_fs_lookup.uid;
+       caller_gid      = fs_m_in.m_vfs_fs_lookup.gid;
+
+       /* Check length. */
+       if(len > sizeof(user_path))
+               return E2BIG;   /* too big for buffer */
+       if(len < 1)
+               return EINVAL;                  /* too small */
+
+       /* Copy the pathname and set up caller's user and group id */
+       r = sys_safecopyfrom(VFS_PROC_NR, grant, 0, (vir_bytes) user_path, 
+                            (phys_bytes) len);
+       if (r != OK) {
+               printf("ISOFS %s:%d sys_safecopyfrom failed: %d\n",
+                      __FILE__, __LINE__, r);
+               return r;
+       }
+
+       /* Verify this is a null-terminated path. */
+       if(user_path[len-1] != '\0')
+               return EINVAL;
+
+       /* Lookup inode */
+       r = parse_path(dir_ino, root_ino, flags, &dir, &offset, &symlinks);
+
+       if(r == ELEAVEMOUNT || r == ESYMLINK) {
+               /* Report offset and the error */
+               fs_m_out.m_fs_vfs_lookup.offset = offset;
+               fs_m_out.m_fs_vfs_lookup.symloop = symlinks;
+               return r;
+       }
+
+       if (r != OK && r != EENTERMOUNT)
+               return r;
+
+       fs_m_out.m_fs_vfs_lookup.inode          = dir->i_stat.st_ino;
+       fs_m_out.m_fs_vfs_lookup.mode           = dir->i_stat.st_mode;
+       fs_m_out.m_fs_vfs_lookup.file_size      = dir->i_stat.st_size;
+       fs_m_out.m_fs_vfs_lookup.device         = dir->i_stat.st_rdev;
+       fs_m_out.m_fs_vfs_lookup.symloop        = 0;
+       fs_m_out.m_fs_vfs_lookup.uid            = dir->i_stat.st_uid;
+       fs_m_out.m_fs_vfs_lookup.gid            = dir->i_stat.st_gid;
+
+       if (r == EENTERMOUNT) {
+               fs_m_out.m_fs_vfs_lookup.offset = offset;
+               put_inode(dir);
+       }
+
+       return r;
 }
 
 /* The search dir actually performs the operation of searching for the
@@ -80,101 +83,78 @@ int fs_lookup() {
  *                             search_dir                                   *
  *===========================================================================*/
 int search_dir(
-       register struct dir_record *ldir_ptr,   /* dir record parent */
+       struct inode *ldir_ptr,         /* dir record parent */
        char string[NAME_MAX],                  /* component to search for */
        ino_t *numb                             /* pointer to new dir record */
 ) {
-  struct dir_record *dir_tmp;
-  register struct buf *bp;
-  int pos;
-  char* comma_pos = NULL;
-  char tmp_string[NAME_MAX];
-
-  /* This function search a particular element (in string) in a inode and
-   * return its number */
-
-  /* Initialize the tmp array */
-  memset(tmp_string,'\0',NAME_MAX);
-
-  if ((ldir_ptr->d_mode & I_TYPE) != I_DIRECTORY) {
-    return(ENOTDIR);
-  }
-  
-  if (strcmp(string,".") == 0) {
-    *numb = ID_DIR_RECORD(ldir_ptr);
-    return OK;
-  }
-
-  if (strcmp(string,"..") == 0 && ldir_ptr->loc_extent_l == v_pri.dir_rec_root->loc_extent_l) {
-    *numb = ROOT_INO_NR;
-/*     *numb = ID_DIR_RECORD(ldir_ptr); */
-    return OK;
-  }
-
-  /* Read the dir's content */
-  pos = ldir_ptr->ext_attr_rec_length;
-  bp = get_block(ldir_ptr->loc_extent_l);
-
-  if (bp == NULL)
-    return EINVAL;
-
-  while (pos < v_pri.logical_block_size_l) {
-    if ((dir_tmp = get_free_dir_record()) == NULL) {
-      put_block(bp);
-      return EINVAL;
-    }
-
-    if (create_dir_record(dir_tmp,b_data(bp) + pos,
-         ldir_ptr->loc_extent_l*v_pri.logical_block_size_l + pos) == EINVAL)
-      return EINVAL;
-
-    if (dir_tmp->length == 0) {
-      release_dir_record(dir_tmp);
-      put_block(bp);
-      return EINVAL;
-    }
-    
-    memcpy(tmp_string,dir_tmp->file_id,dir_tmp->length_file_id);
-    comma_pos = strchr(tmp_string,';');
-    if (comma_pos != NULL)
-      *comma_pos = 0;
-    else
-      tmp_string[dir_tmp->length_file_id] = 0;
-    if (tmp_string[strlen(tmp_string) - 1] == '.')
-      tmp_string[strlen(tmp_string) - 1] = '\0';
-    
-    if (strcmp(tmp_string,string) == 0 ||
-       (dir_tmp->file_id[0] == 1 && strcmp(string,"..") == 0)) {
-
-      /* If the element is found or we are searchig for... */
-
-      if (dir_tmp->loc_extent_l == dir_records->loc_extent_l) {
-       /* In this case the inode is a root because the parent
-        * points to the same location than the inode. */
-       *numb = 1;
-       release_dir_record(dir_tmp);
-       put_block(bp);
-       return OK;
-      }
-
-      if (dir_tmp->ext_attr_rec_length != 0) {
-       dir_tmp->ext_attr = get_free_ext_attr();
-       create_ext_attr(dir_tmp->ext_attr,b_data(bp));
-      }
-
-      *numb = ID_DIR_RECORD(dir_tmp);
-      release_dir_record(dir_tmp);
-      put_block(bp);
-      
-      return OK;
-    }
-
-    pos += dir_tmp->length;
-    release_dir_record(dir_tmp);
-  }
-  
-  put_block(bp);
-  return EINVAL;
+       struct inode *dir_tmp;
+       size_t pos = 0;
+       int r;
+
+       /*
+        * This function search a particular element (in string) in a inode and
+        * return its number.
+        */
+
+       if ((ldir_ptr->i_stat.st_mode & S_IFMT) != S_IFDIR)
+               return ENOTDIR;
+
+       if (strcmp(string, ".") == 0) {
+               *numb = ldir_ptr->i_stat.st_ino;
+               return OK;
+       }
+
+       /*
+        * Parent directories need special attention to make sure directory
+        * inodes stay consistent.
+       */
+       if (strcmp(string, "..") == 0) {
+               if (ldir_ptr->i_stat.st_ino == v_pri.inode_root->i_stat.st_ino) {
+                       *numb = v_pri.inode_root->i_stat.st_ino;
+                       return OK;
+               }
+               else {
+                       dir_tmp = alloc_inode();
+                       r = read_inode(dir_tmp, ldir_ptr->extent, pos, &pos);
+                       if ((r != OK) || (pos >= ldir_ptr->i_stat.st_size)) {
+                               put_inode(dir_tmp);
+                               return EINVAL;
+                       }
+                       r = read_inode(dir_tmp, ldir_ptr->extent, pos, &pos);
+                       if ((r != OK) || (pos >= ldir_ptr->i_stat.st_size)) {
+                               put_inode(dir_tmp);
+                               return EINVAL;
+                       }
+                       *numb = dir_tmp->i_stat.st_ino;
+                       put_inode(dir_tmp);
+                       return OK;
+               }
+       }
+
+       /* Read the dir's content */
+       while (TRUE) {
+               dir_tmp = alloc_inode();
+               r = read_inode(dir_tmp, ldir_ptr->extent, pos, &pos);
+               if ((r != OK) || (pos >= ldir_ptr->i_stat.st_size)) {
+                       put_inode(dir_tmp);
+                       return EINVAL;
+               }
+
+               if ((strcmp(dir_tmp->i_name, string) == 0) ||
+                   (strcmp(dir_tmp->i_name, "..") && strcmp(string, "..") == 0)) {
+                       if (dir_tmp->i_stat.st_ino == v_pri.inode_root->i_stat.st_ino) {
+                               *numb = v_pri.inode_root->i_stat.st_ino;
+                               put_inode(dir_tmp);
+                               return OK;
+                       }
+
+                       *numb = dir_tmp->i_stat.st_ino;
+                       put_inode(dir_tmp);
+                       return OK;
+               }
+
+               put_inode(dir_tmp);
+       }
 }
 
 
@@ -185,187 +165,287 @@ static int parse_path(
 ino_t dir_ino,
 ino_t root_ino,
 int flags,
-struct dir_record **res_inop,
-size_t *offsetp
+struct inode **res_inop,
+size_t *offsetp,
+int *symlinkp
 ) {
-  int r;
-  char string[NAME_MAX+1];
-  char *cp, *ncp;
-  struct dir_record *start_dir, *old_dir;
-
-  /* Find starting inode inode according to the request message */
-  if ((start_dir = get_dir_record(dir_ino)) == NULL) {
-    printf("ISOFS: couldn't find starting inode %llu\n", dir_ino);
-    return(ENOENT);
-  }
-  
-  cp = user_path;
-
-  /* Scan the path component by component. */
-  while (TRUE) {
-    if (cp[0] == '\0') {
-      /* Empty path */
-      *res_inop= start_dir;
-      *offsetp += cp-user_path;
-
-      /* Return EENTERMOUNT if we are at a mount point */
-      if (start_dir->d_mountpoint)
-               return EENTERMOUNT;
-
-      return OK;
-    }
-
-    if (cp[0] == '/') {
-      /* Special case code. If the remaining path consists of just
-       * slashes, we need to look up '.'
-       */
-      while(cp[0] == '/')
-       cp++;
-      if (cp[0] == '\0') {
-       strlcpy(string, ".", NAME_MAX + 1);
-       ncp = cp;
-      }
-      else
-       ncp = get_name(cp, string);
-    } else
-      /* Just get the first component */
-      ncp = get_name(cp, string);
-  
-    /* Special code for '..'. A process is not allowed to leave a chrooted
-     * environment. A lookup of '..' at the root of a mounted filesystem
-     * has to return ELEAVEMOUNT.
-     */
-    if (strcmp(string, "..") == 0) {
-
-      /* This condition is not necessary since it will never be the root filesystem */
-      /*       if (start_dir == dir_records) { */
-      /*       cp = ncp; */
-      /*       continue;       /\* Just ignore the '..' at a process' */
-      /*                        * root. */
-      /*                        *\/ */
-      /*       } */
-
-      if (start_dir == dir_records) {
-       /* Climbing up mountpoint */
-       release_dir_record(start_dir);
-       *res_inop = NULL;
-       *offsetp += cp-user_path;
-       return ELEAVEMOUNT;
-      }
-    } else {
-      /* Only check for a mount point if we are not looking for '..'. */
-      if (start_dir->d_mountpoint) {
-       *res_inop= start_dir;
-       *offsetp += cp-user_path;
-       return EENTERMOUNT;
-      }
-    }
-    /* There is more path.  Keep parsing. */
-    old_dir = start_dir;
-
-    r = advance(old_dir, string, &start_dir);
-
-    if (r != OK) {
-      release_dir_record(old_dir);
-      return r;
-    }
-
-    release_dir_record(old_dir);
-    cp = ncp;
-  }
+       int r;
+       char string[NAME_MAX+1];
+       char *cp, *ncp;
+       struct inode *start_dir = 0, *old_dir = 0;
+
+       /* Find starting inode inode according to the request message */
+       if ((start_dir = find_inode(dir_ino)) == NULL) {
+               printf("ISOFS: couldn't find starting inode %llu\n", dir_ino);
+               return ENOENT;
+       }
+
+       cp = user_path;
+       dup_inode(start_dir);
+
+       /* Scan the path component by component. */
+       while (TRUE) {
+               if (cp[0] == '\0') {
+                       /* Empty path */
+                       *res_inop = start_dir;
+                       *offsetp += cp-user_path;
+
+                       /* Return EENTERMOUNT if we are at a mount point */
+                       if (start_dir->i_mountpoint)
+                               return EENTERMOUNT;
+
+                       return OK;
+               }
+
+               if (cp[0] == '/') {
+                       /*
+                       * Special case code. If the remaining path consists of
+                       * just slashes, we need to look up '.'
+                       */
+                       while(cp[0] == '/')
+                               cp++;
+                       if (cp[0] == '\0') {
+                               strlcpy(string, ".", NAME_MAX + 1);
+                               ncp = cp;
+                       }
+                       else
+                               ncp = get_name(cp, string);
+               }
+               else
+                       /* Just get the first component */
+                       ncp = get_name(cp, string);
+
+               /* Special code for '..'. A process is not allowed to leave a chrooted
+               * environment. A lookup of '..' at the root of a mounted filesystem
+               * has to return ELEAVEMOUNT.
+               */
+               if (strcmp(string, "..") == 0) {
+
+                       /* This condition is not necessary since it will never be the root filesystem */
+                       /*       if (start_dir == v_pri.inode_root) { */
+                       /*      cp = ncp; */
+                       /*      continue;       /\* Just ignore the '..' at a process' */
+                       /*                       * root. */
+                       /*                       *\/ */
+                       /*       } */
+
+                       if (start_dir == v_pri.inode_root) {
+                               /* Climbing up mountpoint. */
+                               put_inode(start_dir);
+                               *res_inop = NULL;
+                               *offsetp += cp-user_path;
+                               return ELEAVEMOUNT;
+                       }
+               }
+               else {
+                       /* Only check for a mount point if we are not looking for '..'. */
+                       if (start_dir->i_mountpoint) {
+                               *res_inop = start_dir;
+                               *offsetp += cp-user_path;
+                               return EENTERMOUNT;
+                       }
+               }
+
+               /* There is more path.  Keep parsing. */
+               old_dir = start_dir;
+
+               r = advance(old_dir, string, &start_dir);
+
+               if (r != OK) {
+                       put_inode(old_dir);
+                       return r;
+               }
+
+               /* The call to advance() succeeded.  Fetch next component. */
+               if (S_ISLNK(start_dir->i_stat.st_mode)) {
+
+                       if (ncp[0] == '\0' && (flags & PATH_RET_SYMLINK)) {
+                               put_inode(old_dir);
+                               *res_inop = start_dir;
+                               *offsetp += ncp - user_path;
+                               return OK;
+                       }
+
+                       /* Extract path name from the symlink file */
+                       r = ltraverse(start_dir, ncp);
+                       ncp = user_path;
+                       *offsetp = 0;
+
+                       /* Symloop limit reached? */
+                       if (++(*symlinkp) > _POSIX_SYMLOOP_MAX)
+                               r = ELOOP;
+
+                       if (r != OK) {
+                               put_inode(old_dir);
+                               put_inode(start_dir);
+                               return r;
+                       }
+
+                       if (ncp[0] == '/') {
+                               put_inode(old_dir);
+                               put_inode(start_dir);
+                               return ESYMLINK;
+                       }
+
+                       put_inode(start_dir);
+                       dup_inode(old_dir);
+                       start_dir = old_dir;
+               }
+
+               put_inode(old_dir);
+               cp = ncp;
+       }
 }
 
+/*===========================================================================*
+ *                             ltraverse                                    *
+ *===========================================================================*/
+static int ltraverse(
+struct inode *rip,             /* symbolic link */
+char *suffix)                  /* current remaining path. Has to point in the
+                                * user_path buffer
+                                */
+{
+       /* Traverse a symbolic link. Copy the link text from the inode and insert
+        * the text into the path. Return error code or report success. Base
+        * directory has to be determined according to the first character of the
+        * new pathname.
+        */
+
+       size_t llen;            /* length of link */
+       size_t slen;            /* length of suffix */
+       char *sp;               /* start of link text */
+
+       llen = strlen(rip->s_link);
+       sp = rip->s_link;
+       slen = strlen(suffix);
+
+       /* The path we're parsing looks like this:
+        * /already/processed/path/<link> or
+        * /already/processed/path/<link>/not/yet/processed/path
+        * After expanding the <link>, the path will look like
+        * <expandedlink> or
+        * <expandedlink>/not/yet/processed
+        * In both cases user_path must have enough room to hold <expandedlink>.
+        * However, in the latter case we have to move /not/yet/processed to the
+        * right place first, before we expand <link>. When strlen(<expandedlink>) is
+        * smaller than strlen(/already/processes/path), we move the suffix to the
+        * left. Is strlen(<expandedlink>) greater then we move it to the right. Else
+        * we do nothing.
+        */
+
+       if (slen > 0) { /* Do we have path after the link? */
+               /* For simplicity we require that suffix starts with a slash */
+               if (suffix[0] != '/') {
+                       panic("ltraverse: suffix does not start with a slash");
+               }
+
+               /* To be able to expand the <link>, we have to move the 'suffix'
+                * to the right place.
+                */
+               if (slen + llen + 1 > sizeof(user_path))
+                       return ENAMETOOLONG;/* <expandedlink>+suffix+\0 does not fit*/
+               if ((unsigned) (suffix - user_path) != llen) {
+                       /* Move suffix left or right */
+                       memmove(&user_path[llen], suffix, slen+1);
+               }
+       }
+       else {
+               if (llen + 1 > sizeof(user_path))
+                       return ENAMETOOLONG; /* <expandedlink> + \0 does not fix */
+
+               /* Set terminating nul */
+               user_path[llen]= '\0';
+       }
+
+       /* Everything is set, now copy the expanded link to user_path */
+       memmove(user_path, sp, llen);
+
+       return OK;
+}
 
 /*===========================================================================*
  *                             advance                                      *
  *===========================================================================*/
-int advance(dirp, string, resp)
-struct dir_record *dirp;               /* inode for directory to be searched */
-char string[NAME_MAX];                 /* component name to look for */
-struct dir_record **resp;              /* resulting inode */
+int advance(
+struct inode *dirp,            /* inode for directory to be searched */
+char string[NAME_MAX],                 /* component name to look for */
+struct inode **resp)           /* resulting inode */
 {
-/* Given a directory and a component of a path, look up the component in
- * the directory, find the inode, open it, and return a pointer to its inode
- * slot.
- */
-
-  register struct dir_record *rip = NULL;
-  int r;
-  ino_t numb;
-
-  /* If 'string' is empty, yield same inode straight away. */
-  if (string[0] == '\0') {
-    return ENOENT;
-  }
-
-  /* Check for NULL. */
-  if (dirp == NULL) {
-    return EINVAL;
-  }
-
-  /* If 'string' is not present in the directory, signal error. */
-  if ( (r = search_dir(dirp, string, &numb)) != OK) {
-    return r;
-  }
-
-  /* The component has been found in the directory.  Get inode. */
-  if ( (rip = get_dir_record((int) numb)) == NULL)  {
-    return(err_code);
-  }
-
-  *resp= rip;
-  return OK;
-}
+       /* Given a directory and a component of a path, look up the component in
+        * the directory, find the inode, open it, and return a pointer to its inode
+        * slot.
+        */
 
+       struct inode *rip = NULL;
+       int r;
+       ino_t numb;
+
+       /* If 'string' is empty, yield same inode straight away. */
+       if (string[0] == '\0')
+               return ENOENT;
+
+       /* Check for NULL. */
+       if (dirp == NULL)
+               return EINVAL;
+
+       /* If 'string' is not present in the directory, signal error. */
+       if ( (r = search_dir(dirp, string, &numb)) != OK)
+               return r;
+
+       /* The component has been found in the directory.  Get inode. */
+       if ( (rip = get_inode((int) numb)) == NULL)
+               return err_code;
+
+       *resp= rip;
+       return OK;
+}
 
 /*===========================================================================*
  *                             get_name                                     *
  *===========================================================================*/
-static char *get_name(path_name, string)
-char *path_name;               /* path name to parse */
-char string[NAME_MAX+1];       /* component extracted from 'old_name' */
+static char *get_name(
+char *path_name,               /* path name to parse */
+char string[NAME_MAX+1])       /* component extracted from 'old_name' */
 {
-/* Given a pointer to a path name in fs space, 'path_name', copy the first
- * component to 'string' (truncated if necessary, always nul terminated).
- * A pointer to the string after the first component of the name as yet
- * unparsed is returned.  Roughly speaking,
- * 'get_name' = 'path_name' - 'string'.
- *
- * This routine follows the standard convention that /usr/ast, /usr//ast,
- * //usr///ast and /usr/ast/ are all equivalent.
- */
-  size_t len;
-  char *cp, *ep;
-
-  cp= path_name;
-
-  /* Skip leading slashes */
-  while (cp[0] == '/')
-       cp++;
-
-  /* Find the end of the first component */
-  ep= cp;
-  while(ep[0] != '\0' && ep[0] != '/')
-       ep++;
-
-  len= ep-cp;
-
-  /* Truncate the amount to be copied if it exceeds NAME_MAX */
-  if (len > NAME_MAX)
-       len= NAME_MAX;
-
-  /* Special case of the string at cp is empty */
-  if (len == 0)
-  {
-       /* Return "." */
-       strlcpy(string, ".", NAME_MAX + 1);
-  }
-  else
-  {
-       memcpy(string, cp, len);
-       string[len]= '\0';
-  }
-
-  return ep;
+       /* Given a pointer to a path name in fs space, 'path_name', copy the first
+        * component to 'string' (truncated if necessary, always nul terminated).
+        * A pointer to the string after the first component of the name as yet
+        * unparsed is returned.  Roughly speaking,
+        * 'get_name' = 'path_name' - 'string'.
+        *
+        * This routine follows the standard convention that /usr/ast, /usr//ast,
+        * //usr///ast and /usr/ast/ are all equivalent.
+        */
+       size_t len;
+       char *cp, *ep;
+
+       cp = path_name;
+
+       /* Skip leading slashes */
+       while (cp[0] == '/')
+               cp++;
+
+       /* Find the end of the first component */
+       ep = cp;
+       while(ep[0] != '\0' && ep[0] != '/')
+               ep++;
+
+       len = ep-cp;
+
+       /* Truncate the amount to be copied if it exceeds NAME_MAX */
+       if (len > NAME_MAX)
+               len = NAME_MAX;
+
+       /* Special case of the string at cp is empty */
+       if (len == 0)
+               /* Return "." */
+               strlcpy(string, ".", NAME_MAX + 1);
+       else {
+               memcpy(string, cp, len);
+               string[len]= '\0';
+       }
+
+       return ep;
 }
+
index faa39aaacadd7988c35d4e470c078fd31eb4fef2..fbcc7055be14cdecd66dffdfa6d9d3889771c83f 100644 (file)
@@ -1,8 +1,11 @@
 /* Function prototypes for iso9660 file system. */
 
 struct dir_record;
-struct ext_attr_rec;
-struct iso9660_vd_pri;
+struct dir_extent;
+struct rrii_dir_record;
+struct iso9660_dir_record;
+struct iso9660_vol_pri_desc;
+struct inode;
 
 #include <minix/libminixfs.h>
 
@@ -10,20 +13,30 @@ struct iso9660_vd_pri;
 #define put_block(n) lmfs_put_block(n, FULL_DATA_BLOCK)
 
 /* main.c */
-int main(void);
+int main(int argc, char *argv[]);
 void reply(int who, message *m_out);
 
 /* inode.c */
-int create_dir_record(struct dir_record *dir, char *buffer, u32_t
-       address);
-int create_ext_attr(struct ext_attr_rec *ext, char *buffer);
-int fs_getnode(void);
 int fs_putnode(void);
-struct dir_record *get_dir_record(ino_t id_dir);
-struct dir_record *get_free_dir_record(void);
-struct ext_attr_rec *get_free_ext_attr(void);
-struct dir_record *load_dir_record_from_disk(u32_t address);
-int release_dir_record(struct dir_record *dir);
+
+struct inode* alloc_inode();
+struct inode* find_inode(ino_t i);
+void put_inode(struct inode *i);
+void dup_inode(struct inode *i_node);
+struct inode* get_inode(ino_t i);
+
+int read_inode(struct inode *i_node, struct dir_extent *extent, size_t offset,
+       size_t *new_offset);
+void read_inode_iso9660(struct inode *i, const struct iso9660_dir_record *dir_rec);
+void read_inode_extents(struct inode *i, const struct iso9660_dir_record *dir_rec,
+       struct dir_extent *extent, size_t *offset);
+void read_inode_susp(struct inode *i, const struct iso9660_dir_record *dir_rec,
+       struct buf *bp, size_t offset);
+
+int check_dir_record(const struct iso9660_dir_record *d, size_t offset);
+
+/* link.c */
+int fs_rdlink(void);
 
 /* misc.c */
 int fs_sync(void);
@@ -36,29 +49,44 @@ int fs_unmount(void);
 
 /* path.c */
 int fs_lookup(void);
-int advance(struct dir_record *dirp, char string[NAME_MAX], struct
-       dir_record **resp);
-int search_dir(struct dir_record *ldir_ptr, char string [NAME_MAX], ino_t *numb);
+int advance(struct inode *dirp, char string[NAME_MAX], struct
+       inode **resp);
+int search_dir(struct inode *ldir_ptr, char string [NAME_MAX], ino_t *numb);
 
 /* read.c */
 int fs_read(void);
 int fs_bread(void);
 int fs_getdents(void);
-int read_chunk(struct dir_record *rip, u64_t position, unsigned off, int
+int read_chunk(struct inode *rip, u64_t position, unsigned off, int
        chunk, unsigned left, cp_grant_id_t gid, unsigned buf_off, int
        block_size, int *completed, int rw);
 
+
 /* stadir.c */
 int fs_stat(void);
 int fs_statvfs(void);
 
 /* super.c */
-int release_v_pri(struct iso9660_vd_pri *v_pri);
-int read_vds(struct iso9660_vd_pri *v_pri, dev_t dev);
-int create_v_pri(struct iso9660_vd_pri *v_pri, char *buffer, unsigned
-       long address);
+int release_vol_pri_desc(struct iso9660_vol_pri_desc *v_pri);
+int create_vol_pri_desc(struct iso9660_vol_pri_desc *v_pri, char *buf,
+       size_t address);
+int read_vds(struct iso9660_vol_pri_desc *v_pri, dev_t dev);
+
+/* susp.c */
+int parse_susp(struct rrii_dir_record *dir, char *buffer);
+void parse_susp_buffer(struct rrii_dir_record *dir, char *buffer, u32_t size);
+
+/* susp_rock_ridge.c */
+void parse_susp_rock_ridge_sl(struct rrii_dir_record *dir, char *buffer, int length);
+int parse_susp_rock_ridge(struct rrii_dir_record *dir, char *buffer);
 
 /* utility.c */
+struct dir_extent* alloc_extent();
+void free_extent(struct dir_extent *extent);
+struct buf* read_extent_block(struct dir_extent *e, size_t block);
+size_t get_extent_absolute_block_id(struct dir_extent *e, size_t block);
+
+time_t date7_to_time_t(const u8_t *date);
 int do_noop(void);
 int no_sys(void);
 
index ff5738a3b66ad6adda4eb2d976dfbe216712575c..d0e3b6406f3cd6a1b222ed726dc1996112c88304 100644 (file)
 #include <minix/minlib.h>
 #include <fcntl.h>
 #include <stddef.h>
-#include "buf.h"
 
 static char getdents_buf[GETDENTS_BUFSIZ];
 
+int fs_read(void)
+{
+       int r = OK, chunk, block_size, completed, rw;
+       size_t nrbytes, off, cum_io;
+       cp_grant_id_t gid;
+       off_t position, f_size, bytes_left;
+       struct inode *i_node;
+
+       switch(fs_m_in.m_type) {
+               case REQ_READ: rw = READING; break;
+               case REQ_PEEK: rw = PEEKING; break;
+               default: panic("odd m_type");
+       }
 
-/*===========================================================================*
- *                             fs_read                                      *
- *===========================================================================*/
-int fs_read(void) {
-  int r, chunk, block_size;
-  size_t nrbytes;
-  cp_grant_id_t gid;
-  off_t position, f_size, bytes_left;
-  unsigned int off, cum_io;
-  int completed;
-  struct dir_record *dir;
-  int rw;
-
-  switch(fs_m_in.m_type) {
-       case REQ_READ: rw = READING; break;
-       case REQ_PEEK: rw = PEEKING; break;
-       default: panic("odd m_type");
-  }
-  
-  r = OK;
-  
-  /* Try to get inode according to its index */
-  dir = get_dir_record(fs_m_in.m_vfs_fs_readwrite.inode);
-  if (dir == NULL) return(EINVAL); /* no inode found */
-
-  position = fs_m_in.m_vfs_fs_readwrite.seek_pos;
-  nrbytes = fs_m_in.m_vfs_fs_readwrite.nbytes; /* number of bytes to read */
-  block_size = v_pri.logical_block_size_l;
-  gid = fs_m_in.m_vfs_fs_readwrite.grant;
-  f_size = dir->d_file_size;
-
-  rdwt_err = OK;               /* set to EIO if disk error occurs */
-  
-  cum_io = 0;
-  /* Split the transfer into chunks that don't span two blocks. */
-  while (nrbytes != 0) {
-       off = position % block_size;
-          
-       chunk = MIN(nrbytes, block_size - off);
-       if (chunk < 0) chunk = block_size - off;
-
-       bytes_left = f_size - position;
-       if (position >= f_size) break;  /* we are beyond EOF */
-       if (chunk > bytes_left) chunk = (int32_t) bytes_left;
-      
-       /* Read or write 'chunk' bytes. */
-       r = read_chunk(dir, position, off, chunk,
-                       (uint32_t) nrbytes, gid, cum_io, block_size,
-                       &completed, rw);
-
-       if (r != OK) break;     /* EOF reached */
-       if (rdwt_err < 0) break;
-
-       /* Update counters and pointers. */
-       nrbytes -= chunk;       /* bytes yet to be read */
-       cum_io += chunk;        /* bytes read so far */
-       position += chunk;      /* position within the file */
-  }
-
-  fs_m_out.m_fs_vfs_readwrite.seek_pos = position;
-  
-  if (rdwt_err != OK) r = rdwt_err;    /* check for disk error */
-  if (rdwt_err == END_OF_FILE) r = OK;
-  
-  fs_m_out.m_fs_vfs_readwrite.nbytes = cum_io; /*dir->d_file_size;*/
-  release_dir_record(dir);
-
-  return(r);
-}
+       /* Try to get inode according to its index. */
+       i_node = find_inode(fs_m_in.m_vfs_fs_readwrite.inode);
+       if (i_node == NULL)
+               return EINVAL; /* No inode found. */
+
+       position        = fs_m_in.m_vfs_fs_readwrite.seek_pos;
+       nrbytes         = fs_m_in.m_vfs_fs_readwrite.nbytes; /* Number of bytes to read. */
+       block_size      = v_pri.logical_block_size_l;
+       gid             = fs_m_in.m_vfs_fs_readwrite.grant;
+       f_size          = i_node->i_stat.st_size;
+       rdwt_err        = OK;   /* Set to EIO if disk error occurs. */
+       cum_io          = 0;
+
+       /* Split the transfer into chunks that don't span two blocks. */
+       while (nrbytes != 0) {
+               off = position % block_size;
+
+               chunk = MIN(nrbytes, block_size - off);
+               if (chunk < 0)
+                       chunk = block_size - off;
+
+               bytes_left = f_size - position;
+               if (position >= f_size)
+                       break;  /* We are beyond EOF. */
+               if (chunk > bytes_left)
+                       chunk = (int32_t) bytes_left;
+
+               /* Read or write 'chunk' bytes. */
+               r = read_chunk(i_node, position, off, chunk,
+                               (uint32_t) nrbytes, gid, cum_io, block_size,
+                               &completed, rw);
+
+               if (r != OK)
+                       break;  /* EOF reached. */
+               if (rdwt_err < 0)
+                       break;
+
+               /* Update counters and pointers. */
+               nrbytes -= chunk;       /* Bytes yet to be read. */
+               cum_io += chunk;        /* Bytes read so far. */
+               position += chunk;      /* Position within the file. */
+       }
 
+       fs_m_out.m_fs_vfs_readwrite.seek_pos = position;
+
+       if (rdwt_err != OK)
+               r = rdwt_err;   /* Check for disk error. */
+       if (rdwt_err == END_OF_FILE)
+               r = OK;
+
+       fs_m_out.m_fs_vfs_readwrite.nbytes = cum_io;
+       return r;
+}
 
-/*===========================================================================*
- *                             fs_bread                                     *
- *===========================================================================*/
 int fs_bread(void)
 {
-  int r, rw_flag, chunk, block_size;
-  cp_grant_id_t gid;
-  int nrbytes;
-  u64_t position;
-  unsigned int off, cum_io;
-  int completed;
-  struct dir_record *dir;
-  
-  r = OK;
-  
-  rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING);
-  gid = fs_m_in.m_vfs_fs_breadwrite.grant;
-  position = fs_m_in.m_vfs_fs_breadwrite.seek_pos;
-  nrbytes = fs_m_in.m_vfs_fs_breadwrite.nbytes;
-  block_size = v_pri.logical_block_size_l;
-  dir = v_pri.dir_rec_root;
-
-  if(rw_flag == WRITING) return (EIO); /* Not supported */
-  rdwt_err = OK;               /* set to EIO if disk error occurs */
-  
-  cum_io = 0;
-  /* Split the transfer into chunks that don't span two blocks. */
-  while (nrbytes != 0) {
-    off = (unsigned int)(position % block_size);       /* offset in blk*/
-    
-    chunk = MIN(nrbytes, block_size - off);
-    if (chunk < 0) chunk = block_size - off;
-
-       /* Read 'chunk' bytes. */
-    r = read_chunk(dir, position, off, chunk, (unsigned) nrbytes, 
-                  gid, cum_io, block_size, &completed, READING);
-    
-    if (r != OK) break;        /* EOF reached */
-    if (rdwt_err < 0) break;
-    
-    /* Update counters and pointers. */
-    nrbytes -= chunk;  /* bytes yet to be read */
-    cum_io += chunk;   /* bytes read so far */
-    position += chunk; /* position within the file */
-  }
-  
-  fs_m_out.m_fs_vfs_breadwrite.seek_pos = position;
-  
-  if (rdwt_err != OK) r = rdwt_err;    /* check for disk error */
-  if (rdwt_err == END_OF_FILE) r = OK;
-
-  fs_m_out.m_fs_vfs_breadwrite.nbytes = cum_io;
-  
-  return(r);
-}
+       int r = OK,  rw_flag, chunk, block_size, completed;
+       size_t nrbytes, off, cum_io;
+       cp_grant_id_t gid;
+       off_t position;
+       struct inode *i_node;
+
+       r = OK;
+
+       rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING);
+       gid = fs_m_in.m_vfs_fs_breadwrite.grant;
+       position = fs_m_in.m_vfs_fs_breadwrite.seek_pos;
+       nrbytes = fs_m_in.m_vfs_fs_breadwrite.nbytes;
+       block_size = v_pri.logical_block_size_l;
+       i_node = v_pri.inode_root;
+
+       if(rw_flag == WRITING)
+               return EIO;     /* Not supported */
+
+       rdwt_err = OK;          /* set to EIO if disk error occurs */
+
+       cum_io = 0;
+       /* Split the transfer into chunks that don't span two blocks. */
+       while (nrbytes != 0) {
+               off = (unsigned int)(position % block_size);    /* offset in blk*/
+
+               chunk = MIN(nrbytes, block_size - off);
+               if (chunk < 0)
+                       chunk = block_size - off;
+
+               /* Read 'chunk' bytes. */
+               r = read_chunk(i_node, position, off, chunk, (unsigned) nrbytes, 
+                              gid, cum_io, block_size, &completed, READING);
+
+               if (r != OK)
+                       break;  /* EOF reached */
+               if (rdwt_err < 0)
+                       break;
+
+               /* Update counters and pointers. */
+               nrbytes -= chunk;       /* bytes yet to be read */
+               cum_io += chunk;        /* bytes read so far */
+               position += chunk;      /* position within the file */
+       }
+
+       fs_m_out.m_fs_vfs_breadwrite.seek_pos = position;
 
+       if (rdwt_err != OK)
+               r = rdwt_err;           /* check for disk error */
+       if (rdwt_err == END_OF_FILE)
+               r = OK;
+
+       fs_m_out.m_fs_vfs_breadwrite.nbytes = cum_io;
+
+       return r;
+}
 
-/*===========================================================================*
- *                             fs_getdents                                  *
- *===========================================================================*/
 int fs_getdents(void)
 {
-  struct dir_record *dir;
-  ino_t ino;
-  cp_grant_id_t gid;
-  size_t block_size;
-  off_t pos, block_pos, block, cur_pos, tmpbuf_offset, userbuf_off;
-  struct buf *bp;
-  struct dir_record *dir_tmp;
-  struct dirent *dirp;
-  int r,done,o,len,reclen;
-  char *cp;
-  char name[NAME_MAX + 1];
-  char name_old[NAME_MAX + 1];
-
-  /* Initialize the tmp arrays */
-  memset(name,'\0',NAME_MAX);
-  memset(name_old,'\0',NAME_MAX);
-
-  /* Get input parameters */
-  ino = fs_m_in.m_vfs_fs_getdents.inode;
-  gid = fs_m_in.m_vfs_fs_getdents.grant;
-  pos = fs_m_in.m_vfs_fs_getdents.seek_pos;
-
-  block_size = v_pri.logical_block_size_l;
-  cur_pos = pos;               /* The current position */
-  tmpbuf_offset = 0;
-  userbuf_off = 0;
-  memset(getdents_buf, '\0', GETDENTS_BUFSIZ); /* Avoid leaking any data */
-
-  if ((dir = get_dir_record(ino)) == NULL) return(EINVAL);
-
-  block = dir->loc_extent_l;   /* First block of the directory */
-  block += pos / block_size;   /* Shift to the block where start to read */
-  done = FALSE;
-
-  while (cur_pos<dir->d_file_size) {
-       bp = get_block(block);  /* Get physical block */
-
-       if (bp == NULL) {
-               release_dir_record(dir);
-               return(EINVAL);
-       }
-    
-       block_pos = cur_pos % block_size; /* Position where to start read */
-
-       while (block_pos < block_size) {
-               dir_tmp = get_free_dir_record();
-               create_dir_record(dir_tmp,b_data(bp) + block_pos,
-                                 block*block_size + block_pos);
-               if (dir_tmp->length == 0) { /* EOF. I exit and return 0s */
-                       block_pos = block_size;
-                       done = TRUE;
-                       release_dir_record(dir_tmp);
-               } else {        /* The dir record is valid. Copy data... */
-                       if (dir_tmp->file_id[0] == 0)
-                               strlcpy(name, ".", NAME_MAX + 1);
-                       else if (dir_tmp->file_id[0] == 1)
-                               strlcpy(name, "..", NAME_MAX + 1);
-                       else {
-                               /* Extract the name from the field file_id */
-                               strncpy(name, dir_tmp->file_id,
-                                       dir_tmp->length_file_id);
-                               name[dir_tmp->length_file_id] = 0;
-         
-                               /* Tidy up file name */
-                               cp = memchr(name, ';', NAME_MAX); 
-                               if (cp != NULL) name[cp - name] = 0;
-         
-                               /*If no file extension, then remove final '.'*/
-                               if (name[strlen(name) - 1] == '.')
-                                       name[strlen(name) - 1] = '\0';
+       struct inode *i_node, *i_node_tmp;
+       ino_t ino;
+       cp_grant_id_t gid;
+       size_t old_pos = 0, cur_pos, new_pos, tmpbuf_off = 0, userbuf_off = 0, grant_size;
+       struct dirent *dirp;
+       int r, len, reclen;
+       char *cp;
+
+       /* Get input parameters */
+       ino        = fs_m_in.m_vfs_fs_getdents.inode;
+       gid        = fs_m_in.m_vfs_fs_getdents.grant;
+       cur_pos    = fs_m_in.m_vfs_fs_getdents.seek_pos;
+       grant_size = fs_m_in.m_vfs_fs_getdents.mem_size;
+
+       //memset(getdents_buf, '\0', GETDENTS_BUFSIZ);  /* Avoid leaking any data */
+
+       if ((i_node = get_inode(ino)) == NULL)
+               return EINVAL;
+
+       while (TRUE) {
+               i_node_tmp = alloc_inode();
+               r = read_inode(i_node_tmp, i_node->extent, cur_pos, &new_pos);
+               if ((r != OK) || (new_pos >= i_node->i_stat.st_size)) {
+                       put_inode(i_node);
+                       put_inode(i_node_tmp);
+                       break;
+               }
+               cur_pos = new_pos;
+
+               /* Compute the length of the name */
+               cp = memchr(i_node_tmp->i_name, '\0', NAME_MAX);
+               if (cp == NULL)
+                       len = NAME_MAX;
+               else
+                       len = cp - i_node_tmp->i_name;
+
+               /* Compute record length; also does alignment. */
+               reclen = _DIRENT_RECLEN(dirp, len);
+
+               /* If the new record does not fit, then copy the buffer
+                * and start from the beginning. */
+               if (tmpbuf_off + reclen > GETDENTS_BUFSIZ ||
+                   userbuf_off + tmpbuf_off + reclen > grant_size) {
+                       r = sys_safecopyto(VFS_PROC_NR, gid, userbuf_off, 
+                           (vir_bytes)getdents_buf, tmpbuf_off);
+
+                       if (r != OK)
+                               panic("fs_getdents: sys_safecopyto failed: %d", r);
+
+                       /* Check if the user grant buffer is filled. */
+                       if (userbuf_off + tmpbuf_off + reclen > grant_size) {
+                               fs_m_out.m_fs_vfs_getdents.nbytes = userbuf_off + tmpbuf_off;
+                               fs_m_out.m_fs_vfs_getdents.seek_pos = old_pos;
+                               return OK;
                        }
 
-                       if (strcmp(name_old, name) == 0) {
-                               cur_pos += dir_tmp->length;
-                               release_dir_record(dir_tmp);
-                               continue;
-                       }
+                       userbuf_off += tmpbuf_off;
+                       tmpbuf_off = 0;
+               }
 
-                       strlcpy(name_old, name, NAME_MAX + 1);
+               /* The standard data structure is created using the
+                * data in the buffer. */
+               dirp = (struct dirent *) &getdents_buf[tmpbuf_off];
+               dirp->d_fileno = i_node_tmp->i_stat.st_ino;
+               dirp->d_reclen = reclen;
+               dirp->d_type   = fs_mode_to_type(i_node_tmp->i_stat.st_mode);
+               dirp->d_namlen = len;
 
-                       /* Compute the length of the name */
-                       cp = memchr(name, '\0', NAME_MAX);
-                       if (cp == NULL)
-                               len = NAME_MAX;
-                       else
-                               len= cp - name;
+               memcpy(dirp->d_name, i_node_tmp->i_name, len);
+               dirp->d_name[len]= '\0';
 
-                       /* Compute record length; also does alignment. */
-                       reclen = _DIRENT_RECLEN(dirp, len);
+               tmpbuf_off += reclen;
+               put_inode(i_node_tmp);
 
-                       /* If the new record does not fit, then copy the buffer
-                        * and start from the beginning. */
-                       if (tmpbuf_offset + reclen > GETDENTS_BUFSIZ) {
-                               r = sys_safecopyto(VFS_PROC_NR, gid, userbuf_off, 
-                                   (vir_bytes)getdents_buf, tmpbuf_offset);
+               old_pos = cur_pos;
+       }
 
-                               if (r != OK)
-                                       panic("fs_getdents: sys_safecopyto failed: %d", r);
-                               userbuf_off += tmpbuf_offset;
-                               tmpbuf_offset= 0;
-                       }
-       
-                       /* The standard data structure is created using the
-                        * data in the buffer. */
-                       dirp = (struct dirent *) &getdents_buf[tmpbuf_offset];
-                       dirp->d_fileno = (u32_t)(b_data(bp) + (size_t)block_pos);
-                       dirp->d_reclen= reclen;
-                       dirp->d_type = fs_mode_to_type(dir_tmp->d_mode);
-                       dirp->d_namlen = len;
-                       memcpy(dirp->d_name, name, len);
-                       dirp->d_name[len]= '\0';
-                       tmpbuf_offset += reclen;
-       
-                       cur_pos += dir_tmp->length;
-                       release_dir_record(dir_tmp);
-               }
+       if (tmpbuf_off != 0) {
+               r = sys_safecopyto(VFS_PROC_NR, gid, userbuf_off,
+                                  (vir_bytes) getdents_buf, tmpbuf_off);
 
-               block_pos += dir_tmp->length;
-       }
-    
-       put_block(bp);          /* release the block */
-       if (done == TRUE) break;
-    
-       cur_pos += block_size - cur_pos;
-       block++;                        /* read the next one */
-  }
-
-  if (tmpbuf_offset != 0) {
-       r = sys_safecopyto(VFS_PROC_NR, gid, userbuf_off,
-                          (vir_bytes) getdents_buf, tmpbuf_offset);
-       if (r != OK)
-               panic("fs_getdents: sys_safecopyto failed: %d", r);
-       userbuf_off += tmpbuf_offset;
-  }
-  
-  fs_m_out.m_fs_vfs_getdents.nbytes = userbuf_off;
-  fs_m_out.m_fs_vfs_getdents.seek_pos = cur_pos;
-
-  release_dir_record(dir);             /* release the inode */
-  return(OK);
-}
+               if (r != OK)
+                       panic("fs_getdents: sys_safecopyto failed: %d", r);
+
+               userbuf_off += tmpbuf_off;
+       }
+
+       fs_m_out.m_fs_vfs_getdents.nbytes = userbuf_off;
+       fs_m_out.m_fs_vfs_getdents.seek_pos = cur_pos;
 
+       return OK;
+}
 
-/*===========================================================================*
- *                             read_chunk                                   *
- *===========================================================================*/
-int read_chunk(dir, position, off, chunk, left, gid, buf_off, block_size, completed, rw)
-register struct dir_record *dir;/* pointer to inode for file to be rd/wr */
-u64_t position;                        /* position within file to read or write */
-unsigned off;                  /* off within the current block */
-int chunk;                     /* number of bytes to read or write */
-unsigned left;                 /* max number of bytes wanted after position */
-cp_grant_id_t gid;             /* grant */
-unsigned buf_off;              /* offset in grant */
-int block_size;                        /* block size of FS operating on */
-int *completed;                        /* number of bytes copied */
-int rw;                                /* READING or PEEKING */
+int read_chunk(
+struct inode *i_node,          /* pointer to inode for file to be rd/wr */
+u64_t position,                        /* position within file to read or write */
+unsigned off,                  /* off within the current block */
+int chunk,                     /* number of bytes to read or write */
+unsigned left,                 /* max number of bytes wanted after position */
+cp_grant_id_t gid,             /* grant */
+unsigned buf_off,              /* offset in grant */
+int block_size,                        /* block size of FS operating on */
+int *completed,                        /* number of bytes copied */
+int rw)                                /* READING or PEEKING */
 {
+       struct buf *bp;
+       int r = OK;
+
+       *completed = 0;
+
+       bp = read_extent_block(i_node->extent, position / block_size);
+       if (bp == NULL)
+               panic("bp not valid in rw_chunk; this can't happen");
+
+       if(rw == READING) {
+               r = sys_safecopyto(VFS_PROC_NR, gid, buf_off,
+                                 (vir_bytes) (b_data(bp)+off),
+                                 (phys_bytes) chunk);
+       }
 
-  register struct buf *bp;
-  register int r = OK;
-  block_t b;
-  int file_unit, rel_block, offset;
-
-  *completed = 0;
-
-  if ((ex64lo(position) <= dir->d_file_size) && 
-                               (ex64lo(position) > dir->data_length_l)) {
-    while ((dir->d_next != NULL) && (ex64lo(position) > dir->data_length_l)) {
-      position -= dir->data_length_l;
-      dir = dir->d_next;
-    }
-  }
-
-  if (dir->inter_gap_size != 0) {
-    rel_block = (unsigned long)(position / block_size);
-    file_unit = rel_block / dir->data_length_l;
-    offset = rel_block % dir->file_unit_size;
-    b = dir->loc_extent_l + (dir->file_unit_size +
-                                dir->inter_gap_size) * file_unit + offset;
-  } else {
-    b = dir->loc_extent_l + (unsigned long)(position / block_size); 
-                                           /* Physical position to read. */
-  }
-
-  bp = get_block(b);
-
-  /* In all cases, bp now points to a valid buffer. */
-  if (bp == NULL) {
-    panic("bp not valid in rw_chunk; this can't happen");
-  }
-  
-  if(rw == READING) {
-        r = sys_safecopyto(VFS_PROC_NR, gid, buf_off,
-                    (vir_bytes) (b_data(bp)+off), (phys_bytes) chunk);
-  }
-
-  put_block(bp);
-
-  return(r);
+       put_block(bp);
+       return r;
 }
 
index 9f0d9d607f551561a4c1207e30c8ec50301cf53a..5ea10463d3f7156547cc1dfc08c90c3faa583b4c 100644 (file)
 
 #include <minix/vfsif.h>
 
-
-/*===========================================================================*
- *                             stat_dir_record                              *
- *===========================================================================*/
-static int stat_dir_record(
-  register struct dir_record *dir,     /* pointer to dir record to stat */
-  int pipe_pos,                /* position in a pipe, supplied by fstat() */
-  endpoint_t who_e,            /* Caller endpoint */
-  cp_grant_id_t gid            /* grant for the stat buf */
-)
-{
-/* This function returns all the info about a particular inode. It's missing
- * the recording date because of a bug in the standard functions stdtime.
- * Once the bug is fixed the function can be called inside this function to
- * return the date. */
-
-/* Common code for stat and fstat system calls. */
-  struct stat statbuf;
-  int r;
-  struct tm ltime;
-  time_t time1;
-  u32_t blocks;
-
-  blocks = v_pri.volume_space_size_l;
-  /* The unit of blocks should be 512 */
-  assert(v_pri.logical_block_size_l >= 512);
-  blocks = blocks * (v_pri.logical_block_size_l >> 9);
-
-  memset(&statbuf, 0, sizeof(struct stat));
-
-  statbuf.st_dev = fs_dev;     /* the device of the file */
-  statbuf.st_ino = ID_DIR_RECORD(dir); /* the id of the dir record */
-  statbuf.st_mode = dir->d_mode; /* flags of the file */
-  statbuf.st_nlink = dir->d_count; /* times this file is used */
-  statbuf.st_uid = 0;          /* user root */
-  statbuf.st_gid = 0;          /* group operator */
-  statbuf.st_rdev = NO_DEV;
-  statbuf.st_size = dir->d_file_size;  /* size of the file */
-  statbuf.st_blksize = v_pri.logical_block_size_l;
-  statbuf.st_blocks = blocks;
-
-  ltime.tm_year = dir->rec_date[0];
-  ltime.tm_mon = dir->rec_date[1] - 1;
-  ltime.tm_mday = dir->rec_date[2];
-  ltime.tm_hour = dir->rec_date[3];
-  ltime.tm_min = dir->rec_date[4];
-  ltime.tm_sec = dir->rec_date[5];
-  ltime.tm_isdst = 0;
-
-  if (dir->rec_date[6] != 0)
-       ltime.tm_hour += dir->rec_date[6] / 4;
-
-  time1 = mktime(&ltime);
-
-  statbuf.st_atime = time1;
-  statbuf.st_mtime = time1;
-  statbuf.st_ctime = time1;
-
-  /* Copy the struct to user space. */
-  r = sys_safecopyto(who_e, gid, 0, (vir_bytes) &statbuf,
-                    (phys_bytes) sizeof(statbuf));
-  
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             fs_stat                                      *
- *===========================================================================*/
 int fs_stat()
 {
-  register int r;              /* return value */
-  struct dir_record *dir;
-  r = EINVAL;
+       int r = EINVAL; /* return value */
+       struct inode *dir;
 
-  if ((dir = get_dir_record(fs_m_in.m_vfs_fs_stat.inode)) != NULL) {
-       r = stat_dir_record(dir, 0, fs_m_in.m_source, fs_m_in.m_vfs_fs_stat.grant);
-       release_dir_record(dir);
-  } 
+       if ((dir = get_inode(fs_m_in.m_vfs_fs_stat.inode)) != NULL) {
+               r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_stat.grant,
+                                  0, (vir_bytes) &dir->i_stat,
+                                  (phys_bytes) sizeof(dir->i_stat));
+               put_inode(dir);
+       }
 
-  return(r);
+       return r;
 }
 
-
-/*===========================================================================*
- *                             fs_statvfs                                   *
- *===========================================================================*/
 int fs_statvfs()
 {
-  struct statvfs st;
-  int r;
+       int r;
+       struct statvfs st;
+
+       memset(&st, 0, sizeof(st));
 
-  memset(&st, 0, sizeof(st));
+       st.f_bsize =  v_pri.logical_block_size_l;
+       st.f_frsize = st.f_bsize;
+       st.f_iosize = st.f_bsize;
+       st.f_blocks = v_pri.volume_space_size_l;
+       st.f_namemax = NAME_MAX;
 
-  st.f_bsize =  v_pri.logical_block_size_l;
-  st.f_frsize = st.f_bsize;
-  st.f_iosize = st.f_bsize;
-  st.f_blocks = v_pri.volume_space_size_l;
-  st.f_namemax = NAME_MAX;
+       /* Copy the struct to user space. */
+       r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_statvfs.grant, 0,
+                          (vir_bytes) &st, (phys_bytes) sizeof(st));
 
-  /* Copy the struct to user space. */
-  r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_statvfs.grant, 0,
-                        (vir_bytes) &st, (phys_bytes) sizeof(st));
-  
-  return(r);
+       return r;
 }
 
-/*===========================================================================*
- *                              blockstats                                   *
-  *===========================================================================*/
 void fs_blockstats(u64_t *blocks, u64_t *free, u64_t *used)
 {
-        *used = *blocks = v_pri.volume_space_size_l;
-        *free = 0;
+       *used = *blocks = v_pri.volume_space_size_l;
+       *free = 0;
 }
 
index 3f9bcfab80de89a3f7b70c02c6f67a7060019b5e..df5a3735341e54369b798bdf7722abb2716a540e 100644 (file)
@@ -1,5 +1,7 @@
-/* Functions to manage the superblock of the filesystem. These functions are
- * are called at the beginning and at the end of the server. */
+/*
+ * Functions to manage the superblock of the filesystem. These functions are
+ * are called at the beginning and at the end of the server.
+ */
 
 #include "inc.h"
 #include <string.h>
 #include <minix/u64.h>
 #include <minix/bdev.h>
 
-/* This function is called when the filesystem is umounted. It releases the 
- * super block. */
-int release_v_pri(v_pri)
-     register struct iso9660_vd_pri *v_pri;
+int release_vol_pri_desc(struct iso9660_vol_pri_desc *vol_pri)
 {
-  /* Release the root dir record */
-  release_dir_record(v_pri->dir_rec_root);
-  v_pri->count = 0;
-  return OK;
-}
+       /* Release the root dir root. */
+       if (vol_pri->i_count > 0) {
+               put_inode(vol_pri->inode_root);
+               vol_pri->inode_root = NULL;
+               vol_pri->i_count = 0;
+       }
 
-/* This function fullfill the super block data structure using the information
- * contained in the stream buf. Such stream is physically read from the device
- * . */
-int create_v_pri(v_pri,buf,address)
-     register struct iso9660_vd_pri *v_pri;
-     register char* buf;
-     register unsigned long address;
-{
-  struct dir_record *dir;
-
-  v_pri->vd_type = buf[0];
-  memcpy(v_pri->standard_id,buf + 1,sizeof(v_pri->standard_id));
-  v_pri->vd_version = buf[6];
-  memcpy(v_pri->system_id,buf + 8,sizeof(v_pri->system_id));
-  memcpy(v_pri->volume_id,buf + 40,sizeof(v_pri->volume_id));
-  memcpy(&v_pri->volume_space_size_l,buf + 80,
-        sizeof(v_pri->volume_space_size_l));
-  memcpy(&v_pri->volume_space_size_m,buf + 84,
-        sizeof(v_pri->volume_space_size_m));
-  memcpy(&v_pri->volume_set_size,buf + 120,sizeof(v_pri->volume_set_size));
-  memcpy(&v_pri->volume_sequence_number,buf + 124,
-        sizeof(v_pri->volume_sequence_number));
-  memcpy(&v_pri->logical_block_size_l,buf + 128,
-        sizeof(v_pri->logical_block_size_l));
-  memcpy(&v_pri->logical_block_size_m,buf + 130,
-        sizeof(v_pri->logical_block_size_m));
-  memcpy(&v_pri->path_table_size_l,buf + 132,
-        sizeof(v_pri->path_table_size_l));
-  memcpy(&v_pri->path_table_size_m,buf + 136,
-        sizeof(v_pri->path_table_size_m));
-  memcpy(&v_pri->loc_l_occ_path_table,buf + 140,
-        sizeof(v_pri->loc_l_occ_path_table));
-  memcpy(&v_pri->loc_opt_l_occ_path_table,buf + 144,
-        sizeof(v_pri->loc_opt_l_occ_path_table));
-  memcpy(&v_pri->loc_m_occ_path_table, buf + 148,
-        sizeof(v_pri->loc_m_occ_path_table));
-  memcpy(&v_pri->loc_opt_m_occ_path_table,buf + 152,
-        sizeof(v_pri->loc_opt_m_occ_path_table));
-
-  dir = get_free_dir_record();
-  if (dir == NULL) return EINVAL;
-  create_dir_record(dir,buf + 156,(u32_t)(address + 156));
-  v_pri->dir_rec_root = dir;
-  dir->d_ino_nr = ROOT_INO_NR;
-
-  memcpy(v_pri->volume_set_id,buf + 190,sizeof(v_pri->volume_set_id));
-  memcpy(v_pri->publisher_id,buf + 318,sizeof(v_pri->publisher_id));
-  memcpy(v_pri->data_preparer_id,buf + 446,sizeof(v_pri->data_preparer_id));
-  memcpy(v_pri->application_id,buf + 574,sizeof(v_pri->application_id));
-  memcpy(v_pri->copyright_file_id,buf + 702,sizeof(v_pri->copyright_file_id));
-  memcpy(v_pri->abstract_file_id,buf + 739,sizeof(v_pri->abstract_file_id));
-  memcpy(v_pri->bibl_file_id,buf + 776,sizeof(v_pri->bibl_file_id));
-  memcpy(v_pri->volume_cre_date,buf + 813,sizeof(v_pri->volume_cre_date));
-  memcpy(v_pri->volume_mod_date,buf + 830,sizeof(v_pri->volume_mod_date));
-  memcpy(v_pri->volume_exp_date,buf + 847,sizeof(v_pri->volume_exp_date));
-  memcpy(v_pri->volume_eff_date,buf + 864,sizeof(v_pri->volume_eff_date));
-  v_pri->file_struct_ver = buf[881];
-  return OK;
+       return OK;
 }
 
-/* This function reads from a ISO9660 filesystem (in the device dev) the
- * super block and saves it in v_pri. */
-int read_vds(
-  register struct iso9660_vd_pri *v_pri,
-  register dev_t dev
-)
+int create_vol_pri_desc(struct iso9660_vol_pri_desc *vol_pri, char *buf,
+       size_t address)
 {
-  u64_t offset;
-  int vol_ok = FALSE;
-  int r;
-  static char sbbuf[ISO9660_MIN_BLOCK_SIZE];
-  int i = 0;
+       /*
+        * This function fullfill the super block data structure using the
+        * information contained in the buffer.
+        */
+       struct iso9660_dir_record *root_record;
+       struct inode *root;
+       struct dir_extent *extent;
+
+       if (vol_pri->i_count > 0)
+               release_vol_pri_desc(vol_pri);
+
+       memcpy(vol_pri, buf, 2048);
 
-  offset = ((u64_t)(ISO9660_SUPER_BLOCK_POSITION));
-  while (!vol_ok && i++<MAX_ATTEMPTS) {
+       /* Check various fields for consistency. */
+       if ((memcmp(vol_pri->standard_id, "CD001", ISO9660_SIZE_STANDARD_ID) != 0) ||
+           (vol_pri->vd_version != 1) ||
+           (vol_pri->logical_block_size_l < 2048) ||
+           (vol_pri->file_struct_ver != 1))
+               return EINVAL;
 
-    /* Read the sector of the super block. */
-    r = bdev_read(dev, offset, sbbuf, ISO9660_MIN_BLOCK_SIZE, BDEV_NOFLAGS);
+       lmfs_set_blocksize(vol_pri->logical_block_size_l, major(fs_dev));
 
-    if (r != ISO9660_MIN_BLOCK_SIZE) /* Damaged sector or what? */
-      continue;
+       /* Read root directory record. */
+       root_record = (struct iso9660_dir_record *)vol_pri->root_directory;
+       root = alloc_inode();
+       extent = alloc_extent();
 
-    if ((sbbuf[0] & BYTE) == VD_PRIMARY) {
-      create_v_pri(v_pri,sbbuf,offset); /* copy the buffer in the data structure. */
-    }
+       extent->location = root_record->loc_extent_l + root_record->ext_attr_rec_length;
+       extent->length = root_record->data_length_l / vol_pri->logical_block_size_l;
+       if (root_record->data_length_l % vol_pri->logical_block_size_l)
+               extent->length++;
 
-    if ((sbbuf[0] & BYTE) == VD_SET_TERM)
-      /* I dont need to save anything about it */
-      vol_ok = TRUE;
+       if (read_inode(root, extent, 0, NULL) != OK) {
+               free_extent(extent);
+               put_inode(root);
+               return EINVAL;
+       }
 
-    offset += ISO9660_MIN_BLOCK_SIZE;
-  }
+       free_extent(extent);
+       vol_pri->inode_root = root;
+       vol_pri->i_count = 1;
 
-  if (vol_ok == FALSE)
-    return EINVAL;             /* If no superblock was found... */
-  else
-    return OK;                 /* otherwise. */
+       return OK;
 }
+
+int read_vds(struct iso9660_vol_pri_desc *vol_pri, dev_t dev)
+{
+       /*
+        * This function reads from a ISO9660 filesystem (in the device dev) the
+        * super block and saves it in vol_pri.
+        */
+       size_t offset;
+       int vol_ok = FALSE, vol_pri_flag = FALSE;
+       int r;
+       static char sbbuf[ISO9660_MIN_BLOCK_SIZE];
+       int i = 0;
+
+       for(offset = ISO9660_SUPER_BLOCK_POSITION; !vol_ok && i++ < MAX_ATTEMPTS;
+           offset += ISO9660_MIN_BLOCK_SIZE) {
+               /* Read the sector of the super block. */
+               r = bdev_read(dev, offset, sbbuf, ISO9660_MIN_BLOCK_SIZE, BDEV_NOFLAGS);
+
+               if (r != ISO9660_MIN_BLOCK_SIZE) {
+                       /* Damaged sector or what? */
+                       return EINVAL;
+               }
+
+               if ((sbbuf[0] & BYTE) == VD_PRIMARY) {
+                       /* Copy the buffer in the data structure. */
+                       if (create_vol_pri_desc(vol_pri, sbbuf, offset) == OK) {
+                               vol_pri_flag = TRUE;
+                       }
+               }
+
+               if ((sbbuf[0] & BYTE) == VD_SET_TERM) {
+                       /* I dont need to save anything about it */
+                       vol_ok = TRUE;
+               }
+       }
+
+       if (vol_ok == FALSE || vol_pri_flag == FALSE)
+               return EINVAL;          /* If no superblock was found... */
+       else
+               return OK;              /* otherwise. */
+}
+
index 363fe350beaf114fc51d569135d053d8c5a38a07..9ace51aa2e0194d7502ac63a30fad14ebe9ff57c 100644 (file)
@@ -1,4 +1,4 @@
-/* This file contains the definitions of a ISO9660 structures */
+/* This file contains the definitions of ISO9660 volume descriptors. */
 #include "inode.h"
 
 #define VD_BOOT_RECORD 0
@@ -7,42 +7,57 @@
 #define VD_PART 3
 #define VD_SET_TERM 255
 
-#define MAX_ATTEMPTS 20        /* # attempts to read the volume descriptors.
-                                * After it gives up */
-#define ROOT_INO_NR 1
+#define MAX_ATTEMPTS 20         /* # attempts to read the volume descriptors.
+                                 * After it gives up */
+
+/* Structure for the primary volume descriptor. */
+struct iso9660_vol_pri_desc {
+       /*
+        * On-disk structure format of the primary volume descriptor,
+        * 2048 bytes long. See ISO specs for details.
+        */
+       u8_t vd_type;
+       char standard_id[ISO9660_SIZE_STANDARD_ID];
+       u8_t vd_version;
+       u8_t pad1;
+       char system_id[ISO9660_SIZE_SYS_ID];
+       char volume_id[ISO9660_SIZE_VOLUME_ID];
+       u8_t pad2[8];
+       u32_t volume_space_size_l;
+       u32_t volume_space_size_m;
+       u8_t pad3[32];
+       u16_t volume_set_size_l;
+       u16_t volume_set_size_m;
+       u16_t volume_sequence_number_l;
+       u16_t volume_sequence_number_m;
+       u16_t logical_block_size_l;
+       u16_t logical_block_size_m;
+       u32_t path_table_size_l;
+       u32_t path_table_size_m;
+       u32_t loc_l_occ_path_table;
+       u32_t loc_opt_l_occ_path_table;
+       u32_t loc_m_occ_path_table;
+       u32_t loc_opt_m_occ_path_table;
+       u8_t root_directory[34];
+       char volume_set_id[ISO9660_SIZE_VOLUME_SET_ID];
+       char publisher_id[ISO9660_SIZE_PUBLISHER_ID];
+       char data_preparer_id[ISO9660_SIZE_DATA_PREP_ID];
+       char application_id[ISO9660_SIZE_APPL_ID];
+       char copyright_file_id[ISO9660_SIZE_COPYRIGHT_FILE_ID];
+       char abstract_file_id[ISO9660_SIZE_ABSTRACT_FILE_ID];
+       char bibl_file_id[ISO9660_SIZE_BIBL_FILE_ID];
+       char volume_cre_date[ISO9660_SIZE_DATE17];
+       char volume_mod_date[ISO9660_SIZE_DATE17];
+       char volume_exp_date[ISO9660_SIZE_DATE17];
+       char volume_eff_date[ISO9660_SIZE_DATE17];
+       u8_t file_struct_ver;
+       u8_t reserved1;
+       u8_t application_use[512];
+       u8_t reserved2[652];
+
+       /* End of the on-disk structure format. */
+
+       struct inode *inode_root;
+       int i_count;
+} __attribute__((packed)) v_pri;
 
-/* Structure for the primary volume descriptor */
-struct iso9660_vd_pri {
-  u8_t vd_type;
-  char standard_id[ISO9660_SIZE_STANDARD_ID];
-  u8_t vd_version;
-  char system_id[ISO9660_SIZE_SYS_ID];
-  char volume_id[ISO9660_SIZE_VOLUME_ID];
-  u32_t volume_space_size_l;
-  u32_t volume_space_size_m;
-  u32_t volume_set_size;
-  u32_t volume_sequence_number;
-  u16_t logical_block_size_l;
-  u16_t logical_block_size_m;
-  u32_t path_table_size_l;
-  u32_t path_table_size_m;
-  u32_t loc_l_occ_path_table;
-  u32_t loc_opt_l_occ_path_table;
-  u32_t loc_m_occ_path_table;
-  u32_t loc_opt_m_occ_path_table;
-  struct dir_record *dir_rec_root;
-  char volume_set_id[ISO9660_SIZE_VOLUME_SET_ID];
-  char publisher_id[ISO9660_SIZE_PUBLISHER_ID];
-  char data_preparer_id[ISO9660_SIZE_DATA_PREP_ID];
-  char application_id[ISO9660_SIZE_APPL_ID];
-  char copyright_file_id[ISO9660_SIZE_COPYRIGHT_FILE_ID];
-  char abstract_file_id[ISO9660_SIZE_ABSTRACT_FILE_ID];
-  char bibl_file_id[ISO9660_SIZE_BIBL_FILE_ID];
-  char volume_cre_date[ISO9660_SIZE_VOL_CRE_DATE];
-  char volume_mod_date[ISO9660_SIZE_VOL_MOD_DATE];
-  char volume_exp_date[ISO9660_SIZE_VOL_EXP_DATE];
-  char volume_eff_date[ISO9660_SIZE_VOL_EFF_DATE];
-  u8_t file_struct_ver;
-  /* The rest is either not specified or reserved */
-  u8_t count;
-} v_pri;
diff --git a/minix/fs/iso9660fs/susp.c b/minix/fs/iso9660fs/susp.c
new file mode 100644 (file)
index 0000000..034f9d5
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * This file contains support for System Use Sharing Protocol (SUSP) extension
+ * to ISO 9660.
+ */
+
+#include "inc.h"
+#include <sys/stat.h>
+
+int parse_susp(struct rrii_dir_record *dir, char *buffer)
+{
+       /* Parse fundamental SUSP entries */
+       char susp_signature[2];
+       u8_t susp_length;
+       u8_t susp_version;
+
+       u32_t ca_block_nr;
+       u32_t ca_offset;
+       u32_t ca_length;
+       struct buf *ca_bp;
+
+       susp_signature[0] = buffer[0];
+       susp_signature[1] = buffer[1];
+       susp_length = *((u8_t*)buffer + 2);
+       susp_version = *((u8_t*)buffer + 3);
+
+       if ((susp_signature[0] == 'C') && (susp_signature[1] == 'E') &&
+           (susp_length >= 28) && (susp_version >= 1)) {
+               /*
+                * Continuation area, perform a recursion.
+                *
+                * FIXME: Currently we're parsing only first logical block of a
+                * continuation area, and infinite recursion is not checked.
+                */
+
+               ca_block_nr = *((u32_t*)(buffer + 4));
+               ca_offset = *((u32_t*)(buffer + 12));
+               ca_length = *((u32_t*)(buffer + 20));
+
+               /* Truncate continuation area to fit one logical block. */
+               if (ca_offset >= v_pri.logical_block_size_l) {
+                       return EINVAL;
+               }
+               if (ca_offset + ca_length > v_pri.logical_block_size_l) {
+                       ca_length = v_pri.logical_block_size_l - ca_offset;
+               }
+
+               ca_bp = get_block(ca_block_nr);
+               if (ca_bp == NULL) {
+                       return EINVAL;
+               }
+
+               parse_susp_buffer(dir, b_data(ca_bp) + ca_offset, ca_length);
+               put_block(ca_bp);
+
+               return OK;
+       }
+       else if ((susp_signature[0] == 'P') && (susp_signature[1] == 'D')) {
+               /* Padding, skip. */
+               return OK;
+       }
+       else if ((susp_signature[0] == 'S') && (susp_signature[1] == 'P')) {
+               /* Ignored, skip. */
+               return OK;
+       }
+       else if ((susp_signature[0] == 'S') && (susp_signature[1] == 'T')) {
+               /* Terminator entry, stop processing. */
+               return(ECANCELED);
+       }
+       else if ((susp_signature[0] == 'E') && (susp_signature[1] == 'R')) {
+               /* Ignored, skip. */
+               return OK;
+       }
+       else if ((susp_signature[0] == 'E') && (susp_signature[1] == 'S')) {
+               /* Ignored, skip. */
+               return OK;
+       }
+
+       /* Not a SUSP fundamental entry. */
+       return EINVAL;
+}
+
+void parse_susp_buffer(struct rrii_dir_record *dir, char *buffer, u32_t size)
+{
+       /*
+        * Parse a SUSP system use entry for the ISO 9660.
+        * This is the main entry point for parsing SUSP data : SUSP entries are
+        * routed from here to the relevant handling functions.
+        */
+       char susp_signature[2];
+       u8_t susp_length;
+
+       int parser_return;
+
+       while (TRUE) {
+               /* A SUSP entry can't be smaller than 4 bytes. */
+               if (size < 4)
+                       return;
+
+               susp_signature[0] = buffer[0];
+               susp_signature[1] = buffer[1];
+               susp_length = *((u8_t*)buffer + 2);
+
+               /* Check if SUSP entry is present. */
+               if (((susp_signature[0] == 0) && (susp_signature[1] == 0)) ||
+                   (susp_length > size) || (susp_length < 4))
+                       return;
+
+               /* Check for SUSP fundamental entry. */
+               parser_return = parse_susp(dir, buffer);
+               if (parser_return == ECANCELED)
+                       return;
+               else if (parser_return == OK)
+                       goto next_entry;
+
+               /* Check for Rock Ridge entry. */
+               if (opt.norock == FALSE) {
+                       parser_return = parse_susp_rock_ridge(dir, buffer);
+                       if (parser_return == ECANCELED)
+                               return;
+                       else if (parser_return == OK)
+                               goto next_entry;
+               }
+
+               /* Parse next SUSP entry. */
+       next_entry:
+               buffer += susp_length;
+               size -= susp_length;
+       }
+}
+
diff --git a/minix/fs/iso9660fs/susp_rock_ridge.c b/minix/fs/iso9660fs/susp_rock_ridge.c
new file mode 100644 (file)
index 0000000..d68bb94
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * This file contains support for Rock Ridge Interchange Protocol (RRIP)
+ * extension to ISO 9660.
+ */
+
+#include "inc.h"
+#include <sys/stat.h>
+
+void parse_susp_rock_ridge_sl(struct rrii_dir_record *dir, char *buffer, int length)
+{
+       /* Parse a Rock Ridge SUSP symbolic link entry (SL). */
+       int offset = 0;
+       int slink_size;
+       u8_t flags, component_length;
+
+       while (offset + 2 <= length) {
+               flags = *((u8_t*)(buffer + offset));
+               component_length = *((u8_t*)(buffer + offset + 1));
+
+               /* Add directory separator if necessary. */
+               if (dir->slink_rrip[0] != '\0') {
+                       slink_size = strlen(dir->slink_rrip);
+                       if (slink_size + 2 >= ISO9660_RRIP_MAX_FILE_ID_LEN)
+                               return;
+
+                       dir->slink_rrip[slink_size] = '/';
+                       slink_size++;
+               }
+               else
+                       slink_size = strlen(dir->slink_rrip);
+
+               switch (flags & 0xF) {
+                       case 0:
+                       case 1: {
+                               /*
+                                * Directory path component.
+                                * Check if component fits within SL entry and
+                                * within symbolic link field.
+                                */
+                               if ((component_length > length - offset) ||
+                                   (slink_size + component_length + 1 >=
+                                   ISO9660_RRIP_MAX_FILE_ID_LEN)) {
+                                       return;
+                               }
+
+                               strlcpy(dir->slink_rrip + slink_size,
+                                   buffer + offset + 2, component_length+1);
+
+                               break;
+                       }
+                       case 2: {
+                               /* Current directory path component. */
+                               if (slink_size + 2 >=
+                                   ISO9660_RRIP_MAX_FILE_ID_LEN) {
+                                       return;
+                               }
+
+                               strcat(dir->slink_rrip + slink_size, ".");
+
+                               break;
+                       }
+                       case 4: {
+                               /* Parent directory path component. */
+                               if (slink_size + 3 >=
+                                   ISO9660_RRIP_MAX_FILE_ID_LEN) {
+                                       return;
+                               }
+
+                               strcat(dir->slink_rrip + slink_size, "..");
+
+                               break;
+                       }
+                       case 8: {
+                               /* Root directory path component relative to
+                                  the current process. */
+                               if (slink_size + 2 >=
+                                   ISO9660_RRIP_MAX_FILE_ID_LEN) {
+                                       return;
+                               }
+
+                               strcat(dir->slink_rrip + slink_size, "/");
+
+                               break;
+                       }
+                       default: {
+                               /* Unsupported/invalid flags. */
+                               return;
+                       }
+               }
+
+               offset += component_length + 2;
+       }
+}
+
+int parse_susp_rock_ridge(struct rrii_dir_record *dir, char *buffer)
+{
+       /* Parse Rock Ridge SUSP entries for a directory entry. */
+       char susp_signature[2];
+       u8_t susp_length;
+       u8_t susp_version;
+
+       int rrii_name_current_size;
+       int rrii_name_append_size;
+       int rrii_tf_flags;
+       int rrii_tf_offset;
+       u32_t rrii_pn_rdev_major;
+       u32_t rrii_pn_rdev_minor;
+       mode_t rrii_px_posix_mode;
+
+       susp_signature[0] = buffer[0];
+       susp_signature[1] = buffer[1];
+       susp_length = *((u8_t*)buffer + 2);
+       susp_version = *((u8_t*)buffer + 3);
+
+       if ((susp_signature[0] == 'P') && (susp_signature[1] == 'X') &&
+           (susp_length >= 36) && (susp_version >= 1)) {
+               /* POSIX file mode, UID and GID. */
+               rrii_px_posix_mode = *((u32_t*)(buffer + 4));
+
+               /* Check if file mode is supported by isofs. */
+               switch (rrii_px_posix_mode & _S_IFMT) {
+                       case S_IFCHR:
+                       case S_IFBLK:
+                       case S_IFREG:
+                       case S_IFDIR:
+                       case S_IFLNK: {
+                               dir->d_mode = rrii_px_posix_mode & _S_IFMT;
+                               break;
+                       }
+                       default: {
+                               /* Fall back to what ISO 9660 said. */
+                               dir->d_mode &= _S_IFMT;
+                               break;
+                       }
+               }
+
+               dir->d_mode |= rrii_px_posix_mode & 07777;
+               dir->uid = *((u32_t*)(buffer + 20));
+               dir->gid = *((u32_t*)(buffer + 28));
+
+               return OK;
+       }
+       else if ((susp_signature[0] == 'P') && (susp_signature[1] == 'N') &&
+                (susp_length >= 20) && (susp_version >= 1)) {
+               /* Device ID (for character or block special inode). */
+               rrii_pn_rdev_major = *((u32_t*)(buffer + 4));
+               rrii_pn_rdev_minor = *((u32_t*)(buffer + 12));
+
+               dir->rdev = makedev(rrii_pn_rdev_major, rrii_pn_rdev_minor);
+
+               return OK;
+       }
+       else if ((susp_signature[0] == 'S') && (susp_signature[1] == 'L') &&
+                (susp_length > 5) && (susp_version >= 1)) {
+               /* Symbolic link target. Multiple entries may be used to
+                  concatenate the complete path target. */
+               parse_susp_rock_ridge_sl(dir, buffer + 5, susp_length - 5);
+
+               return OK;
+       }
+       else if ((susp_signature[0] == 'N') && (susp_signature[1] == 'M') &&
+                (susp_length > 5) && (susp_version >= 1)) {
+               /* Alternate POSIX name. Multiple entries may be used to
+                  concatenate the complete filename. */
+               rrii_name_current_size = strlen(dir->file_id_rrip);
+               rrii_name_append_size = susp_length - 5;
+
+               /* Concatenate only if name component fits. */
+               if (rrii_name_current_size + rrii_name_append_size + 1 <
+                   ISO9660_RRIP_MAX_FILE_ID_LEN) {
+                       strlcpy(dir->file_id_rrip + rrii_name_current_size,
+                           buffer + 5, rrii_name_append_size+1);
+               }
+
+               return OK;
+       }
+       else if ((susp_signature[0] == 'C') && (susp_signature[1] == 'L')) {
+               /* Ignored, skip. */
+               return OK;
+       }
+       else if ((susp_signature[0] == 'P') && (susp_signature[1] == 'L')) {
+               /* Ignored, skip. */
+               return OK;
+       }
+       else if ((susp_signature[0] == 'R') && (susp_signature[1] == 'E')) {
+               /* Ignored, skip. */
+               return OK;
+       }
+       else if ((susp_signature[0] == 'T') && (susp_signature[1] == 'F') &&
+                (susp_length >= 5) && (susp_version >= 1)) {
+               /* POSIX timestamp. */
+               rrii_tf_flags = buffer[5];
+               rrii_tf_offset = 5;
+
+               /*
+                * ISO 9660 17-byte time format.
+                * FIXME: 17-byte time format not supported in TF entry.
+                */
+               if (rrii_tf_flags & (1 << 7)) { }
+
+               /* ISO 9660 7-byte time format. */
+               else {
+                       /* Creation time  */
+                       if ((rrii_tf_flags & (1 << 0)) &&
+                           (rrii_tf_offset + ISO9660_SIZE_DATE7 <= susp_length)) {
+                               memcpy(dir->birthtime, buffer+rrii_tf_offset,
+                                      ISO9660_SIZE_DATE7);
+                               rrii_tf_offset += ISO9660_SIZE_DATE7;
+                       }
+
+                       /* Modification time */
+                       if ((rrii_tf_flags & (1 << 1)) &&
+                           (rrii_tf_offset + ISO9660_SIZE_DATE7 <= susp_length)) {
+                               memcpy(dir->mtime, buffer+rrii_tf_offset,
+                                      ISO9660_SIZE_DATE7);
+                               rrii_tf_offset += ISO9660_SIZE_DATE7;
+                       }
+
+                       /* Last access time. */
+                       if ((rrii_tf_flags & (1 << 2)) &&
+                           (rrii_tf_offset + ISO9660_SIZE_DATE7 <= susp_length)) {
+                               memcpy(dir->atime, buffer+rrii_tf_offset,
+                                      ISO9660_SIZE_DATE7);
+                               rrii_tf_offset += ISO9660_SIZE_DATE7;
+                       }
+
+                       /* Last attribute change time. */
+                       if ((rrii_tf_flags & (1 << 3)) &&
+                           (rrii_tf_offset + ISO9660_SIZE_DATE7 <= susp_length)) {
+                               memcpy(dir->ctime, buffer+rrii_tf_offset,
+                                      ISO9660_SIZE_DATE7);
+                               rrii_tf_offset += ISO9660_SIZE_DATE7;
+                       }
+
+                       /* The rest is ignored. */
+               }
+
+               return OK;
+       }
+       else if ((susp_signature[0] == 'S') && (susp_signature[1] == 'F')) {
+               /* Ignored, skip. */
+               return OK;
+       }
+
+       /* Not a Rock Ridge entry. */
+       return EINVAL;
+}
+
index 6f9297c519b39dc299b9a0eba698b49cdb03224f..5a5cf1ba302ccb61ac9c2f390738849af8de1fcd 100644 (file)
@@ -1,5 +1,6 @@
 
-/* This file contains the table used to map system call numbers onto the
+/*
+ * This file contains the table used to map system call numbers onto the
  * routines that perform them.
  */
 
@@ -8,43 +9,39 @@
 #include "inc.h"
 
 int (*fs_call_vec[])(void) = {
-  no_sys,                      /* 0: not used */
-  no_sys,                      /* 1: not used */
-  fs_putnode,                  /* 2 */
-  no_sys,                      /* 3: not used */
-  no_sys,                      /* 4: not used */
-  no_sys,                      /* 5: not used */
-  no_sys,                      /* 6: not used */
-  do_noop,                     /* 7 */
-  fs_stat,                     /* 8 */
-  no_sys,                      /* 9: not used */
-  fs_statvfs,                  /* 10 */
-  fs_bread,                    /* 11 */
-  no_sys,                      /* 12: not used */
-  no_sys,                      /* 13: not used */
-  no_sys,                      /* 14: not used */
-  fs_unmount,                  /* 15 */
-  fs_sync,                     /* 16 */
-  fs_new_driver,               /* 17 */
-  no_sys,                      /* 18: not_used */
-  fs_read,                     /* 19 */
-  no_sys,                      /* 20: not used */
-  no_sys,                      /* 21: not used */
-  no_sys,                      /* 22: not used */
-  no_sys,                      /* 23: not used */
-  no_sys,                      /* 24: not used */
-  no_sys,                      /* 25: not used */
-  fs_lookup,                   /* 26 */
-  fs_mountpoint,               /* 27 */
-  fs_readsuper,                        /* 28 */
-  no_sys,                      /* 29: not used */
-  no_sys,                      /* 30: not used */
-  fs_getdents,                 /* 31 */
-#if 0
-  fs_read,                     /* 32 */
-  no_sys,                      /* 33 */
-#else
-  no_sys,                      /* 32 */
-  no_sys,                      /* 33 */
-#endif
-};
+       no_sys,                       /* 0: not used */
+       no_sys,                       /* 1: not used */
+       fs_putnode,                   /* 2 */
+       no_sys,                       /* 3: not used */
+       no_sys,                       /* 4: not used */
+       no_sys,                       /* 5: not used */
+       no_sys,                       /* 6: not used */
+       do_noop,                      /* 7 */
+       fs_stat,                      /* 8 */
+       no_sys,                       /* 9: not used */
+       fs_statvfs,                   /* 10 */
+       fs_bread,                     /* 11 */
+       no_sys,                       /* 12: not used */
+       no_sys,                       /* 13: not used */
+       no_sys,                       /* 14: not used */
+       fs_unmount,                   /* 15 */
+       fs_sync,                      /* 16 */
+       fs_new_driver,                /* 17 */
+       no_sys,                       /* 18: not_used */
+       fs_read,                      /* 19 */
+       no_sys,                       /* 20: not used */
+       no_sys,                       /* 21: not used */
+       no_sys,                       /* 22: not used */
+       no_sys,                       /* 23: not used */
+       no_sys,                       /* 24: not used */
+       no_sys,                       /* 25: not used */
+       fs_lookup,                    /* 26 */
+       fs_mountpoint,                /* 27 */
+       fs_readsuper,                 /* 28 */
+       no_sys,                       /* 29: not used */
+       fs_rdlink,                    /* 30  */
+       fs_getdents,                  /* 31 */
+       no_sys,                       /* 32 */
+       no_sys,                       /* 33 */
+} ;
+
index d62b75eb797ba2f6efb630878668ab4b64837808..5a7e0240783f0f2e04d96fadf3df9b7abb0e5f1b 100644 (file)
@@ -5,21 +5,99 @@
 #include <minix/callnr.h>
 #include <minix/vfsif.h>
 
-/*===========================================================================*
- *                             do_noop                                      *
- *===========================================================================*/
+static struct dir_extent dir_extents[NR_DIR_EXTENT_RECORDS];
+
+struct dir_extent* alloc_extent()
+{
+       /* Return a free extent from the pool. */
+       int i;
+       struct dir_extent *extent;
+
+       for (i = 0; i < NR_DIR_EXTENT_RECORDS; i++) {
+               extent = &dir_extents[i];
+
+               if (extent->in_use == 0) {
+                       memset(extent, 0, sizeof(*extent));
+                       extent->in_use = 1;
+
+                       return extent;
+               }
+       }
+
+       panic("No free extents in cache");
+}
+
+void free_extent(struct dir_extent *e)
+{
+       if (e == NULL)
+               return;
+
+       if (e->in_use == 0)
+               panic("Trying to free unused extent");
+
+       free_extent(e->next);
+       e->in_use = 0;
+}
+
+struct buf* read_extent_block(struct dir_extent *e, size_t block)
+{
+       size_t block_id = get_extent_absolute_block_id(e, block);
+
+       if (block_id == 0 || block_id >= v_pri.volume_space_size_l)
+               return NULL;
+
+       return get_block(block_id);
+}
+
+size_t get_extent_absolute_block_id(struct dir_extent *e, size_t block)
+{
+       size_t extent_offset = 0;
+
+       if (e == NULL)
+               return 0;
+
+       /* Retrieve the extent on which the block lies. */
+       while(block > extent_offset + e->length) {
+               if (e->next == NULL)
+                       return 0;
+
+               extent_offset += e->length;
+               e = e->next;
+       }
+
+       return e->location + block - extent_offset;
+}
+
+time_t date7_to_time_t(const u8_t *date)
+{
+       /* This function converts from the ISO 9660 7-byte time format to a time_t. */
+       struct tm ltime;
+       signed char time_zone = (signed char)date[6];
+
+       ltime.tm_year = date[0];
+       ltime.tm_mon = date[1] - 1;
+       ltime.tm_mday = date[2];
+       ltime.tm_hour = date[3];
+       ltime.tm_min = date[4];
+       ltime.tm_sec = date[5];
+       ltime.tm_isdst = 0;
+
+       /* Offset from Greenwich Mean Time */
+       if (time_zone >= -52 && time_zone <= 52)
+               ltime.tm_hour += time_zone;
+
+       return mktime(&ltime);
+}
+
 int do_noop(void)
 {
-/* Do not do anything. */
-  return(OK);
+       /* Do not do anything. */
+       return OK;
 }
 
-/*===========================================================================*
- *                             no_sys                                       *
- *===========================================================================*/
 int no_sys(void)
 {
-/* Somebody has used an illegal system call number */
-  return(EINVAL);
+       /* Somebody has used an illegal system call number */
+       return EINVAL;
 }