On Tue, 16 Jul 2002, Arnaldo Pereira wrote:

>       I'm running a foxpro program under dosemu(1.1.3.2)+drdos(7.03).
>       The foxpro system seems to work fine, but under some circunstances, it can't 
> open a database file, especially when another user has already opened it. 
>       It seems the foxpro application is trying to lock an unique database 
> register, but dosemu is locking the entire database file.
>       I've already tried the share.exe, but it works the same way as without it.
>       Any thought about the solution ?

Could you try this patch and see if it makes any difference?

Bart
diff -ur -x*.o -x*~ -x*.d dosemu-1.1.3.2/src/dosext/mfs/mangle.c 
dosemu-1.1.3.3/src/dosext/mfs/mangle.c
--- dosemu-1.1.3.2/src/dosext/mfs/mangle.c      Sun Jun 16 12:22:43 2002
+++ dosemu-1.1.3.3/src/dosext/mfs/mangle.c      Sat Jun 29 18:54:14 2002
@@ -149,6 +149,7 @@
 {
   int len = strlen(fname);
   char *dot_pos = strchr(fname,'.');
+  char *s;
   int l;
 
   DEBUG(5,("checking %s for 8.3\n",fname));
@@ -158,7 +159,7 @@
     return(False);
 
   /* can't be an MS-DOS Special file such as lpt1 or even lpt1.txt */
-  if (is_reserved_msdos(fname))
+  if ((s = is_reserved_msdos(fname)) && strcmp(s, "NUL") != 0)
     return(False);
 
   /* can't contain invalid dos chars */
diff -ur -x*.o -x*~ -x*.d dosemu-1.1.3.2/src/dosext/mfs/mfs.c 
dosemu-1.1.3.3/src/dosext/mfs/mfs.c
--- dosemu-1.1.3.2/src/dosext/mfs/mfs.c Sun Jun 16 00:48:05 2002
+++ dosemu-1.1.3.3/src/dosext/mfs/mfs.c Sat Jun 29 19:22:25 2002
@@ -1051,8 +1051,8 @@
  * 
  * DANG_END_REMARK
  */
-  if (strncasecmpDOS(mname, "NUL     ", strlen(mname)) == 0 &&
-      strncasecmpDOS(mext, "   ", strlen(mext)) == 0) {
+  if (strncasecmpDOS(mname, "NUL     ", 8) == 0 &&
+      strncasecmpDOS(mext, "   ", 3) == 0) {
 
     entry = make_entry();
     dir_list = entry;
@@ -1702,10 +1702,12 @@
 
   Debug0((dbg_fd, "dos_fs: build_ufs_path for DOS path '%s'\n", path));
 
- if ((s=is_reserved_msdos(path))) {
+  /* we handle only NUL ourselves; this needs to be changed though
+     to handle other devices too ! */
+ if ((s=is_reserved_msdos(path)) && (strcmp(s, "NUL") != 0)) {
   Debug0((dbg_fd,"MFS: Special File, so name changed to '%s'\n", s));
-  strcpy (path, s);
   strcpy (ufs, s);
+  strcpy (path, s);
   return FALSE;
  }
  else {
@@ -1806,8 +1808,19 @@
   /* check for device files like NUL, CON, etc. */
   if ((slash1=is_reserved_msdos(fpath))) {
       if (strcmp(slash1, "NUL") == 0) {
+          slash1 = fpath + strlen(fpath);
+          while (*slash1 != '/' && slash1 > fpath)
+            slash1--;
+          if (*slash1 == '/') {
+            *slash1 = '\0';
+            /* check if path exists */
+            if (stat(fpath, st) || !S_ISDIR(st->st_mode))
+              return (FALSE);
+            *slash1 = '/';
+          }
           Debug0((dbg_fd, "nul cmpr\n"));
           stat("/dev/null", st);
+          strcpy(fpath, "/dev/null");
           return (TRUE);
       } else {
           Debug0((dbg_fd, "Device file %s\n", slash1));
@@ -2538,7 +2551,7 @@
 }
 
 static boolean_t
-share(int fd, boolean_t writing, sft_t sft)
+share(int fd, int mode, sft_t sft)
 {
   /*
    * Return whether FD doesn't break any sharing rules.  FD was opened for
@@ -2567,51 +2580,128 @@
   fl.l_start  = 0x7fffffff;
   fl.l_len = 1;
   fl.l_pid = 0;
+  fl.l_type = F_WRLCK;
+  /* see whatever locks are possible */
+  
+  if ( fcntl( fd, F_GETLK, &fl ) ) {
+  /* work around Linux's NFS locking problems (June 1999) -- sw */
+    static unsigned char u[26] = { 0, };
+    if(current_drive < 26) {
+      if(!u[current_drive])
+        fprintf(stderr,
+                "SHAREing doesn't work on drive %c: (probably NFS volume?)\n",
+                current_drive + 'A'
+          );
+      u[current_drive] = 1;
+    }
+    return (TRUE);
+  }
+
+  /* end NFS fix */
+
+  /* file is already locked? then do not even open */
+  /* a Unix read lock prevents writing;
+     a Unix write lock prevents reading and writing,
+     but for DOS compatibility we allow reading for write locks */
+  if ((fl.l_type == F_RDLCK && mode != O_RDONLY) ||
+      (fl.l_type == F_WRLCK && mode != O_WRONLY))
+    return FALSE;
+  
   switch ( share_mode ) {
+    /* this is a little heuristic and does not completely
+       match to DOS behaviour. That would require tracking
+       how existing fd's are opened and comparing st_dev
+       and st_ino fields
+       from Ralf Brown's interrupt list:
+       (Table 01403)
+Values of DOS 2-6.22 file sharing behavior:
+          |     Second and subsequent Opens
+ First    |Compat  Deny   Deny   Deny   Deny
+ Open     |        All    Write  Read   None
+          |R W RW R W RW R W RW R W RW R W RW
+ - - - - -| - - - - - - - - - - - - - - - - -
+ Compat R |Y Y Y  N N N  1 N N  N N N  1 N N
+        W |Y Y Y  N N N  N N N  N N N  N N N
+        RW|Y Y Y  N N N  N N N  N N N  N N N
+ - - - - -|
+ Deny   R |C C C  N N N  N N N  N N N  N N N
+ All    W |C C C  N N N  N N N  N N N  N N N
+        RW|C C C  N N N  N N N  N N N  N N N
+ - - - - -|
+ Deny   R |2 C C  N N N  Y N N  N N N  Y N N
+ Write  W |C C C  N N N  N N N  Y N N  Y N N
+        RW|C C C  N N N  N N N  N N N  Y N N
+ - - - - -|
+ Deny   R |C C C  N N N  N Y N  N N N  N Y N
+ Read   W |C C C  N N N  N N N  N Y N  N Y N
+        RW|C C C  N N N  N N N  N N N  N Y N
+ - - - - -|
+ Deny   R |2 C C  N N N  Y Y Y  N N N  Y Y Y
+ None   W |C C C  N N N  N N N  Y Y Y  Y Y Y
+        RW|C C C  N N N  N N N  N N N  Y Y Y
+
+        our sharing behaviour:
+ Compat R |Y Y Y  Y Y Y  Y Y Y  Y Y Y  Y Y Y
+        W |Y Y Y  Y Y Y  Y Y Y  Y Y Y  Y Y Y
+        RW|Y Y Y  Y Y Y  Y Y Y  Y Y Y  Y Y Y
+ - - - - -|
+ Deny   R |Y N N  N N N  Y N N  N N N  Y N N
+ All    W |N N N  N N N  N N N  N Y N  N Y N
+        RW|N N N  N N N  N N N  N Y N  N Y N
+ - - - - -|
+ Deny   R |Y N N  N N N  Y N N  N N N  Y N N
+ Write  W |Y Y Y  Y Y Y  Y Y Y  Y Y Y  Y Y Y
+        RW|Y N N  N N N  Y N N  N N N  Y N N
+ - - - - -|
+ Deny   R |Y Y Y  Y Y Y  Y Y Y  Y Y Y  Y Y Y
+ Read   W |N N N  N N N  N N N  N Y N  N Y N
+        RW|N N N  N N N  N N N  N Y N  N Y N
+ - - - - -|
+ Deny   R |Y Y Y  Y Y Y  Y Y Y  Y Y Y  Y Y Y
+ None   W |Y Y Y  Y Y Y  Y Y Y  Y Y Y  Y Y Y
+        RW|Y Y Y  Y Y Y  Y Y Y  Y Y Y  Y Y Y
+
+        Legend: Y = open succeeds, N = open fails with error code 05h
+        C = open fails, INT 24 generated
+        1 = open succeeds if file read-only, else fails with error code
+        2 = open succeeds if file read-only, else fails with INT 24
+    */
   case COMPAT_MODE:
-  case DENY_ALL:
+    if (fl.l_type == F_WRLCK) return FALSE;
+  case DENY_NONE:
+    return TRUE;                   /* do not set locks at all */
   case DENY_WRITE:
+    if (fl.l_type == F_WRLCK) return FALSE;
+    if (mode == O_WRONLY) return TRUE; /* only apply read locks */
+    fl.l_type = F_RDLCK;
+    break;
   case DENY_READ:
-    fl.l_type = !writing ? F_RDLCK : F_WRLCK;
+    if (fl.l_type == F_RDLCK) return FALSE;
+    if (mode == O_RDONLY) return TRUE; /* only apply write locks */
+    fl.l_type = F_WRLCK;
     break;
-  case DENY_ANY:
-    fl.l_type = F_RDLCK;
+  case DENY_ALL:
+    if (fl.l_type == F_WRLCK || fl.l_type == F_RDLCK) return FALSE;
+    fl.l_type = mode == O_RDONLY ? F_RDLCK : F_WRLCK;
     break;
   default:
-    fl.l_type = F_WRLCK;
     Debug0((dbg_fd, "internal SHARE: unknown sharing mode %x\n",
            share_mode));
+    return FALSE;
     break;
   }
-  if ( fcntl( fd, F_SETLK, &fl ) == 0 ) return (TRUE);
+  fl.l_whence = SEEK_SET;
+  fl.l_start  = 0x7fffffff;
+  fl.l_len = 1;
+  fl.l_pid = 0;
+  fcntl( fd, F_SETLK, &fl );
 
   Debug0((dbg_fd,
-    "internal SHARE: locking failed: drive %c:, fd %d, type %d whence %d pid %d\n",
+    "internal SHARE: locking: drive %c:, fd %d, type %d whence %d pid %d\n",
      current_drive + 'A', fd, fl.l_type, fl.l_whence, fl.l_pid
   ));
 
-  /* work around Linux's NFS locking problems (June 1999) -- sw */
-
-  {
-    static unsigned char u[26] = { 0, };
-
-    if ( fcntl( fd, F_GETLK, &fl ) ) {
-      if(current_drive < 26) {
-        if(!u[current_drive])
-          fprintf(stderr,
-            "SHAREing doesn't work on drive %c: (probably NFS volume?)\n",
-            current_drive + 'A'
-          );
-        u[current_drive] = 1;
-      }
-
-      return (TRUE);
-    }
-  }
-
-  /* end NFS fix */
-
-  return (FALSE);
+  return (TRUE);
 }
 
 static int
@@ -3180,6 +3270,11 @@
       return (FALSE);
     }
     build_ufs_path(fpath, filename1);
+    for (i = 0, bs_pos = 0; fpath[i] != EOS; i++) {
+      if (fpath[i] == SLASH)
+       bs_pos = i;
+    }
+    auspr(fpath + bs_pos + 1, fname, fext);
     if (!find_file(fpath, &st)) {
       Debug0((dbg_fd, "open failed: '%s'\n", fpath));
       SETWORD(&(state->eax), FILE_NOT_FOUND);
@@ -3191,6 +3286,7 @@
       SETWORD(&(state->eax), FILE_NOT_FOUND);
       return (FALSE);
     }
+    attr = get_dos_attr(st.st_mode,is_hidden(fpath));
     if (dos_mode == READ_ACC) {
       unix_mode = O_RDONLY;
     }
@@ -3212,33 +3308,19 @@
       return (FALSE);
     }
 
-    /* Handle DOS requests for drive:\patch\NUL */
-    if (!strncmpDOS((u_char *) (fpath + strlen(fpath) - 3), "nul", 3)) {
-      if ((fd = open("/dev/null", unix_mode)) < 0) {
-       Debug0((dbg_fd, "access denied:'%s'\n", fpath));
-       SETWORD(&(state->eax), ACCESS_DENIED);
-       return (FALSE);
-      }
-    }
-    else {
-      if ((fd = open(fpath, unix_mode )) < 0) {
-        Debug0((dbg_fd, "access denied:'%s'\n", fpath));
-        SETWORD(&(state->eax), ACCESS_DENIED);
-        return (FALSE);
-      }
-      if (!share(fd, unix_mode != O_RDONLY, sft)) {
-       close( fd );
-       SETWORD(&(state->eax), ACCESS_DENIED);
-       return (FALSE);
-      }
+    if ((fd = open(fpath, unix_mode )) < 0) {
+      Debug0((dbg_fd, "access denied:'%s'\n", fpath));
+      SETWORD(&(state->eax), ACCESS_DENIED);
+      return (FALSE);
     }
-
-    for (i = 0, bs_pos = 0; fpath[i] != EOS; i++) {
-      if (fpath[i] == SLASH)
-       bs_pos = i;
+    if (!share(fd, unix_mode & O_ACCMODE, sft)) {
+      close( fd );
+      SETWORD(&(state->eax), ACCESS_DENIED);
+      return (FALSE);
     }
 
-    auspr(fpath + bs_pos + 1, sft_name(sft), sft_ext(sft));
+    memcpy(sft_name(sft), fname, 8);
+    memcpy(sft_ext(sft), fext, 3);
 
 #if 0
     if (FCBcall)
@@ -3249,11 +3331,7 @@
     sft_dev_drive_ptr(sft) = (u_long)strdup(fpath);
     sft_directory_entry(sft) = 0;
     sft_directory_sector(sft) = 0;
-#ifdef NOTEST
     sft_attribute_byte(sft) = attr;
-#else
-    sft_attribute_byte(sft) = 0x20;
-#endif /* NOTEST */
     sft_device_info(sft) = current_drive + (0x8040);
     time_to_dos(&st.st_mtime,
                &sft_date(sft), &sft_time(sft));
@@ -3322,7 +3400,13 @@
       return (FALSE);
     }
     build_ufs_path(fpath, filename1);
-
+    bs_pos=0;
+    for (i = 0, bs_pos = 0; fpath[i] != EOS; i++) {
+      if (fpath[i] == SLASH)
+       bs_pos = i;
+    }
+    auspr(fpath + bs_pos + 1, fname, fext);
+    
     if (find_file(fpath, &st)) {
       Debug0((dbg_fd, "st.st_mode = 0x%02x, handles=%d\n", st.st_mode, 
sft_handle_cnt(sft)));
       if ( /* !(st.st_mode & S_IFREG) || */ create_file) {
@@ -3332,12 +3416,6 @@
       }
     }
 
-    bs_pos=0;
-    for (i = 0, bs_pos = 0; fpath[i] != EOS; i++) {
-      if (fpath[i] == SLASH)
-       bs_pos = i;
-    }
-
     if ((fd = open(fpath, (O_RDWR | O_CREAT),
                   get_unix_attr(0664, attr))) < 0) {
       strncpy(buf, fpath, bs_pos);
@@ -3358,7 +3436,7 @@
       }
     }
 
-    if (!share(fd, TRUE, sft) || ftruncate(fd, 0) != 0) {
+    if (!share(fd, O_RDWR, sft) || ftruncate(fd, 0) != 0) {
       Debug0((dbg_fd, "unable to truncate %s: %s (%d)\n",
              fpath, strerror(errno), errno));
       close(fd);
@@ -3372,7 +3450,8 @@
       leave_priv_setting();
     }
 
-    auspr(fpath + bs_pos + 1, sft_name(sft), sft_ext(sft));
+    memcpy(sft_name(sft), fname, 8);
+    memcpy(sft_ext(sft), fext, 3);
     sft_dev_drive_ptr(sft) = (u_long)strdup(fpath);
 
     /* This caused a bug with temporary files so they couldn't be read,
@@ -3483,8 +3562,8 @@
     fpath[bs_pos] = EOS;
 
     auspr(fpath + bs_pos + 1, fname, fext);
-    strncpy(sdb_template_name(sdb), fname, 8);
-    strncpy(sdb_template_ext(sdb), fext, 3);
+    memcpy(sdb_template_name(sdb), fname, 8);
+    memcpy(sdb_template_ext(sdb), fext, 3);
     sdb_attribute(sdb) = attr;
     sdb_drive_letter(sdb) = 0x80 + current_drive;
     sdb_dir_entry(sdb) = HLIST_STACK_SIZE*2;  /* correct value later */
@@ -3542,6 +3621,8 @@
       strncpy(sdb_file_name(sdb), fname, 8);
       strncpy(sdb_file_ext(sdb), fext, 3);
       sdb_file_attr(sdb) = VOLUME_LABEL;
+      if (attr == VOLUME_LABEL)
+        return TRUE; /* no findnext */
       sdb_dir_entry(sdb) = 0x0;
       /* if (attr != VOLUME_LABEL)
        find_in_progress = TRUE; */
diff -ur -x*.o -x*~ -x*.d dosemu-1.1.3.2/src/dosext/mfs/mfs.h 
dosemu-1.1.3.3/src/dosext/mfs/mfs.h
--- dosemu-1.1.3.2/src/dosext/mfs/mfs.h Sun May 26 16:57:56 2002
+++ dosemu-1.1.3.3/src/dosext/mfs/mfs.h Thu Jun 20 18:37:54 2002
@@ -387,7 +387,7 @@
 #define DENY_ALL       0x01
 #define DENY_WRITE     0x02
 #define DENY_READ      0x03
-#define DENY_ANY       0x04
+#define DENY_NONE      0x04
 
 #define CHILD_INHERIT  0x00
 #define NO_INHERIT     0x01

Reply via email to