diff -urNX ../kernels/exclude linux+lock-F/fs/locks.c linux+lock/fs/locks.c --- linux+lock-F/fs/locks.c Wed Jun 14 22:01:03 2000 +++ linux+lock/fs/locks.c Thu Jun 15 04:25:57 2000 @@ -216,6 +216,10 @@ case LOCK_UN: return F_UNLCK; } + + if (cmd & LOCK_MAND) + return cmd & (LOCK_MAND | LOCK_RW); + return -EINVAL; } @@ -360,10 +364,9 @@ case F_WRLCK: return 1; - - default: - BUG(); } + BUG(); + return 0; /* I'm a liar */ } /* Determine if lock sys_fl blocks lock caller_fl. FLOCK specific @@ -384,10 +387,9 @@ case F_WRLCK: return 1; - - default: - BUG(); } + BUG(); + return 0; /* I'm a liar */ } /* Insert file lock fl into an inode's lock list at the position indicated @@ -1322,7 +1324,7 @@ error = flock_translate_cmd(cmd); if (error < 0) - goto out; + goto out_putf; type = error; error = -EBADF; @@ -1444,6 +1446,59 @@ acquire_fl_sem(); locks_delete_block(waiter); release_fl_sem(); +} + +/* + * Emulate windows share modes + */ +int lock_may_read(struct inode *inode, loff_t start, unsigned long len) +{ + struct file_lock *fl; + int result = 1; + acquire_fl_sem(); + for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { + printk("flock_may_read: lock = %x, %x\n", fl->fl_flags, fl->fl_type); + if (fl->fl_flags == FL_POSIX) { + if (fl->fl_type == F_RDLCK) + continue; + if ((fl->fl_end < start) || (fl->fl_start > (start + len))) + continue; + } else { + if (!(fl->fl_type & LOCK_MAND)) + continue; + if (fl->fl_type & LOCK_READ) + continue; + } + result = 0; + break; + } + release_fl_sem(); +printk("flock_may_read: %x\n", result); + return result; +} + +int lock_may_write(struct inode *inode, loff_t start, unsigned long len) +{ + struct file_lock *fl; + int result = 1; + acquire_fl_sem(); + for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { + printk("flock_may_write: lock = %x, %x\n", fl->fl_flags, fl->fl_type); + if (fl->fl_flags == FL_POSIX) { + if ((fl->fl_end < start) || (fl->fl_start > (start + len))) + continue; + } else { + if (!(fl->fl_type & LOCK_MAND)) + continue; + if (fl->fl_type & LOCK_WRITE) + continue; + } + result = 0; + break; + } + release_fl_sem(); +printk("flock_may_write: %x\n", result); + return result; } void __init filelock_init(void) diff -urNX ../kernels/exclude linux+lock-F/fs/nfsd/vfs.c linux+lock/fs/nfsd/vfs.c --- linux+lock-F/fs/nfsd/vfs.c Mon May 8 18:54:17 2000 +++ linux+lock/fs/nfsd/vfs.c Thu Jun 15 01:14:06 2000 @@ -585,6 +585,9 @@ err = nfserr_perm; if (!file.f_op->read) goto out_close; + if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && + (!lock_may_read(file.f_dentry->d_inode, offset, *count))) + goto out_close; /* Get readahead parameters */ ra = nfsd_get_raparms(fhp->fh_export->ex_dev, fhp->fh_dentry->d_inode->i_ino); @@ -654,6 +657,9 @@ err = nfserr_perm; if (!file.f_op->write) goto out_close; + if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && + (!lock_may_write(file.f_dentry->d_inode, offset, cnt))) + goto out_close; dentry = file.f_dentry; inode = dentry->d_inode; @@ -1255,7 +1261,12 @@ fill_pre_wcc(tfhp); #endif /* CONFIG_NFSD_V3 */ - err = vfs_rename(fdir, odentry, tdir, ndentry); + if ((ffhp->fh_export->ex_flags & NFSEXP_MSNFS) && + ((odentry->d_count > 1) || (ndentry->d_count > 1))) { + err = nfserr_perm; + } else { + err = vfs_rename(fdir, odentry, tdir, ndentry); + } if (!err && EX_ISSYNC(tfhp->fh_export)) { nfsd_sync_dir(tdentry); nfsd_sync_dir(fdentry); @@ -1317,7 +1328,12 @@ } if (type != S_IFDIR) { /* It's UNLINK */ - err = vfs_unlink(dirp, rdentry); + if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) && + (rdentry->d_count > 1)) { + err = nfserr_perm; + } else { + err = vfs_unlink(dirp, rdentry); + } } else { /* It's RMDIR */ err = vfs_rmdir(dirp, rdentry); } diff -urNX ../kernels/exclude linux+lock-F/include/linux/fs.h linux+lock/include/linux/fs.h --- linux+lock-F/include/linux/fs.h Wed Jun 14 22:01:04 2000 +++ linux+lock/include/linux/fs.h Thu Jun 15 01:15:09 2000 @@ -549,6 +549,8 @@ extern void posix_block_lock(struct file_lock *, struct file_lock *); extern void posix_unblock_lock(struct file_lock *); extern int __get_lease(struct inode *inode, unsigned int flags); +extern int lock_may_read(struct inode *, loff_t start, unsigned long count); +extern int lock_may_write(struct inode *, loff_t start, unsigned long count); #define FASYNC_MAGIC 0x4601 .