1/* 2 Unix SMB/CIFS implementation. 3 Files[] structure handling 4 Copyright (C) Andrew Tridgell 1998 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18*/ 19 20#include "includes.h" 21#include "smbd/globals.h" 22 23#define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < real_max_open_files)) 24 25#define FILE_HANDLE_OFFSET 0x1000 26 27/**************************************************************************** 28 Return a unique number identifying this fsp over the life of this pid. 29****************************************************************************/ 30 31static unsigned long get_gen_count(void) 32{ 33 if ((++file_gen_counter) == 0) 34 return ++file_gen_counter; 35 return file_gen_counter; 36} 37 38/**************************************************************************** 39 Find first available file slot. 40****************************************************************************/ 41 42NTSTATUS file_new(struct smb_request *req, connection_struct *conn, 43 files_struct **result) 44{ 45 int i; 46 files_struct *fsp; 47 NTSTATUS status; 48 49 /* we want to give out file handles differently on each new 50 connection because of a common bug in MS clients where they try to 51 reuse a file descriptor from an earlier smb connection. This code 52 increases the chance that the errant client will get an error rather 53 than causing corruption */ 54 if (first_file == 0) { 55 first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files; 56 } 57 58 /* TODO: Port the id-tree implementation from Samba4 */ 59 60 i = bitmap_find(file_bmap, first_file); 61 if (i == -1) { 62 DEBUG(0,("ERROR! Out of file structures\n")); 63 /* TODO: We have to unconditionally return a DOS error here, 64 * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with 65 * NTSTATUS negotiated */ 66 return NT_STATUS_TOO_MANY_OPENED_FILES; 67 } 68 69 /* 70 * Make a child of the connection_struct as an fsp can't exist 71 * indepenedent of a connection. 72 */ 73 fsp = talloc_zero(conn, struct files_struct); 74 if (!fsp) { 75 return NT_STATUS_NO_MEMORY; 76 } 77 78 /* 79 * This can't be a child of fsp because the file_handle can be ref'd 80 * when doing a dos/fcb open, which will then share the file_handle 81 * across multiple fsps. 82 */ 83 fsp->fh = talloc_zero(conn, struct fd_handle); 84 if (!fsp->fh) { 85 TALLOC_FREE(fsp); 86 return NT_STATUS_NO_MEMORY; 87 } 88 89 fsp->fh->ref_count = 1; 90 fsp->fh->fd = -1; 91 92 fsp->conn = conn; 93 fsp->fh->gen_id = get_gen_count(); 94 GetTimeOfDay(&fsp->open_time); 95 96 first_file = (i+1) % real_max_open_files; 97 98 bitmap_set(file_bmap, i); 99 files_used++; 100 101 fsp->fnum = i + FILE_HANDLE_OFFSET; 102 SMB_ASSERT(fsp->fnum < 65536); 103 104 /* 105 * Create an smb_filename with "" for the base_name. There are very 106 * few NULL checks, so make sure it's initialized with something. to 107 * be safe until an audit can be done. 108 */ 109 status = create_synthetic_smb_fname(fsp, "", NULL, NULL, 110 &fsp->fsp_name); 111 if (!NT_STATUS_IS_OK(status)) { 112 TALLOC_FREE(fsp); 113 TALLOC_FREE(fsp->fh); 114 } 115 116 DLIST_ADD(Files, fsp); 117 118 DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n", 119 i, fsp->fnum, files_used)); 120 121 if (req != NULL) { 122 req->chain_fsp = fsp; 123 } 124 125 /* A new fsp invalidates the positive and 126 negative fsp_fi_cache as the new fsp is pushed 127 at the start of the list and we search from 128 a cache hit to the *end* of the list. */ 129 130 ZERO_STRUCT(fsp_fi_cache); 131 132 conn->num_files_open++; 133 134 *result = fsp; 135 return NT_STATUS_OK; 136} 137 138/**************************************************************************** 139 Close all open files for a connection. 140****************************************************************************/ 141 142void file_close_conn(connection_struct *conn) 143{ 144 files_struct *fsp, *next; 145 146 for (fsp=Files;fsp;fsp=next) { 147 next = fsp->next; 148 if (fsp->conn == conn) { 149 close_file(NULL, fsp, SHUTDOWN_CLOSE); 150 } 151 } 152} 153 154/**************************************************************************** 155 Close all open files for a pid and a vuid. 156****************************************************************************/ 157 158void file_close_pid(uint16 smbpid, int vuid) 159{ 160 files_struct *fsp, *next; 161 162 for (fsp=Files;fsp;fsp=next) { 163 next = fsp->next; 164 if ((fsp->file_pid == smbpid) && (fsp->vuid == vuid)) { 165 close_file(NULL, fsp, SHUTDOWN_CLOSE); 166 } 167 } 168} 169 170/**************************************************************************** 171 Initialise file structures. 172****************************************************************************/ 173 174void file_init(void) 175{ 176 int request_max_open_files = lp_max_open_files(); 177 int real_lim; 178 179 /* 180 * Set the max_open files to be the requested 181 * max plus a fudgefactor to allow for the extra 182 * fd's we need such as log files etc... 183 */ 184 real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR); 185 186 real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR; 187 188 if (real_max_open_files + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536) 189 real_max_open_files = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES; 190 191 if(real_max_open_files != request_max_open_files) { 192 DEBUG(1,("file_init: Information only: requested %d \ 193open files, %d are available.\n", request_max_open_files, real_max_open_files)); 194 } 195 196 SMB_ASSERT(real_max_open_files > 100); 197 198 file_bmap = bitmap_allocate(real_max_open_files); 199 200 if (!file_bmap) { 201 exit_server("out of memory in file_init"); 202 } 203} 204 205/**************************************************************************** 206 Close files open by a specified vuid. 207****************************************************************************/ 208 209void file_close_user(int vuid) 210{ 211 files_struct *fsp, *next; 212 213 for (fsp=Files;fsp;fsp=next) { 214 next=fsp->next; 215 if (fsp->vuid == vuid) { 216 close_file(NULL, fsp, SHUTDOWN_CLOSE); 217 } 218 } 219} 220 221/* 222 * Walk the files table until "fn" returns non-NULL 223 */ 224 225struct files_struct *file_walk_table( 226 struct files_struct *(*fn)(struct files_struct *fsp, 227 void *private_data), 228 void *private_data) 229{ 230 struct files_struct *fsp, *next; 231 232 for (fsp = Files; fsp; fsp = next) { 233 struct files_struct *ret; 234 next = fsp->next; 235 ret = fn(fsp, private_data); 236 if (ret != NULL) { 237 return ret; 238 } 239 } 240 return NULL; 241} 242 243/**************************************************************************** 244 Debug to enumerate all open files in the smbd. 245****************************************************************************/ 246 247void file_dump_open_table(void) 248{ 249 int count=0; 250 files_struct *fsp; 251 252 for (fsp=Files;fsp;fsp=fsp->next,count++) { 253 DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, gen = %lu, " 254 "fileid=%s\n", count, fsp->fnum, fsp_str_dbg(fsp), 255 fsp->fh->fd, (unsigned long)fsp->fh->gen_id, 256 file_id_string_tos(&fsp->file_id))); 257 } 258} 259 260/**************************************************************************** 261 Find a fsp given a file descriptor. 262****************************************************************************/ 263 264files_struct *file_find_fd(int fd) 265{ 266 int count=0; 267 files_struct *fsp; 268 269 for (fsp=Files;fsp;fsp=fsp->next,count++) { 270 if (fsp->fh->fd == fd) { 271 if (count > 10) { 272 DLIST_PROMOTE(Files, fsp); 273 } 274 return fsp; 275 } 276 } 277 278 return NULL; 279} 280 281/**************************************************************************** 282 Find a fsp given a device, inode and file_id. 283****************************************************************************/ 284 285files_struct *file_find_dif(struct file_id id, unsigned long gen_id) 286{ 287 int count=0; 288 files_struct *fsp; 289 290 for (fsp=Files;fsp;fsp=fsp->next,count++) { 291 /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */ 292 if (file_id_equal(&fsp->file_id, &id) && 293 fsp->fh->gen_id == gen_id ) { 294 if (count > 10) { 295 DLIST_PROMOTE(Files, fsp); 296 } 297 /* Paranoia check. */ 298 if ((fsp->fh->fd == -1) && 299 (fsp->oplock_type != NO_OPLOCK) && 300 (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { 301 DEBUG(0,("file_find_dif: file %s file_id = " 302 "%s, gen = %u oplock_type = %u is a " 303 "stat open with oplock type !\n", 304 fsp_str_dbg(fsp), 305 file_id_string_tos(&fsp->file_id), 306 (unsigned int)fsp->fh->gen_id, 307 (unsigned int)fsp->oplock_type )); 308 smb_panic("file_find_dif"); 309 } 310 return fsp; 311 } 312 } 313 314 return NULL; 315} 316 317/**************************************************************************** 318 Check if an fsp still exists. 319****************************************************************************/ 320 321files_struct *file_find_fsp(files_struct *orig_fsp) 322{ 323 files_struct *fsp; 324 325 for (fsp=Files;fsp;fsp=fsp->next) { 326 if (fsp == orig_fsp) 327 return fsp; 328 } 329 330 return NULL; 331} 332 333/**************************************************************************** 334 Find the first fsp given a device and inode. 335 We use a singleton cache here to speed up searching from getfilepathinfo 336 calls. 337****************************************************************************/ 338 339files_struct *file_find_di_first(struct file_id id) 340{ 341 files_struct *fsp; 342 343 if (file_id_equal(&fsp_fi_cache.id, &id)) { 344 /* Positive or negative cache hit. */ 345 return fsp_fi_cache.fsp; 346 } 347 348 fsp_fi_cache.id = id; 349 350 for (fsp=Files;fsp;fsp=fsp->next) { 351 if (file_id_equal(&fsp->file_id, &id)) { 352 /* Setup positive cache. */ 353 fsp_fi_cache.fsp = fsp; 354 return fsp; 355 } 356 } 357 358 /* Setup negative cache. */ 359 fsp_fi_cache.fsp = NULL; 360 return NULL; 361} 362 363/**************************************************************************** 364 Find the next fsp having the same device and inode. 365****************************************************************************/ 366 367files_struct *file_find_di_next(files_struct *start_fsp) 368{ 369 files_struct *fsp; 370 371 for (fsp = start_fsp->next;fsp;fsp=fsp->next) { 372 if (file_id_equal(&fsp->file_id, &start_fsp->file_id)) { 373 return fsp; 374 } 375 } 376 377 return NULL; 378} 379 380/**************************************************************************** 381 Find a fsp that is open for printing. 382****************************************************************************/ 383 384files_struct *file_find_print(void) 385{ 386 files_struct *fsp; 387 388 for (fsp=Files;fsp;fsp=fsp->next) { 389 if (fsp->print_file) { 390 return fsp; 391 } 392 } 393 394 return NULL; 395} 396 397/**************************************************************************** 398 Find any fsp open with a pathname below that of an already open path. 399****************************************************************************/ 400 401bool file_find_subpath(files_struct *dir_fsp) 402{ 403 files_struct *fsp; 404 size_t dlen; 405 char *d_fullname = NULL; 406 407 d_fullname = talloc_asprintf(talloc_tos(), "%s/%s", 408 dir_fsp->conn->connectpath, 409 dir_fsp->fsp_name->base_name); 410 411 if (!d_fullname) { 412 return false; 413 } 414 415 dlen = strlen(d_fullname); 416 417 for (fsp=Files;fsp;fsp=fsp->next) { 418 char *d1_fullname; 419 420 if (fsp == dir_fsp) { 421 continue; 422 } 423 424 d1_fullname = talloc_asprintf(talloc_tos(), 425 "%s/%s", 426 fsp->conn->connectpath, 427 fsp->fsp_name->base_name); 428 429 /* 430 * If the open file has a path that is a longer 431 * component, then it's a subpath. 432 */ 433 if (strnequal(d_fullname, d1_fullname, dlen) && 434 (d1_fullname[dlen] == '/')) { 435 TALLOC_FREE(d1_fullname); 436 TALLOC_FREE(d_fullname); 437 return true; 438 } 439 TALLOC_FREE(d1_fullname); 440 } 441 442 TALLOC_FREE(d_fullname); 443 return false; 444} 445 446/**************************************************************************** 447 Sync open files on a connection. 448****************************************************************************/ 449 450void file_sync_all(connection_struct *conn) 451{ 452 files_struct *fsp, *next; 453 454 for (fsp=Files;fsp;fsp=next) { 455 next=fsp->next; 456 if ((conn == fsp->conn) && (fsp->fh->fd != -1)) { 457 sync_file(conn, fsp, True /* write through */); 458 } 459 } 460} 461 462/**************************************************************************** 463 Free up a fsp. 464****************************************************************************/ 465 466void file_free(struct smb_request *req, files_struct *fsp) 467{ 468 DLIST_REMOVE(Files, fsp); 469 470 TALLOC_FREE(fsp->fake_file_handle); 471 472 if (fsp->fh->ref_count == 1) { 473 TALLOC_FREE(fsp->fh); 474 } else { 475 fsp->fh->ref_count--; 476 } 477 478 if (fsp->notify) { 479 if (fsp->is_directory) { 480 notify_remove_onelevel(fsp->conn->notify_ctx, 481 &fsp->file_id, fsp); 482 } 483 notify_remove(fsp->conn->notify_ctx, fsp); 484 TALLOC_FREE(fsp->notify); 485 } 486 487 /* Ensure this event will never fire. */ 488 TALLOC_FREE(fsp->oplock_timeout); 489 490 /* Ensure this event will never fire. */ 491 TALLOC_FREE(fsp->update_write_time_event); 492 493 bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); 494 files_used--; 495 496 DEBUG(5,("freed files structure %d (%d used)\n", 497 fsp->fnum, files_used)); 498 499 fsp->conn->num_files_open--; 500 501 if ((req != NULL) && (fsp == req->chain_fsp)) { 502 req->chain_fsp = NULL; 503 } 504 505 /* Closing a file can invalidate the positive cache. */ 506 if (fsp == fsp_fi_cache.fsp) { 507 ZERO_STRUCT(fsp_fi_cache); 508 } 509 510 /* Drop all remaining extensions. */ 511 while (fsp->vfs_extension) { 512 vfs_remove_fsp_extension(fsp->vfs_extension->owner, fsp); 513 } 514 515 /* this is paranoia, just in case someone tries to reuse the 516 information */ 517 ZERO_STRUCTP(fsp); 518 519 /* fsp->fsp_name is a talloc child and is free'd automatically. */ 520 TALLOC_FREE(fsp); 521} 522 523/**************************************************************************** 524 Get an fsp from a 16 bit fnum. 525****************************************************************************/ 526 527files_struct *file_fnum(uint16 fnum) 528{ 529 files_struct *fsp; 530 int count=0; 531 532 for (fsp=Files;fsp;fsp=fsp->next, count++) { 533 if (fsp->fnum == fnum) { 534 if (count > 10) { 535 DLIST_PROMOTE(Files, fsp); 536 } 537 return fsp; 538 } 539 } 540 return NULL; 541} 542 543/**************************************************************************** 544 Get an fsp from a packet given the offset of a 16 bit fnum. 545****************************************************************************/ 546 547files_struct *file_fsp(struct smb_request *req, uint16 fid) 548{ 549 files_struct *fsp; 550 551 if ((req != NULL) && (req->chain_fsp != NULL)) { 552 return req->chain_fsp; 553 } 554 555 fsp = file_fnum(fid); 556 if ((fsp != NULL) && (req != NULL)) { 557 req->chain_fsp = fsp; 558 } 559 return fsp; 560} 561 562/**************************************************************************** 563 Duplicate the file handle part for a DOS or FCB open. 564****************************************************************************/ 565 566NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from, 567 uint32 access_mask, uint32 share_access, 568 uint32 create_options, files_struct *to) 569{ 570 TALLOC_FREE(to->fh); 571 572 to->fh = from->fh; 573 to->fh->ref_count++; 574 575 to->file_id = from->file_id; 576 to->initial_allocation_size = from->initial_allocation_size; 577 to->mode = from->mode; 578 to->file_pid = from->file_pid; 579 to->vuid = from->vuid; 580 to->open_time = from->open_time; 581 to->access_mask = access_mask; 582 to->share_access = share_access; 583 to->oplock_type = from->oplock_type; 584 to->can_lock = from->can_lock; 585 to->can_read = (access_mask & (FILE_READ_DATA)) ? True : False; 586 if (!CAN_WRITE(from->conn)) { 587 to->can_write = False; 588 } else { 589 to->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False; 590 } 591 to->print_file = from->print_file; 592 to->modified = from->modified; 593 to->is_directory = from->is_directory; 594 to->aio_write_behind = from->aio_write_behind; 595 return fsp_set_smb_fname(to, from->fsp_name); 596} 597 598/** 599 * The only way that the fsp->fsp_name field should ever be set. 600 */ 601NTSTATUS fsp_set_smb_fname(struct files_struct *fsp, 602 const struct smb_filename *smb_fname_in) 603{ 604 NTSTATUS status; 605 struct smb_filename *smb_fname_new; 606 607 status = copy_smb_filename(fsp, smb_fname_in, &smb_fname_new); 608 if (!NT_STATUS_IS_OK(status)) { 609 return status; 610 } 611 612 TALLOC_FREE(fsp->fsp_name); 613 fsp->fsp_name = smb_fname_new; 614 615 return NT_STATUS_OK; 616} 617