Hi,

attached is a patch to (more cleanly than before) implement 64-bit file
locking in DOSEMU. This is as far as I can see, as far as DOSEMU can
reasonably go in the locking business, but I hope I didn't introduce any
new problems. Old problems that aren't solved by this patch will probably
never be solved (on the DOSEMU side at least), I'm afraid.

You need glibc 2.2+ and kernel 2.4, otherwise the code will revert to the
old locking behaviour.

Also, you may experiment with a new option, $_full_file_locks in your
dosemu.conf or .dosemurc, which affects the way who DOSEMU locks whole
files. Default is (off), and that is the old behaviour (lock 1 byte that
DOS can't see).

patch is vs. version 1.1.4.11 (see http://www.dosemu.org/testing).

Bart
diff -urN -X dosemu-ignore-files dosemu-1.1.4.11/etc/dosemu.conf 
dosemu-1.1.4.12/etc/dosemu.conf
--- dosemu-1.1.4.11/etc/dosemu.conf     Tue Feb  4 21:39:59 2003
+++ dosemu-1.1.4.12/etc/dosemu.conf     Thu Feb  6 01:10:08 2003
@@ -48,6 +48,8 @@
 #                      # optionally the device may be appended such as
 #                      # "threeinch:/dev/fd0"
 #$_floppy_b = ""               # ditto for B:
+#$_full_file_locks = (off) # whether to lock the full file on lredired drives 
+#                      # for file locking requests or just one byte
 #
 #
 #$_debug = "-a+cw"     # same format as -D commandline option, ""="-a+cw".
diff -urN -X dosemu-ignore-files dosemu-1.1.4.11/etc/global.conf 
dosemu-1.1.4.12/etc/global.conf
--- dosemu-1.1.4.11/etc/global.conf     Tue Feb  4 21:39:59 2003
+++ dosemu-1.1.4.12/etc/global.conf     Thu Feb  6 01:08:51 2003
@@ -356,6 +356,8 @@
   cli_timeout $_cli_timeout
   pic_watchdog $_pic_watchdog
 
+  full_file_locks $_full_file_locks
+
   ## serial
   if (strlen($_ttylocks))
     ttylocks { directory $_ttylocks namestub LCK.. }
diff -urN -X dosemu-ignore-files dosemu-1.1.4.11/src/base/init/config.c 
dosemu-1.1.4.12/src/base/init/config.c
--- dosemu-1.1.4.11/src/base/init/config.c      Tue Feb  4 21:39:59 2003
+++ dosemu-1.1.4.12/src/base/init/config.c      Thu Feb  6 01:12:33 2003
@@ -228,8 +228,8 @@
         config.timers);
     (*print)("tty_lockdir \"%s\"\ntty_lockfile \"%s\"\nconfig.tty_lockbinary %d\n",
         config.tty_lockdir, config.tty_lockfile, config.tty_lockbinary);
-    (*print)("num_ser %d\nnum_lpt %d\nfastfloppy %d\n",
-        config.num_ser, config.num_lpt, config.fastfloppy);
+    (*print)("num_ser %d\nnum_lpt %d\nfastfloppy %d\nfull_file_locks %d\n",
+        config.num_ser, config.num_lpt, config.fastfloppy, config.full_file_locks);
     (*print)("emusys \"%s\"\nemuini \"%s\"\n",
         (config.emusys ? config.emusys : ""), (config.emuini ? config.emuini : ""));
     (*print)("dosbanner %d\nvbios_post %d\ndetach %d\n",
diff -urN -X dosemu-ignore-files dosemu-1.1.4.11/src/base/init/lexer.l.in 
dosemu-1.1.4.12/src/base/init/lexer.l.in
--- dosemu-1.1.4.11/src/base/init/lexer.l.in    Sat Feb  1 16:04:47 2003
+++ dosemu-1.1.4.12/src/base/init/lexer.l.in    Thu Feb  6 01:11:44 2003
@@ -361,6 +361,7 @@
 printer                        RETURN(PRINTER);
 emusys                  RETURN(EMUSYS);
 emuini                  RETURN(EMUINI);
+full_file_locks                RETURN(FULL_FILE_LOCKS);
 ttylocks               RETURN(TTYLOCKS);
 sound_emu               RETURN(L_SOUND);
 joystick_emu           RETURN(L_JOYSTICK);
diff -urN -X dosemu-ignore-files dosemu-1.1.4.11/src/base/init/parser.y.in 
dosemu-1.1.4.12/src/base/init/parser.y.in
--- dosemu-1.1.4.11/src/base/init/parser.y.in   Tue Feb  4 21:39:59 2003
+++ dosemu-1.1.4.12/src/base/init/parser.y.in   Thu Feb  6 01:14:20 2003
@@ -224,7 +224,7 @@
 %token NETDEV VNET
 %token DEBUG MOUSE SERIAL COM KEYBOARD TERMINAL VIDEO EMURETRACE TIMER
 %token MATHCO CPU CPUSPEED RDTSC BOOTA BOOTB BOOTC L_XMS L_DPMI PORTS DISK DOSMEM 
PRINTER
-%token L_EMS L_UMB EMS_SIZE EMS_FRAME TTYLOCKS L_SOUND L_JOYSTICK
+%token L_EMS L_UMB EMS_SIZE EMS_FRAME TTYLOCKS L_SOUND L_JOYSTICK FULL_FILE_LOCKS
 %token DEXE ALLOWDISK FORCEXDOS XDOSONLY
 %token ABORT WARN
 %token BOOTDISK L_FLOPPY EMUSYS EMUINI L_X
@@ -412,6 +412,10 @@
                     {
                     config.emuini = $3;
                     c_printf("CONF: config.emuini = '%s'\n", $3);
+                   }
+               | FULL_FILE_LOCKS bool
+                   {
+                   config.full_file_locks = ($2!=0);
                    }
                | FASTFLOPPY floppy_bool
                        {
diff -urN -X dosemu-ignore-files dosemu-1.1.4.11/src/dosext/mfs.c 
dosemu-1.1.4.12/src/dosext/mfs.c
--- dosemu-1.1.4.11/src/dosext/mfs/mfs.c        Sat Feb  1 16:04:48 2003
+++ dosemu-1.1.4.12/src/dosext/mfs/mfs.c        Thu Feb  6 01:38:56 2003
@@ -153,6 +153,7 @@
 
 /* Modified by O.V.Zhirov at July 1998    */
 
+#include "config.h"
 
 #if defined(__linux__)
 #define DOSEMU 1               /* this is a port to dosemu */
@@ -197,7 +198,6 @@
 #include <signal.h>
 #include <string.h>
 #include "mfs.h"
-#include "config.h"
 /* For passing through GetRedirection Status */
 #include "memory.h"
 #include "redirect.h"
@@ -2570,6 +2570,38 @@
   return (TRUE);
 }
 
+static int lock_file_region(int fd, int cmd, struct flock *fl, long long start, 
+unsigned long len)
+{
+  fl->l_whence = SEEK_SET;
+  fl->l_pid = 0;
+  /* first handle magic file lock value */
+  if (start == 0x100000000LL && config.full_file_locks) {
+    start = len = 0;
+  }
+#ifdef F_GETLK64
+  if (cmd == F_SETLK64 || cmd == F_GETLK64) {
+    struct flock64 fl64;
+    int result;
+    Debug0((dbg_fd, "Large file locking start=%lld, len=%lu\n", start, len));
+    fl64.l_type = fl->l_type;
+    fl64.l_whence = fl->l_whence;
+    fl64.l_pid = fl->l_pid;
+    fl64.l_start = start;
+    fl64.l_len = len;
+    result = fcntl( fd, cmd, &fl64 );
+    fl->l_type = fl64.l_type;
+    fl->l_start = (long) fl64.l_start;
+    fl->l_len = (long) fl64.l_len;
+    return result;
+  }
+#endif
+  if (start == 0x10000000LL)
+    start = 0x7fffffff;
+  fl->l_start = start;
+  fl->l_len = len;
+  return fcntl( fd, cmd, fl );
+}
+
 static boolean_t
 share(int fd, int mode, sft_t sft)
 {
@@ -2595,15 +2627,17 @@
    * and 0x7fffffff is my start position.  --Maxim Ruchko
    */
   struct flock fl;
+  int ret;
   int share_mode = ( sft_open_mode( sft ) >> 4 ) & 0x7;
-  fl.l_whence = SEEK_SET;
-  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 ) ) {
+
+#ifdef F_GETLK64
+  ret = lock_file_region( fd, F_GETLK64, &fl, 0x100000000LL, 1 );
+  if ( ret == -1 && errno == EINVAL )
+#endif
+    ret = lock_file_region( fd, F_GETLK, &fl, 0x100000000LL, 1 );
+  if ( ret == -1 ) {
   /* work around Linux's NFS locking problems (June 1999) -- sw */
     static unsigned char u[26] = { 0, };
     if(current_drive < 26) {
@@ -2713,12 +2747,11 @@
     return FALSE;
     break;
   }
-  fl.l_whence = SEEK_SET;
-  fl.l_start  = 0x7fffffff;
-  fl.l_len = 1;
-  fl.l_pid = 0;
-  fcntl( fd, F_SETLK, &fl );
-
+#ifdef F_SETLK64
+  ret = lock_file_region( fd, F_SETLK64, &fl, 0x100000000LL, 1 );
+  if ( ret == -1 && errno == EINVAL )
+#endif
+    lock_file_region( fd, F_SETLK, &fl, 0x100000000LL, 1 );
   Debug0((dbg_fd,
     "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
@@ -3852,7 +3885,7 @@
                int fd = open_files[sft_fd(sft)].fd;
                int ret;
                struct LOCKREC{
-                       long offset,size;
+                       unsigned long offset,size;
                } *pt = (struct LOCKREC*) Addr (state,ds,edx);
                struct flock larg;
                unsigned long mask = 0xC0000000;
@@ -3862,6 +3895,14 @@
                   return (FALSE);
                 }
 
+               Debug0((dbg_fd, "lock requested, fd=%d, is_lock=%d, start=%lx, 
+len=%lx\n",
+                       fd, is_lock, larg.l_start,larg.l_len));
+
+               if (pt->offset + pt->size < pt->offset) {
+                       SETWORD(&(state->eax), ACCESS_DENIED);
+                       return FALSE;
+               }
+
 #if 1   /* The kernel can't place F_WRLCK on files opened read-only and
          * FoxPro fails. IMHO the right solution is:         --Maxim Ruchko */
                larg.l_type = is_lock ? (
@@ -3874,10 +3915,8 @@
 #else
                larg.l_type = is_lock ? F_WRLCK : F_UNLCK;
 #endif
-               larg.l_whence = SEEK_SET;
                larg.l_start = pt->offset;
                larg.l_len = pt->size;
-               larg.l_pid = 0;
 
                /*
                        This is a superdooper patch extract from the Samba project
@@ -3902,7 +3941,11 @@
                if ((larg.l_start & mask) != 0)
                        larg.l_start = (larg.l_start & ~mask) | ((larg.l_start & mask) 
>> 2);
 
-               ret = fcntl (fd,F_SETLK,&larg);
+#ifdef F_SETLK64
+               ret = lock_file_region (fd,F_SETLK64,&larg,pt->offset,pt->size);
+               if (ret == -1 && errno == EINVAL)
+#endif
+                       ret = lock_file_region 
+(fd,F_SETLK,&larg,larg.l_start,larg.l_len);
                Debug0((dbg_fd, "lock fd=%x rc=%x type=%x whence=%x start=%lx, 
len=%lx\n",
                        fd, ret, larg.l_type, larg.l_whence, larg.l_start,larg.l_len));
                if (ret != -1) return TRUE; /* no error */
--- dosemu-1.1.4.11/src/include/emu.h   Tue Feb  4 21:39:59 2003
+++ dosemu-1.1.4.12/src/include/emu.h   Thu Feb  6 01:43:39 2003
@@ -316,6 +316,7 @@
        unsigned char *pre_stroke_mem;
 
        /* Lock File business */
+       boolean full_file_locks;
        char *tty_lockdir;      /* The Lock directory  */
        char *tty_lockfile;     /* Lock file pretext ie LCK.. */
        boolean tty_lockbinary; /* Binary lock files ? */

Reply via email to