00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022
00023 static int real_max_open_files;
00024
00025 #define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < real_max_open_files))
00026
00027 #define FILE_HANDLE_OFFSET 0x1000
00028
00029 static struct bitmap *file_bmap;
00030
00031 static files_struct *Files;
00032
00033
00034 static files_struct *chain_fsp = NULL;
00035
00036 static int files_used;
00037
00038
00039 static struct fsp_singleton_cache {
00040 files_struct *fsp;
00041 SMB_DEV_T dev;
00042 SMB_INO_T inode;
00043 } fsp_fi_cache;
00044
00045
00046
00047
00048
00049 static unsigned long get_gen_count(void)
00050 {
00051 static unsigned long file_gen_counter;
00052
00053 if ((++file_gen_counter) == 0)
00054 return ++file_gen_counter;
00055 return file_gen_counter;
00056 }
00057
00058
00059
00060
00061
00062 NTSTATUS file_new(connection_struct *conn, files_struct **result)
00063 {
00064 int i;
00065 static int first_file;
00066 files_struct *fsp;
00067
00068
00069
00070
00071
00072
00073 if (first_file == 0) {
00074 first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files;
00075 }
00076
00077
00078
00079 i = bitmap_find(file_bmap, first_file);
00080 if (i == -1) {
00081 DEBUG(0,("ERROR! Out of file structures\n"));
00082
00083
00084
00085 return NT_STATUS_TOO_MANY_OPENED_FILES;
00086 }
00087
00088 fsp = SMB_MALLOC_P(files_struct);
00089 if (!fsp) {
00090 return NT_STATUS_NO_MEMORY;
00091 }
00092
00093 ZERO_STRUCTP(fsp);
00094
00095 fsp->fh = SMB_MALLOC_P(struct fd_handle);
00096 if (!fsp->fh) {
00097 SAFE_FREE(fsp);
00098 return NT_STATUS_NO_MEMORY;
00099 }
00100
00101 ZERO_STRUCTP(fsp->fh);
00102
00103 fsp->fh->ref_count = 1;
00104 fsp->fh->fd = -1;
00105
00106 fsp->conn = conn;
00107 fsp->fh->file_id = get_gen_count();
00108 GetTimeOfDay(&fsp->open_time);
00109
00110 first_file = (i+1) % real_max_open_files;
00111
00112 bitmap_set(file_bmap, i);
00113 files_used++;
00114
00115 fsp->fnum = i + FILE_HANDLE_OFFSET;
00116 SMB_ASSERT(fsp->fnum < 65536);
00117
00118 string_set(&fsp->fsp_name,"");
00119
00120 DLIST_ADD(Files, fsp);
00121
00122 DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
00123 i, fsp->fnum, files_used));
00124
00125 chain_fsp = fsp;
00126
00127
00128 if (fsp_fi_cache.fsp == NULL) {
00129 ZERO_STRUCT(fsp_fi_cache);
00130 }
00131
00132 *result = fsp;
00133 return NT_STATUS_OK;
00134 }
00135
00136
00137
00138
00139
00140 void file_close_conn(connection_struct *conn)
00141 {
00142 files_struct *fsp, *next;
00143
00144 for (fsp=Files;fsp;fsp=next) {
00145 next = fsp->next;
00146 if (fsp->conn == conn) {
00147 close_file(fsp,SHUTDOWN_CLOSE);
00148 }
00149 }
00150 }
00151
00152
00153
00154
00155
00156 void file_close_pid(uint16 smbpid, int vuid)
00157 {
00158 files_struct *fsp, *next;
00159
00160 for (fsp=Files;fsp;fsp=next) {
00161 next = fsp->next;
00162 if ((fsp->file_pid == smbpid) && (fsp->vuid == vuid)) {
00163 close_file(fsp,SHUTDOWN_CLOSE);
00164 }
00165 }
00166 }
00167
00168
00169
00170
00171
00172 #define MAX_OPEN_FUDGEFACTOR 20
00173
00174 void file_init(void)
00175 {
00176 int request_max_open_files = lp_max_open_files();
00177 int real_lim;
00178
00179
00180
00181
00182
00183
00184 real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR);
00185
00186 real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR;
00187
00188 if (real_max_open_files + FILE_HANDLE_OFFSET + MAX_OPEN_PIPES > 65536)
00189 real_max_open_files = 65536 - FILE_HANDLE_OFFSET - MAX_OPEN_PIPES;
00190
00191 if(real_max_open_files != request_max_open_files) {
00192 DEBUG(1,("file_init: Information only: requested %d \
00193 open files, %d are available.\n", request_max_open_files, real_max_open_files));
00194 }
00195
00196 SMB_ASSERT(real_max_open_files > 100);
00197
00198 file_bmap = bitmap_allocate(real_max_open_files);
00199
00200 if (!file_bmap) {
00201 exit_server("out of memory in file_init");
00202 }
00203
00204
00205
00206
00207 set_pipe_handle_offset(real_max_open_files);
00208 }
00209
00210
00211
00212
00213
00214 void file_close_user(int vuid)
00215 {
00216 files_struct *fsp, *next;
00217
00218 for (fsp=Files;fsp;fsp=next) {
00219 next=fsp->next;
00220 if (fsp->vuid == vuid) {
00221 close_file(fsp,SHUTDOWN_CLOSE);
00222 }
00223 }
00224 }
00225
00226
00227
00228
00229
00230 void file_dump_open_table(void)
00231 {
00232 int count=0;
00233 files_struct *fsp;
00234
00235 for (fsp=Files;fsp;fsp=fsp->next,count++) {
00236 DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n",
00237 count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->file_id,
00238 (unsigned int)fsp->dev, (double)fsp->inode ));
00239 }
00240 }
00241
00242
00243
00244
00245
00246 files_struct *file_find_fd(int fd)
00247 {
00248 int count=0;
00249 files_struct *fsp;
00250
00251 for (fsp=Files;fsp;fsp=fsp->next,count++) {
00252 if (fsp->fh->fd == fd) {
00253 if (count > 10) {
00254 DLIST_PROMOTE(Files, fsp);
00255 }
00256 return fsp;
00257 }
00258 }
00259
00260 return NULL;
00261 }
00262
00263
00264
00265
00266
00267 files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id)
00268 {
00269 int count=0;
00270 files_struct *fsp;
00271
00272 for (fsp=Files;fsp;fsp=fsp->next,count++) {
00273
00274 if (fsp->dev == dev &&
00275 fsp->inode == inode &&
00276 fsp->fh->file_id == file_id ) {
00277 if (count > 10) {
00278 DLIST_PROMOTE(Files, fsp);
00279 }
00280
00281 if ((fsp->fh->fd == -1) &&
00282 (fsp->oplock_type != NO_OPLOCK) &&
00283 (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
00284 DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \
00285 oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev,
00286 (double)fsp->inode, (unsigned int)fsp->fh->file_id,
00287 (unsigned int)fsp->oplock_type ));
00288 smb_panic("file_find_dif\n");
00289 }
00290 return fsp;
00291 }
00292 }
00293
00294 return NULL;
00295 }
00296
00297
00298
00299
00300
00301 files_struct *file_find_fsp(files_struct *orig_fsp)
00302 {
00303 files_struct *fsp;
00304
00305 for (fsp=Files;fsp;fsp=fsp->next) {
00306 if (fsp == orig_fsp)
00307 return fsp;
00308 }
00309
00310 return NULL;
00311 }
00312
00313
00314
00315
00316
00317
00318
00319 files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
00320 {
00321 files_struct *fsp;
00322
00323 if (fsp_fi_cache.dev == dev && fsp_fi_cache.inode == inode) {
00324
00325 return fsp_fi_cache.fsp;
00326 }
00327
00328 fsp_fi_cache.dev = dev;
00329 fsp_fi_cache.inode = inode;
00330
00331 for (fsp=Files;fsp;fsp=fsp->next) {
00332 if ( fsp->fh->fd != -1 &&
00333 fsp->dev == dev &&
00334 fsp->inode == inode ) {
00335
00336 fsp_fi_cache.fsp = fsp;
00337 return fsp;
00338 }
00339 }
00340
00341
00342 fsp_fi_cache.fsp = NULL;
00343 return NULL;
00344 }
00345
00346
00347
00348
00349
00350 files_struct *file_find_di_next(files_struct *start_fsp)
00351 {
00352 files_struct *fsp;
00353
00354 for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
00355 if ( fsp->fh->fd != -1 &&
00356 fsp->dev == start_fsp->dev &&
00357 fsp->inode == start_fsp->inode )
00358 return fsp;
00359 }
00360
00361 return NULL;
00362 }
00363
00364
00365
00366
00367
00368 files_struct *file_find_print(void)
00369 {
00370 files_struct *fsp;
00371
00372 for (fsp=Files;fsp;fsp=fsp->next) {
00373 if (fsp->print_file) {
00374 return fsp;
00375 }
00376 }
00377
00378 return NULL;
00379 }
00380
00381
00382
00383
00384
00385
00386 void fsp_set_pending_modtime(files_struct *tfsp, const struct timespec mod)
00387 {
00388 files_struct *fsp;
00389
00390 if (null_timespec(mod)) {
00391 return;
00392 }
00393
00394 for (fsp = Files;fsp;fsp=fsp->next) {
00395 if ( fsp->fh->fd != -1 &&
00396 fsp->dev == tfsp->dev &&
00397 fsp->inode == tfsp->inode ) {
00398 fsp->pending_modtime = mod;
00399 fsp->pending_modtime_owner = False;
00400 }
00401 }
00402
00403 tfsp->pending_modtime_owner = True;
00404 }
00405
00406
00407
00408
00409
00410 void file_sync_all(connection_struct *conn)
00411 {
00412 files_struct *fsp, *next;
00413
00414 for (fsp=Files;fsp;fsp=next) {
00415 next=fsp->next;
00416 if ((conn == fsp->conn) && (fsp->fh->fd != -1)) {
00417 sync_file(conn, fsp, True );
00418 }
00419 }
00420 }
00421
00422
00423
00424
00425
00426 void file_free(files_struct *fsp)
00427 {
00428 DLIST_REMOVE(Files, fsp);
00429
00430 string_free(&fsp->fsp_name);
00431
00432 if (fsp->fake_file_handle) {
00433 destroy_fake_file_handle(&fsp->fake_file_handle);
00434 }
00435
00436 if (fsp->fh->ref_count == 1) {
00437 SAFE_FREE(fsp->fh);
00438 } else {
00439 fsp->fh->ref_count--;
00440 }
00441
00442 if (fsp->notify) {
00443 notify_remove(fsp->conn->notify_ctx, fsp);
00444 TALLOC_FREE(fsp->notify);
00445 }
00446
00447
00448 TALLOC_FREE(fsp->oplock_timeout);
00449
00450 bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
00451 files_used--;
00452
00453 DEBUG(5,("freed files structure %d (%d used)\n",
00454 fsp->fnum, files_used));
00455
00456
00457
00458 ZERO_STRUCTP(fsp);
00459
00460 if (fsp == chain_fsp) {
00461 chain_fsp = NULL;
00462 }
00463
00464
00465 if (fsp == fsp_fi_cache.fsp) {
00466 ZERO_STRUCT(fsp_fi_cache);
00467 }
00468
00469 SAFE_FREE(fsp);
00470 }
00471
00472
00473
00474
00475
00476 files_struct *file_fnum(uint16 fnum)
00477 {
00478 files_struct *fsp;
00479 int count=0;
00480
00481 for (fsp=Files;fsp;fsp=fsp->next, count++) {
00482 if (fsp->fnum == fnum) {
00483 if (count > 10) {
00484 DLIST_PROMOTE(Files, fsp);
00485 }
00486 return fsp;
00487 }
00488 }
00489 return NULL;
00490 }
00491
00492
00493
00494
00495
00496 files_struct *file_fsp(char *buf, int where)
00497 {
00498 files_struct *fsp;
00499
00500 if (chain_fsp) {
00501 return chain_fsp;
00502 }
00503
00504 if (!buf) {
00505 return NULL;
00506 }
00507
00508 fsp = file_fnum(SVAL(buf, where));
00509 if (fsp) {
00510 chain_fsp = fsp;
00511 }
00512 return fsp;
00513 }
00514
00515
00516
00517
00518
00519 void file_chain_reset(void)
00520 {
00521 chain_fsp = NULL;
00522 }
00523
00524
00525
00526
00527
00528 NTSTATUS dup_file_fsp(files_struct *fsp,
00529 uint32 access_mask,
00530 uint32 share_access,
00531 uint32 create_options,
00532 files_struct **result)
00533 {
00534 NTSTATUS status;
00535 files_struct *dup_fsp;
00536
00537 status = file_new(fsp->conn, &dup_fsp);
00538
00539 if (!NT_STATUS_IS_OK(status)) {
00540 return status;
00541 }
00542
00543 SAFE_FREE(dup_fsp->fh);
00544
00545 dup_fsp->fh = fsp->fh;
00546 dup_fsp->fh->ref_count++;
00547
00548 dup_fsp->dev = fsp->dev;
00549 dup_fsp->inode = fsp->inode;
00550 dup_fsp->initial_allocation_size = fsp->initial_allocation_size;
00551 dup_fsp->mode = fsp->mode;
00552 dup_fsp->file_pid = fsp->file_pid;
00553 dup_fsp->vuid = fsp->vuid;
00554 dup_fsp->open_time = fsp->open_time;
00555 dup_fsp->access_mask = access_mask;
00556 dup_fsp->share_access = share_access;
00557 dup_fsp->pending_modtime_owner = fsp->pending_modtime_owner;
00558 dup_fsp->pending_modtime = fsp->pending_modtime;
00559 dup_fsp->last_write_time = fsp->last_write_time;
00560 dup_fsp->oplock_type = fsp->oplock_type;
00561 dup_fsp->can_lock = fsp->can_lock;
00562 dup_fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
00563 if (!CAN_WRITE(fsp->conn)) {
00564 dup_fsp->can_write = False;
00565 } else {
00566 dup_fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ? True : False;
00567 }
00568 dup_fsp->print_file = fsp->print_file;
00569 dup_fsp->modified = fsp->modified;
00570 dup_fsp->is_directory = fsp->is_directory;
00571 dup_fsp->is_stat = fsp->is_stat;
00572 dup_fsp->aio_write_behind = fsp->aio_write_behind;
00573 string_set(&dup_fsp->fsp_name,fsp->fsp_name);
00574
00575 *result = dup_fsp;
00576 return NT_STATUS_OK;
00577 }