smbd/files.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    Files[] structure handling
00004    Copyright (C) Andrew Tridgell 1998
00005    
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015    
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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 /* a fsp to use when chaining */
00034 static files_struct *chain_fsp = NULL;
00035 
00036 static int files_used;
00037 
00038 /* A singleton cache to speed up searching by dev/inode. */
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  Return a unique number identifying this fsp over the life of this pid.
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  Find first available file slot.
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         /* we want to give out file handles differently on each new
00069            connection because of a common bug in MS clients where they try to
00070            reuse a file descriptor from an earlier smb connection. This code
00071            increases the chance that the errant client will get an error rather
00072            than causing corruption */
00073         if (first_file == 0) {
00074                 first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files;
00075         }
00076 
00077         /* TODO: Port the id-tree implementation from Samba4 */
00078 
00079         i = bitmap_find(file_bmap, first_file);
00080         if (i == -1) {
00081                 DEBUG(0,("ERROR! Out of file structures\n"));
00082                 /* TODO: We have to unconditionally return a DOS error here,
00083                  * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with
00084                  * NTSTATUS negotiated */
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         /* A new fsp invalidates a negative fsp_fi_cache. */
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  Close all open files for a connection.
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  Close all open files for a pid and a vuid.
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  Initialise file structures.
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          * Set the max_open files to be the requested
00181          * max plus a fudgefactor to allow for the extra
00182          * fd's we need such as log files etc...
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          * Ensure that pipe_handle_oppset is set correctly.
00206          */
00207         set_pipe_handle_offset(real_max_open_files);
00208 }
00209 
00210 /****************************************************************************
00211  Close files open by a specified vuid.
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  Debug to enumerate all open files in the smbd.
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  Find a fsp given a file descriptor.
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  Find a fsp given a device, inode and file_id.
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                 /* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
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                         /* Paranoia check. */
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  Check if an fsp still exists.
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  Find the first fsp given a device and inode.
00315  We use a singleton cache here to speed up searching from getfilepathinfo
00316  calls.
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                 /* Positive or negative cache hit. */
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                         /* Setup positive cache. */
00336                         fsp_fi_cache.fsp = fsp;
00337                         return fsp;
00338                 }
00339         }
00340 
00341         /* Setup negative cache. */
00342         fsp_fi_cache.fsp = NULL;
00343         return NULL;
00344 }
00345 
00346 /****************************************************************************
00347  Find the next fsp having the same device and inode.
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  Find a fsp that is open for printing.
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  Set a pending modtime across all files with a given dev/ino pair.
00383  Record the owner of that modtime.
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  Sync open files on a connection.
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 /* write through */);
00418                 }
00419         }
00420 }
00421 
00422 /****************************************************************************
00423  Free up a fsp.
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         /* Ensure this event will never fire. */
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         /* this is paranoia, just in case someone tries to reuse the 
00457            information */
00458         ZERO_STRUCTP(fsp);
00459 
00460         if (fsp == chain_fsp) {
00461                 chain_fsp = NULL;
00462         }
00463 
00464         /* Closing a file can invalidate the positive cache. */
00465         if (fsp == fsp_fi_cache.fsp) {
00466                 ZERO_STRUCT(fsp_fi_cache);
00467         }
00468 
00469         SAFE_FREE(fsp);
00470 }
00471 
00472 /****************************************************************************
00473  Get an fsp from a 16 bit fnum.
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  Get an fsp from a packet given the offset of a 16 bit fnum.
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  Reset the chained fsp - done at the start of a packet reply.
00517 ****************************************************************************/
00518 
00519 void file_chain_reset(void)
00520 {
00521         chain_fsp = NULL;
00522 }
00523 
00524 /****************************************************************************
00525  Duplicate the file handle part for a DOS or FCB open.
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 }

Sambaに対してSat Aug 29 21:23:23 2009に生成されました。  doxygen 1.4.7