Hi,

Here is an updated patch that should have answered most of the queries:
1.  Discs are configured in rpc.cfg.  rpc.cfg is updated with exmaples.
2.  Discs can be referenced by name or by index
3.  There are no concept of default permissions

There is still a concept of a default disc, for use when the HostFS
module references HostFS:$.  The default disc is now HostFS::0.$.

Bugs: 
1.  you don't get an invalid disc error when referencing discs that do
not exist.  I need to fix that, really.
2.  you don't get a permission denied error when trying to create a file
on a read-only filesystem.

James
Index: cmos.ram
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: rpc.cfg
===================================================================
--- rpc.cfg	(revision 137)
+++ rpc.cfg	(working copy)
@@ -8,3 +8,13 @@
 cpu_type = SA110
 mem_size = 16
 ipaddress = 172.31.0.1
+hostfs.drive0.name = Boot
+hostfs.drive0.path = ./hostfs
+hostfs.drive0.permissions = read,write
+hostfs.drive1.name = System
+hostfs.drive1.path = /
+hostfs.drive1.permissions = read
+hostfs.drive2.name = Home
+hostfs.drive2.path = ~/rpcemu
+hostfs.drive2.permissions = read,write
+
Index: src/hostfs.c
===================================================================
--- src/hostfs.c	(revision 137)
+++ src/hostfs.c	(working copy)
@@ -28,6 +28,8 @@
 #include "mem.h"
 #include "hostfs.h"
 
+#define WANT_DEFAULT_DISC
+
 typedef int bool;
 
 #define true  ((bool) 1)
@@ -74,13 +76,14 @@
   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"
+#define MAX_HOSTFS_DISCS 10
+HOSTFS_Discs hostfs_discs[MAX_HOSTFS_DISCS];
 
 #define MAX_OPEN_FILES 255
 
@@ -110,6 +113,69 @@
 }
 #endif
 
+int hostfs_initialise()
+{
+    memset(&hostfs_discs, 0, sizeof(hostfs_discs));
+
+    return 0;
+}
+
+int add_hostfs_disc(const char *name, const char *path, const char *permissions)
+{
+    int i;
+    char *c;
+
+    for (i = 0; i < sizeof(hostfs_discs) / sizeof(HOSTFS_Discs); i++) {
+        if (strlen(hostfs_discs[i].disc_name) == 0) {
+            strncpy(hostfs_discs[i].disc_name, name, sizeof(hostfs_discs[i].disc_name)-1);
+            if (*path == '~')
+                rpcemu_os_expand_home_path(path, hostfs_discs[i].hostfs_root, sizeof(hostfs_discs[i].hostfs_root));
+            else
+                strncpy(hostfs_discs[i].hostfs_root, path, sizeof(hostfs_discs[i].hostfs_root)-1);
+            c = hostfs_discs[i].hostfs_root;
+            while (*c != '\0') {
+                if (*c == '\\') {
+                    *c = '/';
+                }
+                c++;
+            }
+            if (strstr(permissions, "read"))
+                hostfs_discs[i].permissions |= HOSTFS_DISC_READABLE;
+            if (strstr(permissions, "write"))
+                hostfs_discs[i].permissions |= HOSTFS_DISC_WRITEABLE;
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+int get_max_hostfs_discs()
+{
+    return MAX_HOSTFS_DISCS;
+}
+
+static HOSTFS_Discs *get_hostfs_disc_info_by_name(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 NULL;
+}
+
+static HOSTFS_Discs *get_hostfs_disc_info_by_index(int index)
+{
+    if (index >= MAX_HOSTFS_DISCS || index < 0)
+        return NULL;
+
+    return &hostfs_discs[index];
+}
+
 /**
  * @param buffer_size_needed Required buffer
  */
@@ -257,7 +323,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 +356,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 +371,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 +484,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 +495,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 +525,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 +583,17 @@
   char component_name[PATH_MAX]; /* working Host component */
   char *component;
   const char *ro_path_orig = ro_path;
+  char disc_name[80] = "";
+  int disc_index = -1;
+  char *p;
+  char *endptr;
+  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 +606,51 @@
   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);
+      disc_index = strtoul(disc_name, &endptr, 10);
+      if (disc_name == endptr) {
+          // disc name is a text based name, not an index
+          disc_index = -1;
+      }
+
+
+      ro_path = p;
+      break;
     case '$':
-      strcat(host_pathname, HOSTFS_ROOT);
+#ifdef WANT_DEFAULT_DISC
+      // We have neither have a disc name nor index.  Use the default disc.
+      if (disc_name[0] == '\0' && disc_index == -1)
+      {
+          disc_index = 0;
+      }
+#endif
+      if (disc_index != -1) {
+          hostfs_disc_info = get_hostfs_disc_info_by_index(disc_index);
+      } else {
+          hostfs_disc_info = get_hostfs_disc_info_by_name(disc_name);
+          if (!hostfs_disc_info) {
+             object_info->type = OBJECT_TYPE_NOT_FOUND;
+             return;
+          }
+      }
+      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 +667,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 +709,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 +1050,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 +1077,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 +1173,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 +1254,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 +1296,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 +1321,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 +1355,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 +1376,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 +1648,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 +1688,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: src/hostfs.h
===================================================================
--- src/hostfs.h	(revision 137)
+++ src/hostfs.h	(working copy)
@@ -15,13 +15,24 @@
 #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 void hostfs(ARMul_State *state);
+int hostfs_initialise();
+int add_hostfs_disc();
+int get_max_hostfs_discs();
 
 #define ARMul_LoadWordS(state, address) readmeml(address)
 #define ARMul_LoadByte(state, address) readmemb(address)
Index: src/rpcemu.c
===================================================================
--- src/rpcemu.c	(revision 137)
+++ src/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];
@@ -59,17 +60,10 @@
 
 int startrpcemu()
 {
-        int c;
         char *p;
         get_executable_name(exname,511);
         p=get_filename(exname);
         *p=0;
-        append_filename(HOSTFS_ROOT,exname,"hostfs",511);
-        for (c=0;c<511;c++)
-        {
-                if (HOSTFS_ROOT[c]=='\\')
-                   HOSTFS_ROOT[c]='/';
-        }
         initmem();
 //printf("Mem inited...\n");
 	loadroms();
@@ -92,7 +86,6 @@
 //printf("About to init video...\n");
         initvideo();
 //printf("Video inited!\n");
-        loadconfig();
         initsound();
         reallocmem(rammask+1);
         initcodeblocks();
@@ -151,6 +144,11 @@
 {
         char fn[512];
         char *p;
+        unsigned int i;
+        char *hostfs_name;
+        char *hostfs_path;
+        char *hostfs_perm;
+        char config_key[80];
         append_filename(fn,exname,"rpc.cfg",511);
         set_config_file(fn);
         p=(char *)get_config_string(NULL,"mem_size",NULL);
@@ -188,6 +186,29 @@
         mousehackon=get_config_int(NULL,"mouse_following",1);
         username=get_config_string(NULL,"username",NULL);
         ipaddress=get_config_string(NULL,"ipaddress",NULL);
+        hostfs_initialise();
+        for (i = 0; i < get_max_hostfs_discs(); i++) {
+                sprintf(config_key, "hostfs.drive%d.name", i);
+                hostfs_name = get_config_string(NULL, config_key, NULL);
+                if (!hostfs_name)
+                        break;
+                sprintf(config_key, "hostfs.drive%d.path", i);
+                hostfs_path = get_config_string(NULL, config_key, NULL);
+                if (!hostfs_name) {
+                        printf("Error: drive %d has no path\n", i);
+                        break;
+                }
+                sprintf(config_key, "hostfs.drive%d.permissions", i);
+                hostfs_perm = get_config_string(NULL, config_key, NULL);
+                if (!hostfs_name) {
+                        printf("Error: drive %d has no permissions\n", i);
+                        break;
+                }
+                if (add_hostfs_disc(hostfs_name, hostfs_path, hostfs_perm) != 0) {
+                        printf("Error: Failed to add hostfs drive %s,%s,%s\n",
+                               hostfs_name, hostfs_path, hostfs_perm);
+                }
+        }
 }
 
 void saveconfig()
Index: src/rpcemu.h
===================================================================
--- src/rpcemu.h	(revision 137)
+++ src/rpcemu.h	(working copy)
@@ -125,6 +125,7 @@
 extern void wakeupsoundthread();
 extern void updateirqs(void);
 extern int quited;
+extern char *rpcemu_os_expand_home_path(const char *path, char *buf, int buflen);
 
 extern char exname[512];
 extern int timetolive;
Index: src/rpc-win.c
===================================================================
--- src/rpc-win.c	(revision 137)
+++ src/rpc-win.c	(working copy)
@@ -31,7 +31,20 @@
 int updatemips=0;
 int vsyncints=0;
 
+char *rpcemu_os_expand_home_path(const char *path, char *buf, int buflen)
+{
+        buf[buflen-1] = '\0';
 
+        if (*path != '~') {
+                strncpy(buf, buflen-1, path);
+        } else {
+                // FIXME: Is this correct?
+                snprintf(buf, buflen, "%s%s", getenv("USERPROFILE"), path+1);
+        }
+
+        return buf;
+}
+
 void domips(void)
 {
         mips=(float)inscount/1000000.0f;
@@ -333,6 +346,7 @@
         ShowWindow (ghwnd, nFunsterStil);
         win_set_window(ghwnd);
         allegro_init();
+        loadconfig();
         install_keyboard();
         install_timer();
         install_mouse();
Index: src/rpc-linux.c
===================================================================
--- src/rpc-linux.c	(revision 137)
+++ src/rpc-linux.c	(working copy)
@@ -10,6 +10,7 @@
 #include "vidc20.h"
 #include "gui.h"
 
+extern void loadconfig();
 
 int mousecapture=0;
 float mips;
@@ -22,6 +23,19 @@
 static uint32_t mipscount;
 float mipstotal;
 
+char *rpcemu_os_expand_home_path(const char *path, char *buf, int buflen)
+{
+        buf[buflen-1] = '\0';
+
+        if (*path != '~') {
+                strncpy(buf, path, buflen-1);
+        } else {
+                snprintf(buf, buflen, "%s%s", getenv("HOME"), path+1);
+        }
+
+        return buf;
+}
+
 void *_soundthread(void *p)
 {
 	int c;
@@ -215,6 +229,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 +239,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: src/iomd.h
===================================================================
--- src/iomd.h	(revision 137)
+++ src/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