Hi,

I have attached a patch that enables support for multiple discs in
HostFS.

I have modified the emulator to create three discs (on Unix, only two on
Windows):
HostFS::HostFS.$  - the standard HostFS directory
HostFS::system.$  - The root of the host (/ under Unix, c:/ under Win)
HostFS::home.$    - ~/rpcemu (Unix only)
I have also left backwards compatibility, so that HostFS:$ works as
expected with hostfsfiler.

My reasoning is that if rpcemu is installed on a shared machine, then
people may want personal, writable disc space on the host without the
need to understand NFS or other networking services.  HostFS::HostFS.$
may also be a read only file system to prevent people from accidentally
breaking the system.

I have kept HostFS::system.$ as a read only file system as some RISC OS
apps change the filetype of files they have successfully loaded.  This
has the unfortunate side effect of the file being renamed on the host -
which is probably not what the user wants in the average case.

Obviously, hostfsfiler does not handle any of this, so to access system
or home, you have to either do something like: "filer_opendir
HostFS::system.$" or "addtinydir HostFS::system.$".

It's more of an opening gambit of a patch, really.  I'd be interested in
any comments.

James
Index: hostfs.c
===================================================================
--- hostfs.c	(revision 137)
+++ hostfs.c	(working copy)
@@ -74,13 +74,13 @@
   ARMword exec;
   ARMword length;
   ARMword attribs;
+  HOSTFS_Discs *disc_info;
 } risc_os_object_info;
 
 /* TODO Avoid duplicate macro with extnrom.c */
 #define ROUND_UP_TO_4(x) (((x) + 3) & (~3))
 
-char HOSTFS_ROOT[512];
-//#define HOSTFS_ROOT "./hostfs"
+HOSTFS_Discs hostfs_discs[10];
 
 #define MAX_OPEN_FILES 255
 
@@ -110,6 +110,20 @@
 }
 #endif
 
+static HOSTFS_Discs *get_hostfs_disc_info(const char *disc_name)
+{
+    unsigned int i;
+    for (i = 0; i < sizeof(hostfs_discs) / sizeof(HOSTFS_Discs); i++)
+    {
+       if (strlen(hostfs_discs[i].disc_name) == 0)
+          break;
+       if (strcmp(disc_name, hostfs_discs[i].disc_name) == 0)
+          return &hostfs_discs[i];
+    }
+
+    return &hostfs_discs[0];
+}
+
 /**
  * @param buffer_size_needed Required buffer
  */
@@ -257,7 +271,6 @@
 static void
 name_host_to_riscos(const char *object_name, size_t len, char *riscos_name)
 {
-        char *s=riscos_name,*s2=object_name;
   assert(object_name);
   assert(riscos_name);
 
@@ -291,7 +304,8 @@
 static void
 hostfs_read_object_info(const char *host_pathname,
                         char *ro_leaf,
-                        risc_os_object_info *object_info)
+                        risc_os_object_info *object_info,
+                        HOSTFS_Discs *disc_info)
 {
   struct stat info;
   ARMword file_type;
@@ -305,6 +319,7 @@
   assert(ro_leaf);
   assert(object_info);
 
+  object_info->disc_info = disc_info;
   if (stat(host_pathname, &info)) {
     /* Error reading info about the object */
 
@@ -417,7 +432,8 @@
                  int case_sensitive,
                  char *host_name,
                  char *ro_leaf,
-                 risc_os_object_info *object_info)
+                 risc_os_object_info *object_info,
+                 HOSTFS_Discs *disc_info)
 {
   DIR *d;
   struct dirent *entry;
@@ -427,6 +443,7 @@
   assert(host_name && ro_leaf);
   assert(object_info);
 
+  object_info->disc_info = disc_info;
   d = opendir(host_dir_path);
   if (!d) {
     switch (errno) {
@@ -456,7 +473,7 @@
     strcat(entry_path, "/");
     strcat(entry_path, entry->d_name);
 
-    hostfs_read_object_info(entry_path, ro_leaf, object_info);
+    hostfs_read_object_info(entry_path, ro_leaf, object_info, disc_info);
 
     /* Ignore entries we can not read information about,
        or which are neither regular files or directories */
@@ -514,12 +531,15 @@
   char component_name[PATH_MAX]; /* working Host component */
   char *component;
   const char *ro_path_orig = ro_path;
+  char disc_name[80] = "HostFS";
+  char *p;
+  HOSTFS_Discs *hostfs_disc_info = NULL;
 
   assert(ro_path);
   assert(host_pathname && ro_leaf);
   assert(object_info);
 
-  assert(ro_path[0] == '$');
+  assert(ro_path[0] == '$' || ro_path[0] == ':');
 
   /* Initialise Host pathname */
   host_pathname[0] = '\0';
@@ -532,10 +552,30 @@
   while (*ro_path) {
                 //rpclog("%i %c\n",*ro_path,*ro_path);
     switch (*ro_path) {
+    case ':':
+      p = strchr(ro_path, '$');
+      if (!p) {
+        object_info->type = OBJECT_TYPE_NOT_FOUND;
+        dbug_hostfs("DISC NOT FOUND %s %s\n",host_pathname,ro_leaf);
+        return;
+      }
+      p--;
+      if (*p != '.') {
+        object_info->type = OBJECT_TYPE_NOT_FOUND;
+        dbug_hostfs("DISC NOT FOUND %s %s\n",host_pathname,ro_leaf);
+        return;
+      }
+      ro_path++;
+      memset(disc_name, 0, sizeof(disc_name));
+      strncpy(disc_name, ro_path, p-ro_path>sizeof(disc_name)?sizeof(disc_name)-1:p-ro_path);
+
+      ro_path = p;
+      break;
     case '$':
-      strcat(host_pathname, HOSTFS_ROOT);
+      hostfs_disc_info = get_hostfs_disc_info(disc_name);
+      strcat(host_pathname, hostfs_disc_info->hostfs_root);
 
-      hostfs_read_object_info(host_pathname, ro_leaf, object_info);
+      hostfs_read_object_info(host_pathname, ro_leaf, object_info, hostfs_disc_info);
       if (object_info->type == OBJECT_TYPE_NOT_FOUND) {
                 dbug_hostfs("OBJECT NOT FOUND %s %s\n",host_pathname,ro_leaf);
         return;
@@ -552,7 +592,7 @@
         *component = '\0'; /* add terminator */
 
         hostfs_path_scan(host_pathname, component_name, 0,
-                         host_name, ro_leaf, object_info);
+                         host_name, ro_leaf, object_info, hostfs_disc_info);
         if (object_info->type == OBJECT_TYPE_NOT_FOUND) {
           /* This component of the path is invalid */
           /* Return what we have of the host_pathname */
@@ -594,7 +634,7 @@
     *component = '\0'; /* add terminator */
 
     hostfs_path_scan(host_pathname, component_name, preserve_leaf,
-                     host_name, ro_leaf, object_info);
+                     host_name, ro_leaf, object_info, hostfs_disc_info);
     if (object_info->type == OBJECT_TYPE_NOT_FOUND) {
       /* This component of the path is invalid */
       /* Return what we have of the host_pathname */
@@ -935,6 +975,7 @@
 {
   const unsigned BUFSIZE = MINIMUM_BUFFER_SIZE;
   char ro_path[PATH_MAX], host_pathname[PATH_MAX], ro_leaf[PATH_MAX];
+  char tmp_pathname[PATH_MAX];
   risc_os_object_info object_info;
   char host_path[PATH_MAX];
   FILE *f;
@@ -961,12 +1002,16 @@
   riscos_path_to_host(ro_path, host_path);
   dbug_hostfs("\tPATH2 = %s\n", host_path);
 
-  hostfs_path_process(ro_path, 0, host_pathname, ro_leaf, &object_info);
+  hostfs_path_process(ro_path, 0, tmp_pathname, ro_leaf, &object_info);
   dbug_hostfs("\tro_path = \"%s\"\n", ro_path);
   if (object_info.type != OBJECT_TYPE_NOT_FOUND) {
     dbug_hostfs("\thost_pathname = \"%s\"\n\tro_leaf = \"%s\"\n",
                 host_pathname, ro_leaf);
   }
+  if (!(object_info.disc_info && (object_info.disc_info->permissions & HOSTFS_DISC_WRITEABLE))) {
+    /* TODO handle error */
+    return;
+  }
 
   if (object_info.type == OBJECT_TYPE_DIRECTORY) {
     /* This should never occur as RISC OS checks whether a directory exists
@@ -1053,22 +1098,25 @@
     {
       char new_pathname[PATH_MAX];
 
-      path_construct(host_pathname, new_pathname, sizeof(new_pathname),
-                     state->Reg[2], state->Reg[3]);
+      if (object_info.disc_info && (object_info.disc_info->permissions & HOSTFS_DISC_WRITEABLE)) {
+        path_construct(host_pathname, new_pathname, sizeof(new_pathname),
+                       state->Reg[2], state->Reg[3]);
 
-      if (rename(host_pathname, new_pathname)) {
-        /* TODO handle error in renaming */
-      }
+        if (rename(host_pathname, new_pathname)) {
+          /* TODO handle error in renaming */
+        }
 
-      /* Update timestamp if necessary */
-      if ((state->Reg[2] & 0xfff00000u) == 0xfff00000u) {
-        struct utimbuf t;
+        /* Update timestamp if necessary */
+        if ((state->Reg[2] & 0xfff00000u) == 0xfff00000u) {
+          struct utimbuf t;
 
-        t.modtime = hostfs_adfs2host_time(state->Reg[2], state->Reg[3]);
-        t.actime = t.modtime;
-        utime(new_pathname, &t);
-        /* TODO handle error in utime() */
+          t.modtime = hostfs_adfs2host_time(state->Reg[2], state->Reg[3]);
+          t.actime = t.modtime;
+          utime(new_pathname, &t);
+          /* TODO handle error in utime() */
+        }
       }
+      /* TOD: handle permission error */
     }
 
     /* TODO handle new attribs */
@@ -1131,6 +1179,9 @@
   /* TODO Ensure we do not try to delete the root object: i.e. $ */
 
   hostfs_path_process(ro_path, 0, host_pathname, ro_leaf, &object_info);
+  if (!(object_info.disc_info && (object_info.disc_info->permissions & HOSTFS_DISC_WRITEABLE))) {
+    return;
+  }
 
   state->Reg[0] = object_info.type;
 
@@ -1170,9 +1221,12 @@
 {
   const unsigned BUFSIZE = MINIMUM_BUFFER_SIZE;
   char ro_path[PATH_MAX];
+  char ro_leaf[PATH_MAX];
   char host_path[PATH_MAX];
+  char tmp_path[PATH_MAX];
   FILE *f;
   ARMword length;
+  risc_os_object_info object_info;
 
   assert(state);
 
@@ -1192,6 +1246,11 @@
   dbug_hostfs("\tPATH = %s\n", ro_path);
   dbug_hostfs("\tPATH2 = %s\n", host_path);
 
+  hostfs_path_process(ro_path, 0, tmp_path, ro_leaf, &object_info);
+  if (!(object_info.disc_info && (object_info.disc_info->permissions & HOSTFS_DISC_WRITEABLE))) {
+    return;
+  }
+
   hostfs_ensure_buffer_size(BUFSIZE);
 
   f = fopen(host_path, "wb");
@@ -1221,7 +1280,10 @@
 hostfs_file_8_create_dir(ARMul_State *state)
 {
   char ro_path[PATH_MAX];
+  char ro_leaf[PATH_MAX];
   char host_path[PATH_MAX];
+  char tmp_path[PATH_MAX];
+  risc_os_object_info object_info;
   int s;
 
   assert(state);
@@ -1239,6 +1301,10 @@
   dbug_hostfs("\tPATH = %s\n", ro_path);
   dbug_hostfs("\tPATH2 = %s\n", host_path);
 
+  hostfs_path_process(ro_path, 0, tmp_path, ro_leaf, &object_info);
+  if (!(object_info.disc_info && (object_info.disc_info->permissions & HOSTFS_DISC_WRITEABLE))) {
+    return;
+  }
 #if defined __unix || __MACH__
   s = mkdir(host_path, 0755);
 #else
@@ -1507,7 +1573,7 @@
       strcat(entry_path, "/");
       strcat(entry_path, entry->d_name);
 
-      hostfs_read_object_info(entry_path, ro_leaf, &object_info);
+      hostfs_read_object_info(entry_path, ro_leaf, &object_info, NULL);
 
       /* Ignore entries we can not read information about,
          or which are neither regular files or directories */
@@ -1547,7 +1613,7 @@
       strcat(entry_path, "/");
       strcat(entry_path, entry->d_name);
 
-      hostfs_read_object_info(entry_path, ro_leaf, &object_info);
+      hostfs_read_object_info(entry_path, ro_leaf, &object_info, NULL);
 
       /* Ignore entries we can not read information about,
          or which are neither regular files or directories */
Index: hostfs.h
===================================================================
--- hostfs.h	(revision 137)
+++ hostfs.h	(working copy)
@@ -15,12 +15,21 @@
 #define ARCEM_SWI_NANOSLEEP (ARCEM_SWI_CHUNK + 3)
 #define ARCEM_SWI_NETWORK   (ARCEM_SWI_CHUNK + 4)
 
+#define HOSTFS_DISC_WRITEABLE	1
+#define HOSTFS_DISC_READABLE	2
+
 typedef uint32_t ARMword;
 typedef struct {
   uint32_t *Reg;
 } ARMul_State;
 
+typedef struct {
+  char disc_name[80];
+  char hostfs_root[512];
+  int permissions;
+} HOSTFS_Discs;
 
+extern HOSTFS_Discs hostfs_discs[10];
 extern void hostfs(ARMul_State *state);
 
 #define ARMul_LoadWordS(state, address) readmeml(address)
Index: rpcemu.c
===================================================================
--- rpcemu.c	(revision 137)
+++ rpcemu.c	(working copy)
@@ -19,6 +19,7 @@
 #include "cdrom-iso.h"
 #include "podulerom.h"
 #include "podules.h"
+#include "hostfs.h"
 
 int cdromtype;
 unsigned char flaglookup[16][16];
@@ -64,12 +65,25 @@
         get_executable_name(exname,511);
         p=get_filename(exname);
         *p=0;
-        append_filename(HOSTFS_ROOT,exname,"hostfs",511);
+	memset(hostfs_discs, 0, sizeof(hostfs_discs));
+	strcpy(hostfs_discs[0].disc_name, "HostFS");
+	hostfs_discs[0].permissions = HOSTFS_DISC_WRITEABLE | HOSTFS_DISC_READABLE;
+        append_filename(hostfs_discs[0].hostfs_root,exname,"hostfs",sizeof(hostfs_discs[0].hostfs_root)-1);
         for (c=0;c<511;c++)
         {
-                if (HOSTFS_ROOT[c]=='\\')
-                   HOSTFS_ROOT[c]='/';
+                if (hostfs_discs[0].hostfs_root[c]=='\\')
+                   hostfs_discs[0].hostfs_root[c]='/';
         }
+	strcpy(hostfs_discs[1].disc_name, "system");
+	hostfs_discs[1].permissions = HOSTFS_DISC_READABLE;
+#if defined(_WIN32)
+        strcpy(hostfs_discs[1].hostfs_root,"c:/");
+#elif defined(__unix__)
+        strcpy(hostfs_discs[1].hostfs_root,"/");
+	strcpy(hostfs_discs[2].disc_name, "home");
+	hostfs_discs[2].permissions = HOSTFS_DISC_READABLE | HOSTFS_DISC_WRITEABLE;
+	append_filename(hostfs_discs[2].hostfs_root, getenv("HOME"), "rpcemu", sizeof(hostfs_discs[2].hostfs_root)-1);
+#endif
         initmem();
 //printf("Mem inited...\n");
 	loadroms();
@@ -92,7 +106,6 @@
 //printf("About to init video...\n");
         initvideo();
 //printf("Video inited!\n");
-        loadconfig();
         initsound();
         reallocmem(rammask+1);
         initcodeblocks();
Index: rpc-linux.c
===================================================================
--- rpc-linux.c	(revision 137)
+++ rpc-linux.c	(working copy)
@@ -10,6 +10,7 @@
 #include "vidc20.h"
 #include "gui.h"
 
+extern void loadconfig();
 
 int mousecapture=0;
 float mips;
@@ -215,6 +216,8 @@
 
         infocus=1;
         allegro_init();
+	// load config here before anybody needs it.
+	loadconfig();
 
 	LOCK_FUNCTION(close_button_handler);
 	set_close_button_callback(close_button_handler);
@@ -223,11 +226,12 @@
         install_timer();
         install_mouse();
 
+	// Init network before startrpcemu so that we have dropped root privileges before any configuration happens
+        initnetwork();
+
         if (startrpcemu())
            return -1;
 
-        initnetwork();
-
         install_int_ex(domips,MSEC_TO_TIMER(1000));
         install_int_ex(vblupdate,BPS_TO_TIMER(refresh));
 	startsoundthread();
Index: iomd.h
===================================================================
--- iomd.h	(revision 137)
+++ iomd.h	(working copy)
@@ -36,8 +36,6 @@
 extern uint8_t readmb(void);
 extern void iomdvsync(int vsync);
 
-extern char HOSTFS_ROOT[512];
-
 extern char discname[2][260];
 extern int drawscre;
 
_______________________________________________
Rpcemu mailing list
[email protected]
http://www.riscos.info/cgi-bin/mailman/listinfo/rpcemu

Reply via email to