00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "includes.h"
00026
00027 #undef DBGC_CLASS
00028 #define DBGC_CLASS DBGC_LOCKING
00029
00030
00031
00032
00033
00034 static TDB_CONTEXT *posix_pending_close_tdb;
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 static int map_posix_lock_type( files_struct *fsp, enum brl_type lock_type)
00048 {
00049 if((lock_type == WRITE_LOCK) && !fsp->can_write) {
00050
00051
00052
00053
00054
00055 DEBUG(10,("map_posix_lock_type: Downgrading write lock to read due to read-only file.\n"));
00056 return F_RDLCK;
00057 }
00058
00059
00060
00061
00062
00063
00064 return (lock_type == READ_LOCK) ? F_RDLCK : F_WRLCK;
00065 }
00066
00067
00068
00069
00070
00071 static const char *posix_lock_type_name(int lock_type)
00072 {
00073 return (lock_type == F_RDLCK) ? "READ" : "WRITE";
00074 }
00075
00076
00077
00078
00079
00080
00081
00082 static BOOL posix_lock_in_range(SMB_OFF_T *offset_out, SMB_OFF_T *count_out,
00083 SMB_BIG_UINT u_offset, SMB_BIG_UINT u_count)
00084 {
00085 SMB_OFF_T offset = (SMB_OFF_T)u_offset;
00086 SMB_OFF_T count = (SMB_OFF_T)u_count;
00087
00088
00089
00090
00091
00092
00093 #if defined(MAX_POSITIVE_LOCK_OFFSET)
00094
00095 SMB_OFF_T max_positive_lock_offset = (MAX_POSITIVE_LOCK_OFFSET);
00096
00097 #elif defined(LARGE_SMB_OFF_T) && !defined(HAVE_BROKEN_FCNTL64_LOCKS)
00098
00099
00100
00101
00102
00103
00104 SMB_OFF_T mask2 = ((SMB_OFF_T)0x4) << (SMB_OFF_T_BITS-4);
00105 SMB_OFF_T mask = (mask2<<1);
00106 SMB_OFF_T max_positive_lock_offset = ~mask;
00107
00108 #else
00109
00110
00111
00112
00113
00114
00115
00116 SMB_OFF_T max_positive_lock_offset = 0x7FFFFFFF;
00117
00118 #endif
00119
00120
00121
00122
00123
00124
00125
00126 if (count == (SMB_OFF_T)0) {
00127 DEBUG(10,("posix_lock_in_range: count = 0, ignoring.\n"));
00128 return False;
00129 }
00130
00131
00132
00133
00134
00135
00136 if (u_offset & ~((SMB_BIG_UINT)max_positive_lock_offset)) {
00137 DEBUG(10,("posix_lock_in_range: (offset = %.0f) offset > %.0f and we cannot handle this. Ignoring lock.\n",
00138 (double)u_offset, (double)((SMB_BIG_UINT)max_positive_lock_offset) ));
00139 return False;
00140 }
00141
00142
00143
00144
00145
00146 if (u_count & ~((SMB_BIG_UINT)max_positive_lock_offset)) {
00147 count = max_positive_lock_offset;
00148 }
00149
00150
00151
00152
00153
00154 if (offset + count < 0 || offset + count > max_positive_lock_offset) {
00155 count = max_positive_lock_offset - offset;
00156 }
00157
00158
00159
00160
00161
00162 if (count == 0) {
00163 DEBUG(10,("posix_lock_in_range: Count = 0. Ignoring lock u_offset = %.0f, u_count = %.0f\n",
00164 (double)u_offset, (double)u_count ));
00165 return False;
00166 }
00167
00168
00169
00170
00171
00172 DEBUG(10,("posix_lock_in_range: offset_out = %.0f, count_out = %.0f\n",
00173 (double)offset, (double)count ));
00174
00175 *offset_out = offset;
00176 *count_out = count;
00177
00178 return True;
00179 }
00180
00181
00182
00183
00184
00185
00186 static BOOL posix_fcntl_lock(files_struct *fsp, int op, SMB_OFF_T offset, SMB_OFF_T count, int type)
00187 {
00188 BOOL ret;
00189
00190 DEBUG(8,("posix_fcntl_lock %d %d %.0f %.0f %d\n",fsp->fh->fd,op,(double)offset,(double)count,type));
00191
00192 ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
00193
00194 if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) {
00195
00196 DEBUG(0,("posix_fcntl_lock: WARNING: lock request at offset %.0f, length %.0f returned\n",
00197 (double)offset,(double)count));
00198 DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
00199 DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
00200
00201
00202
00203
00204
00205
00206 if (offset & ~((SMB_OFF_T)0x7fffffff)) {
00207 DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
00208 return True;
00209 }
00210
00211 if (count & ~((SMB_OFF_T)0x7fffffff)) {
00212
00213 DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
00214 errno = 0;
00215 count &= 0x7fffffff;
00216 ret = SMB_VFS_LOCK(fsp,fsp->fh->fd,op,offset,count,type);
00217 }
00218 }
00219
00220 DEBUG(8,("posix_fcntl_lock: Lock call %s\n", ret ? "successful" : "failed"));
00221 return ret;
00222 }
00223
00224
00225
00226
00227
00228
00229 static BOOL posix_fcntl_getlock(files_struct *fsp, SMB_OFF_T *poffset, SMB_OFF_T *pcount, int *ptype)
00230 {
00231 pid_t pid;
00232 BOOL ret;
00233
00234 DEBUG(8,("posix_fcntl_getlock %d %.0f %.0f %d\n",
00235 fsp->fh->fd,(double)*poffset,(double)*pcount,*ptype));
00236
00237 ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
00238
00239 if (!ret && ((errno == EFBIG) || (errno == ENOLCK) || (errno == EINVAL))) {
00240
00241 DEBUG(0,("posix_fcntl_getlock: WARNING: lock request at offset %.0f, length %.0f returned\n",
00242 (double)*poffset,(double)*pcount));
00243 DEBUG(0,("an %s error. This can happen when using 64 bit lock offsets\n", strerror(errno)));
00244 DEBUG(0,("on 32 bit NFS mounted file systems.\n"));
00245
00246
00247
00248
00249
00250
00251 if (*poffset & ~((SMB_OFF_T)0x7fffffff)) {
00252 DEBUG(0,("Offset greater than 31 bits. Returning success.\n"));
00253 return True;
00254 }
00255
00256 if (*pcount & ~((SMB_OFF_T)0x7fffffff)) {
00257
00258 DEBUG(0,("Count greater than 31 bits - retrying with 31 bit truncated length.\n"));
00259 errno = 0;
00260 *pcount &= 0x7fffffff;
00261 ret = SMB_VFS_GETLOCK(fsp,fsp->fh->fd,poffset,pcount,ptype,&pid);
00262 }
00263 }
00264
00265 DEBUG(8,("posix_fcntl_getlock: Lock query call %s\n", ret ? "successful" : "failed"));
00266 return ret;
00267 }
00268
00269
00270
00271
00272
00273
00274 BOOL is_posix_locked(files_struct *fsp,
00275 SMB_BIG_UINT *pu_offset,
00276 SMB_BIG_UINT *pu_count,
00277 enum brl_type *plock_type,
00278 enum brl_flavour lock_flav)
00279 {
00280 SMB_OFF_T offset;
00281 SMB_OFF_T count;
00282 int posix_lock_type = map_posix_lock_type(fsp,*plock_type);
00283
00284 DEBUG(10,("is_posix_locked: File %s, offset = %.0f, count = %.0f, type = %s\n",
00285 fsp->fsp_name, (double)*pu_offset, (double)*pu_count, posix_lock_type_name(*plock_type) ));
00286
00287
00288
00289
00290
00291
00292 if(!posix_lock_in_range(&offset, &count, *pu_offset, *pu_count)) {
00293 return False;
00294 }
00295
00296 if (!posix_fcntl_getlock(fsp,&offset,&count,&posix_lock_type)) {
00297 return False;
00298 }
00299
00300 if (posix_lock_type == F_UNLCK) {
00301 return False;
00302 }
00303
00304 if (lock_flav == POSIX_LOCK) {
00305
00306 *pu_offset = (SMB_BIG_UINT)offset;
00307 *pu_count = (SMB_BIG_UINT)count;
00308 *plock_type = (posix_lock_type == F_RDLCK) ? READ_LOCK : WRITE_LOCK;
00309 }
00310 return True;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320 struct lock_ref_count_key {
00321 SMB_DEV_T device;
00322 SMB_INO_T inode;
00323 char r;
00324 };
00325
00326 struct fd_key {
00327 SMB_DEV_T device;
00328 SMB_INO_T inode;
00329 };
00330
00331
00332
00333
00334
00335 static TDB_DATA fd_array_key(SMB_DEV_T dev, SMB_INO_T inode)
00336 {
00337 static struct fd_key key;
00338 TDB_DATA kbuf;
00339
00340 memset(&key, '\0', sizeof(key));
00341 key.device = dev;
00342 key.inode = inode;
00343 kbuf.dptr = (char *)&key;
00344 kbuf.dsize = sizeof(key);
00345 return kbuf;
00346 }
00347
00348
00349
00350
00351
00352 static TDB_DATA locking_ref_count_key(SMB_DEV_T dev, SMB_INO_T inode)
00353 {
00354 static struct lock_ref_count_key key;
00355 TDB_DATA kbuf;
00356
00357 memset(&key, '\0', sizeof(key));
00358 key.device = dev;
00359 key.inode = inode;
00360 key.r = 'r';
00361 kbuf.dptr = (char *)&key;
00362 kbuf.dsize = sizeof(key);
00363 return kbuf;
00364 }
00365
00366
00367
00368
00369
00370 static TDB_DATA fd_array_key_fsp(files_struct *fsp)
00371 {
00372 return fd_array_key(fsp->dev, fsp->inode);
00373 }
00374
00375
00376
00377
00378
00379 static TDB_DATA locking_ref_count_key_fsp(files_struct *fsp)
00380 {
00381 return locking_ref_count_key(fsp->dev, fsp->inode);
00382 }
00383
00384
00385
00386
00387
00388 BOOL posix_locking_init(int read_only)
00389 {
00390 if (posix_pending_close_tdb) {
00391 return True;
00392 }
00393
00394 if (!posix_pending_close_tdb) {
00395 posix_pending_close_tdb = tdb_open_log(NULL, 0, TDB_INTERNAL,
00396 read_only?O_RDONLY:(O_RDWR|O_CREAT), 0644);
00397 }
00398 if (!posix_pending_close_tdb) {
00399 DEBUG(0,("Failed to open POSIX pending close database.\n"));
00400 return False;
00401 }
00402
00403 return True;
00404 }
00405
00406
00407
00408
00409
00410 BOOL posix_locking_end(void)
00411 {
00412 if (posix_pending_close_tdb && tdb_close(posix_pending_close_tdb) != 0) {
00413 return False;
00414 }
00415 return True;
00416 }
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 static void increment_windows_lock_ref_count(files_struct *fsp)
00438 {
00439 TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
00440 TDB_DATA dbuf;
00441 int lock_ref_count;
00442
00443 dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
00444 if (dbuf.dptr == NULL) {
00445 dbuf.dptr = (char *)SMB_MALLOC_P(int);
00446 if (!dbuf.dptr) {
00447 smb_panic("increment_windows_lock_ref_count: malloc fail.\n");
00448 }
00449 memset(dbuf.dptr, '\0', sizeof(int));
00450 dbuf.dsize = sizeof(int);
00451 }
00452
00453 memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
00454 lock_ref_count++;
00455 memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
00456
00457 if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
00458 smb_panic("increment_windows_lock_ref_count: tdb_store_fail.\n");
00459 }
00460 SAFE_FREE(dbuf.dptr);
00461
00462 DEBUG(10,("increment_windows_lock_ref_count for file now %s = %d\n",
00463 fsp->fsp_name, lock_ref_count ));
00464 }
00465
00466 static void decrement_windows_lock_ref_count(files_struct *fsp)
00467 {
00468 TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
00469 TDB_DATA dbuf;
00470 int lock_ref_count;
00471
00472 dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
00473 if (!dbuf.dptr) {
00474 smb_panic("decrement_windows_lock_ref_count: logic error.\n");
00475 }
00476
00477 memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
00478 lock_ref_count--;
00479 memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
00480
00481 if (lock_ref_count < 0) {
00482 smb_panic("decrement_windows_lock_ref_count: lock_count logic error.\n");
00483 }
00484
00485 if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
00486 smb_panic("decrement_windows_lock_ref_count: tdb_store_fail.\n");
00487 }
00488 SAFE_FREE(dbuf.dptr);
00489
00490 DEBUG(10,("decrement_windows_lock_ref_count for file now %s = %d\n",
00491 fsp->fsp_name, lock_ref_count ));
00492 }
00493
00494
00495
00496
00497
00498 void reduce_windows_lock_ref_count(files_struct *fsp, unsigned int dcount)
00499 {
00500 TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
00501 TDB_DATA dbuf;
00502 int lock_ref_count;
00503
00504 dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
00505 if (!dbuf.dptr) {
00506 return;
00507 }
00508
00509 memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
00510 lock_ref_count -= dcount;
00511
00512 if (lock_ref_count < 0) {
00513 smb_panic("reduce_windows_lock_ref_count: lock_count logic error.\n");
00514 }
00515 memcpy(dbuf.dptr, &lock_ref_count, sizeof(int));
00516
00517 if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
00518 smb_panic("reduce_windows_lock_ref_count: tdb_store_fail.\n");
00519 }
00520 SAFE_FREE(dbuf.dptr);
00521
00522 DEBUG(10,("reduce_windows_lock_ref_count for file now %s = %d\n",
00523 fsp->fsp_name, lock_ref_count ));
00524 }
00525
00526
00527
00528
00529
00530 static int get_windows_lock_ref_count(files_struct *fsp)
00531 {
00532 TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
00533 TDB_DATA dbuf;
00534 int lock_ref_count;
00535
00536 dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
00537 if (!dbuf.dptr) {
00538 lock_ref_count = 0;
00539 } else {
00540 memcpy(&lock_ref_count, dbuf.dptr, sizeof(int));
00541 }
00542 SAFE_FREE(dbuf.dptr);
00543
00544 DEBUG(10,("get_windows_lock_count for file %s = %d\n",
00545 fsp->fsp_name, lock_ref_count ));
00546 return lock_ref_count;
00547 }
00548
00549
00550
00551
00552
00553 static void delete_windows_lock_ref_count(files_struct *fsp)
00554 {
00555 TDB_DATA kbuf = locking_ref_count_key_fsp(fsp);
00556
00557
00558 tdb_delete(posix_pending_close_tdb, kbuf);
00559 DEBUG(10,("delete_windows_lock_ref_count for file %s\n", fsp->fsp_name));
00560 }
00561
00562
00563
00564
00565
00566 static void add_fd_to_close_entry(files_struct *fsp)
00567 {
00568 TDB_DATA kbuf = fd_array_key_fsp(fsp);
00569 TDB_DATA dbuf;
00570
00571 dbuf.dptr = NULL;
00572 dbuf.dsize = 0;
00573
00574 dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
00575
00576 dbuf.dptr = (char *)SMB_REALLOC(dbuf.dptr, dbuf.dsize + sizeof(int));
00577 if (!dbuf.dptr) {
00578 smb_panic("add_fd_to_close_entry: Realloc fail !\n");
00579 }
00580
00581 memcpy(dbuf.dptr + dbuf.dsize, &fsp->fh->fd, sizeof(int));
00582 dbuf.dsize += sizeof(int);
00583
00584 if (tdb_store(posix_pending_close_tdb, kbuf, dbuf, TDB_REPLACE) == -1) {
00585 smb_panic("add_fd_to_close_entry: tdb_store_fail.\n");
00586 }
00587
00588 DEBUG(10,("add_fd_to_close_entry: added fd %d file %s\n",
00589 fsp->fh->fd, fsp->fsp_name ));
00590
00591 SAFE_FREE(dbuf.dptr);
00592 }
00593
00594
00595
00596
00597
00598 static void delete_close_entries(files_struct *fsp)
00599 {
00600 TDB_DATA kbuf = fd_array_key_fsp(fsp);
00601
00602 if (tdb_delete(posix_pending_close_tdb, kbuf) == -1) {
00603 smb_panic("delete_close_entries: tdb_delete fail !\n");
00604 }
00605 }
00606
00607
00608
00609
00610
00611
00612 static size_t get_posix_pending_close_entries(files_struct *fsp, int **entries)
00613 {
00614 TDB_DATA kbuf = fd_array_key_fsp(fsp);
00615 TDB_DATA dbuf;
00616 size_t count = 0;
00617
00618 *entries = NULL;
00619 dbuf.dptr = NULL;
00620
00621 dbuf = tdb_fetch(posix_pending_close_tdb, kbuf);
00622
00623 if (!dbuf.dptr) {
00624 return 0;
00625 }
00626
00627 *entries = (int *)dbuf.dptr;
00628 count = (size_t)(dbuf.dsize / sizeof(int));
00629
00630 return count;
00631 }
00632
00633
00634
00635
00636
00637
00638
00639 NTSTATUS fd_close_posix(struct connection_struct *conn, files_struct *fsp)
00640 {
00641 int saved_errno = 0;
00642 int ret;
00643 int *fd_array = NULL;
00644 size_t count, i;
00645
00646 if (!lp_locking(fsp->conn->params) || !lp_posix_locking(conn->params)) {
00647
00648
00649
00650
00651
00652 ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
00653 fsp->fh->fd = -1;
00654 if (ret == -1) {
00655 return map_nt_error_from_unix(errno);
00656 }
00657 return NT_STATUS_OK;
00658 }
00659
00660 if (get_windows_lock_ref_count(fsp)) {
00661
00662
00663
00664
00665
00666
00667 add_fd_to_close_entry(fsp);
00668 fsp->fh->fd = -1;
00669 return NT_STATUS_OK;
00670 }
00671
00672
00673
00674
00675
00676
00677 count = get_posix_pending_close_entries(fsp, &fd_array);
00678
00679 if (count) {
00680 DEBUG(10,("fd_close_posix: doing close on %u fd's.\n", (unsigned int)count ));
00681
00682 for(i = 0; i < count; i++) {
00683 if (SMB_VFS_CLOSE(fsp,fd_array[i]) == -1) {
00684 saved_errno = errno;
00685 }
00686 }
00687
00688
00689
00690
00691
00692
00693 delete_close_entries(fsp);
00694 }
00695
00696 SAFE_FREE(fd_array);
00697
00698
00699 delete_windows_lock_ref_count(fsp);
00700
00701
00702
00703
00704
00705 ret = SMB_VFS_CLOSE(fsp,fsp->fh->fd);
00706
00707 if (ret == 0 && saved_errno != 0) {
00708 errno = saved_errno;
00709 ret = -1;
00710 }
00711
00712 fsp->fh->fd = -1;
00713
00714 if (ret == -1) {
00715 return map_nt_error_from_unix(errno);
00716 }
00717
00718 return NT_STATUS_OK;
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731 struct lock_list {
00732 struct lock_list *next;
00733 struct lock_list *prev;
00734 SMB_OFF_T start;
00735 SMB_OFF_T size;
00736 };
00737
00738
00739
00740
00741
00742
00743
00744 static struct lock_list *posix_lock_list(TALLOC_CTX *ctx,
00745 struct lock_list *lhead,
00746 const struct lock_context *lock_ctx,
00747 files_struct *fsp,
00748 const struct lock_struct *plocks,
00749 int num_locks)
00750 {
00751 int i;
00752
00753
00754
00755
00756
00757
00758 DEBUG(10,("posix_lock_list: curr: start=%.0f,size=%.0f\n",
00759 (double)lhead->start, (double)lhead->size ));
00760
00761 for (i=0; i<num_locks && lhead; i++) {
00762 const struct lock_struct *lock = &plocks[i];
00763 struct lock_list *l_curr;
00764
00765
00766 if (lock->lock_type != READ_LOCK && lock->lock_type != WRITE_LOCK) {
00767 continue;
00768 }
00769
00770
00771 if (!procid_equal(&lock->context.pid, &lock_ctx->pid)) {
00772 continue;
00773 }
00774
00775
00776
00777
00778
00779
00780
00781 for (l_curr = lhead; l_curr;) {
00782
00783 DEBUG(10,("posix_lock_list: lock: fnum=%d: start=%.0f,size=%.0f:type=%s", lock->fnum,
00784 (double)lock->start, (double)lock->size, posix_lock_type_name(lock->lock_type) ));
00785
00786 if ( (l_curr->start >= (lock->start + lock->size)) ||
00787 (lock->start >= (l_curr->start + l_curr->size))) {
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803 DEBUG(10,(" no overlap case.\n" ));
00804
00805 l_curr = l_curr->next;
00806
00807 } else if ( (l_curr->start >= lock->start) &&
00808 (l_curr->start + l_curr->size <= lock->start + lock->size) ) {
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823 struct lock_list *ul_next = l_curr->next;
00824
00825 DEBUG(10,(" delete case.\n" ));
00826
00827 DLIST_REMOVE(lhead, l_curr);
00828 if(lhead == NULL) {
00829 break;
00830 }
00831
00832 l_curr = ul_next;
00833
00834 } else if ( (l_curr->start >= lock->start) &&
00835 (l_curr->start < lock->start + lock->size) &&
00836 (l_curr->start + l_curr->size > lock->start + lock->size) ) {
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 l_curr->size = (l_curr->start + l_curr->size) - (lock->start + lock->size);
00856 l_curr->start = lock->start + lock->size;
00857
00858 DEBUG(10,(" truncate high case: start=%.0f,size=%.0f\n",
00859 (double)l_curr->start, (double)l_curr->size ));
00860
00861 l_curr = l_curr->next;
00862
00863 } else if ( (l_curr->start < lock->start) &&
00864 (l_curr->start + l_curr->size > lock->start) &&
00865 (l_curr->start + l_curr->size <= lock->start + lock->size) ) {
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884 l_curr->size = lock->start - l_curr->start;
00885
00886 DEBUG(10,(" truncate low case: start=%.0f,size=%.0f\n",
00887 (double)l_curr->start, (double)l_curr->size ));
00888
00889 l_curr = l_curr->next;
00890
00891 } else if ( (l_curr->start < lock->start) &&
00892 (l_curr->start + l_curr->size > lock->start + lock->size) ) {
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911 struct lock_list *l_new = TALLOC_P(ctx, struct lock_list);
00912
00913 if(l_new == NULL) {
00914 DEBUG(0,("posix_lock_list: talloc fail.\n"));
00915 return NULL;
00916 }
00917
00918 ZERO_STRUCTP(l_new);
00919 l_new->start = lock->start + lock->size;
00920 l_new->size = l_curr->start + l_curr->size - l_new->start;
00921
00922
00923 l_curr->size = lock->start - l_curr->start;
00924
00925 DEBUG(10,(" split case: curr: start=%.0f,size=%.0f \
00926 new: start=%.0f,size=%.0f\n", (double)l_curr->start, (double)l_curr->size,
00927 (double)l_new->start, (double)l_new->size ));
00928
00929
00930
00931
00932
00933
00934 l_new->prev = l_curr;
00935 l_new->next = l_curr->next;
00936 l_curr->next = l_new;
00937
00938
00939 l_curr = l_new->next;
00940
00941 } else {
00942
00943
00944
00945
00946
00947 pstring msg;
00948
00949 slprintf(msg, sizeof(msg)-1, "logic flaw in cases: l_curr: start = %.0f, size = %.0f : \
00950 lock: start = %.0f, size = %.0f\n", (double)l_curr->start, (double)l_curr->size, (double)lock->start, (double)lock->size );
00951
00952 smb_panic(msg);
00953 }
00954 }
00955 }
00956
00957 return lhead;
00958 }
00959
00960
00961
00962
00963
00964
00965 BOOL set_posix_lock_windows_flavour(files_struct *fsp,
00966 SMB_BIG_UINT u_offset,
00967 SMB_BIG_UINT u_count,
00968 enum brl_type lock_type,
00969 const struct lock_context *lock_ctx,
00970 const struct lock_struct *plocks,
00971 int num_locks,
00972 int *errno_ret)
00973 {
00974 SMB_OFF_T offset;
00975 SMB_OFF_T count;
00976 int posix_lock_type = map_posix_lock_type(fsp,lock_type);
00977 BOOL ret = True;
00978 size_t lock_count;
00979 TALLOC_CTX *l_ctx = NULL;
00980 struct lock_list *llist = NULL;
00981 struct lock_list *ll = NULL;
00982
00983 DEBUG(5,("set_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n",
00984 fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
00985
00986
00987
00988
00989
00990
00991 if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
00992 increment_windows_lock_ref_count(fsp);
00993 return True;
00994 }
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014 if ((l_ctx = talloc_init("set_posix_lock")) == NULL) {
01015 DEBUG(0,("set_posix_lock_windows_flavour: unable to init talloc context.\n"));
01016 return False;
01017 }
01018
01019 if ((ll = TALLOC_P(l_ctx, struct lock_list)) == NULL) {
01020 DEBUG(0,("set_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
01021 talloc_destroy(l_ctx);
01022 return False;
01023 }
01024
01025
01026
01027
01028
01029
01030 ZERO_STRUCTP(ll);
01031 ll->start = offset;
01032 ll->size = count;
01033
01034 DLIST_ADD(llist, ll);
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044 llist = posix_lock_list(l_ctx,
01045 llist,
01046 lock_ctx,
01047 fsp,
01048 plocks,
01049 num_locks);
01050
01051
01052
01053
01054
01055
01056
01057 for (lock_count = 0, ll = llist; ll; ll = ll->next, lock_count++) {
01058 offset = ll->start;
01059 count = ll->size;
01060
01061 DEBUG(5,("set_posix_lock_windows_flavour: Real lock: Type = %s: offset = %.0f, count = %.0f\n",
01062 posix_lock_type_name(posix_lock_type), (double)offset, (double)count ));
01063
01064 if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) {
01065 *errno_ret = errno;
01066 DEBUG(5,("set_posix_lock_windows_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",
01067 posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) ));
01068 ret = False;
01069 break;
01070 }
01071 }
01072
01073 if (!ret) {
01074
01075
01076
01077
01078
01079 for (ll = llist; lock_count; ll = ll->next, lock_count--) {
01080 offset = ll->start;
01081 count = ll->size;
01082
01083 DEBUG(5,("set_posix_lock_windows_flavour: Backing out locks: Type = %s: offset = %.0f, count = %.0f\n",
01084 posix_lock_type_name(posix_lock_type), (double)offset, (double)count ));
01085
01086 posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK);
01087 }
01088 } else {
01089
01090 increment_windows_lock_ref_count(fsp);
01091 }
01092
01093 talloc_destroy(l_ctx);
01094 return ret;
01095 }
01096
01097
01098
01099
01100
01101
01102 BOOL release_posix_lock_windows_flavour(files_struct *fsp,
01103 SMB_BIG_UINT u_offset,
01104 SMB_BIG_UINT u_count,
01105 enum brl_type deleted_lock_type,
01106 const struct lock_context *lock_ctx,
01107 const struct lock_struct *plocks,
01108 int num_locks)
01109 {
01110 SMB_OFF_T offset;
01111 SMB_OFF_T count;
01112 BOOL ret = True;
01113 TALLOC_CTX *ul_ctx = NULL;
01114 struct lock_list *ulist = NULL;
01115 struct lock_list *ul = NULL;
01116
01117 DEBUG(5,("release_posix_lock_windows_flavour: File %s, offset = %.0f, count = %.0f\n",
01118 fsp->fsp_name, (double)u_offset, (double)u_count ));
01119
01120
01121 decrement_windows_lock_ref_count(fsp);
01122
01123
01124
01125
01126
01127
01128 if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
01129 return True;
01130 }
01131
01132 if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) {
01133 DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n"));
01134 return False;
01135 }
01136
01137 if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) {
01138 DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
01139 talloc_destroy(ul_ctx);
01140 return False;
01141 }
01142
01143
01144
01145
01146
01147
01148 ZERO_STRUCTP(ul);
01149 ul->start = offset;
01150 ul->size = count;
01151
01152 DLIST_ADD(ulist, ul);
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163 ulist = posix_lock_list(ul_ctx,
01164 ulist,
01165 lock_ctx,
01166 fsp,
01167 plocks,
01168 num_locks);
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178 if (deleted_lock_type == WRITE_LOCK &&
01179 (!ulist || ulist->next != NULL || ulist->start != offset || ulist->size != count)) {
01180
01181 DEBUG(5,("release_posix_lock_windows_flavour: downgrading lock to READ: offset = %.0f, count = %.0f\n",
01182 (double)offset, (double)count ));
01183
01184 if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_RDLCK)) {
01185 DEBUG(0,("release_posix_lock_windows_flavour: downgrade of lock failed with error %s !\n", strerror(errno) ));
01186 talloc_destroy(ul_ctx);
01187 return False;
01188 }
01189 }
01190
01191
01192
01193
01194
01195 for(; ulist; ulist = ulist->next) {
01196 offset = ulist->start;
01197 count = ulist->size;
01198
01199 DEBUG(5,("release_posix_lock_windows_flavour: Real unlock: offset = %.0f, count = %.0f\n",
01200 (double)offset, (double)count ));
01201
01202 if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) {
01203 ret = False;
01204 }
01205 }
01206
01207 talloc_destroy(ul_ctx);
01208 return ret;
01209 }
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 BOOL set_posix_lock_posix_flavour(files_struct *fsp,
01226 SMB_BIG_UINT u_offset,
01227 SMB_BIG_UINT u_count,
01228 enum brl_type lock_type,
01229 int *errno_ret)
01230 {
01231 SMB_OFF_T offset;
01232 SMB_OFF_T count;
01233 int posix_lock_type = map_posix_lock_type(fsp,lock_type);
01234
01235 DEBUG(5,("set_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f, type = %s\n",
01236 fsp->fsp_name, (double)u_offset, (double)u_count, posix_lock_type_name(lock_type) ));
01237
01238
01239
01240
01241
01242
01243 if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
01244 return True;
01245 }
01246
01247 if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,posix_lock_type)) {
01248 *errno_ret = errno;
01249 DEBUG(5,("set_posix_lock_posix_flavour: Lock fail !: Type = %s: offset = %.0f, count = %.0f. Errno = %s\n",
01250 posix_lock_type_name(posix_lock_type), (double)offset, (double)count, strerror(errno) ));
01251 return False;
01252 }
01253 return True;
01254 }
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265 BOOL release_posix_lock_posix_flavour(files_struct *fsp,
01266 SMB_BIG_UINT u_offset,
01267 SMB_BIG_UINT u_count,
01268 const struct lock_context *lock_ctx,
01269 const struct lock_struct *plocks,
01270 int num_locks)
01271 {
01272 BOOL ret = True;
01273 SMB_OFF_T offset;
01274 SMB_OFF_T count;
01275 TALLOC_CTX *ul_ctx = NULL;
01276 struct lock_list *ulist = NULL;
01277 struct lock_list *ul = NULL;
01278
01279 DEBUG(5,("release_posix_lock_posix_flavour: File %s, offset = %.0f, count = %.0f\n",
01280 fsp->fsp_name, (double)u_offset, (double)u_count ));
01281
01282
01283
01284
01285
01286
01287 if(!posix_lock_in_range(&offset, &count, u_offset, u_count)) {
01288 return True;
01289 }
01290
01291 if ((ul_ctx = talloc_init("release_posix_lock")) == NULL) {
01292 DEBUG(0,("release_posix_lock_windows_flavour: unable to init talloc context.\n"));
01293 return False;
01294 }
01295
01296 if ((ul = TALLOC_P(ul_ctx, struct lock_list)) == NULL) {
01297 DEBUG(0,("release_posix_lock_windows_flavour: unable to talloc unlock list.\n"));
01298 talloc_destroy(ul_ctx);
01299 return False;
01300 }
01301
01302
01303
01304
01305
01306
01307 ZERO_STRUCTP(ul);
01308 ul->start = offset;
01309 ul->size = count;
01310
01311 DLIST_ADD(ulist, ul);
01312
01313
01314
01315
01316
01317
01318 ulist = posix_lock_list(ul_ctx,
01319 ulist,
01320 lock_ctx,
01321 fsp,
01322 plocks,
01323 num_locks);
01324
01325
01326
01327
01328
01329 for(; ulist; ulist = ulist->next) {
01330 offset = ulist->start;
01331 count = ulist->size;
01332
01333 DEBUG(5,("release_posix_lock_posix_flavour: Real unlock: offset = %.0f, count = %.0f\n",
01334 (double)offset, (double)count ));
01335
01336 if (!posix_fcntl_lock(fsp,SMB_F_SETLK,offset,count,F_UNLCK)) {
01337 ret = False;
01338 }
01339 }
01340
01341 talloc_destroy(ul_ctx);
01342 return ret;
01343 }