[PATCH] (locking) (was Re: dosemu and CLIPPER locks (again))

Bart Oldeman
2003-02-06T06:56:16Z

[-- Attachment #1: Type: TEXT/PLAIN, Size: 755 bytes --]

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

[-- Attachment #2: Type: TEXT/PLAIN, Size: 8343 bytes --]

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 ? */