smbd/open.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    file opening and share modes
00004    Copyright (C) Andrew Tridgell 1992-1998
00005    Copyright (C) Jeremy Allison 2001-2004
00006    Copyright (C) Volker Lendecke 2005
00007    
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012    
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017    
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00021 */
00022 
00023 #include "includes.h"
00024 
00025 extern struct generic_mapping file_generic_mapping;
00026 extern struct current_user current_user;
00027 extern userdom_struct current_user_info;
00028 extern uint16 global_smbpid;
00029 extern BOOL global_client_failed_oplock_break;
00030 
00031 struct deferred_open_record {
00032         BOOL delayed_for_oplocks;
00033         SMB_DEV_T dev;
00034         SMB_INO_T inode;
00035 };
00036 
00037 /****************************************************************************
00038  fd support routines - attempt to do a dos_open.
00039 ****************************************************************************/
00040 
00041 static NTSTATUS fd_open(struct connection_struct *conn,
00042                     const char *fname, 
00043                     files_struct *fsp,
00044                     int flags,
00045                     mode_t mode)
00046 {
00047         NTSTATUS status = NT_STATUS_OK;
00048 
00049 #ifdef O_NOFOLLOW
00050         /* 
00051          * Never follow symlinks on a POSIX client. The
00052          * client should be doing this.
00053          */
00054 
00055         if (fsp->posix_open || !lp_symlinks(SNUM(conn))) {
00056                 flags |= O_NOFOLLOW;
00057         }
00058 #endif
00059 
00060         fsp->fh->fd = SMB_VFS_OPEN(conn,fname,fsp,flags,mode);
00061         if (fsp->fh->fd == -1) {
00062                 status = map_nt_error_from_unix(errno);
00063         }
00064 
00065         DEBUG(10,("fd_open: name %s, flags = 0%o mode = 0%o, fd = %d. %s\n",
00066                     fname, flags, (int)mode, fsp->fh->fd,
00067                 (fsp->fh->fd == -1) ? strerror(errno) : "" ));
00068 
00069         return status;
00070 }
00071 
00072 /****************************************************************************
00073  Close the file associated with a fsp.
00074 ****************************************************************************/
00075 
00076 NTSTATUS fd_close(struct connection_struct *conn, files_struct *fsp)
00077 {
00078         if (fsp->fh->fd == -1) {
00079                 return NT_STATUS_OK; /* What we used to call a stat open. */
00080         }
00081         if (fsp->fh->ref_count > 1) {
00082                 return NT_STATUS_OK; /* Shared handle. Only close last reference. */
00083         }
00084         return fd_close_posix(conn, fsp);
00085 }
00086 
00087 /****************************************************************************
00088  Change the ownership of a file to that of the parent directory.
00089  Do this by fd if possible.
00090 ****************************************************************************/
00091 
00092 static void change_file_owner_to_parent(connection_struct *conn,
00093                                         const char *inherit_from_dir,
00094                                         files_struct *fsp)
00095 {
00096         SMB_STRUCT_STAT parent_st;
00097         int ret;
00098 
00099         ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
00100         if (ret == -1) {
00101                 DEBUG(0,("change_file_owner_to_parent: failed to stat parent "
00102                          "directory %s. Error was %s\n",
00103                          inherit_from_dir, strerror(errno) ));
00104                 return;
00105         }
00106 
00107         become_root();
00108         ret = SMB_VFS_FCHOWN(fsp, fsp->fh->fd, parent_st.st_uid, (gid_t)-1);
00109         unbecome_root();
00110         if (ret == -1) {
00111                 DEBUG(0,("change_file_owner_to_parent: failed to fchown "
00112                          "file %s to parent directory uid %u. Error "
00113                          "was %s\n", fsp->fsp_name,
00114                          (unsigned int)parent_st.st_uid,
00115                          strerror(errno) ));
00116         }
00117 
00118         DEBUG(10,("change_file_owner_to_parent: changed new file %s to "
00119                   "parent directory uid %u.\n", fsp->fsp_name,
00120                   (unsigned int)parent_st.st_uid ));
00121 }
00122 
00123 static void change_dir_owner_to_parent(connection_struct *conn,
00124                                        const char *inherit_from_dir,
00125                                        const char *fname,
00126                                        SMB_STRUCT_STAT *psbuf)
00127 {
00128         pstring saved_dir;
00129         SMB_STRUCT_STAT sbuf;
00130         SMB_STRUCT_STAT parent_st;
00131         int ret;
00132 
00133         ret = SMB_VFS_STAT(conn, inherit_from_dir, &parent_st);
00134         if (ret == -1) {
00135                 DEBUG(0,("change_dir_owner_to_parent: failed to stat parent "
00136                          "directory %s. Error was %s\n",
00137                          inherit_from_dir, strerror(errno) ));
00138                 return;
00139         }
00140 
00141         /* We've already done an lstat into psbuf, and we know it's a
00142            directory. If we can cd into the directory and the dev/ino
00143            are the same then we can safely chown without races as
00144            we're locking the directory in place by being in it.  This
00145            should work on any UNIX (thanks tridge :-). JRA.
00146         */
00147 
00148         if (!vfs_GetWd(conn,saved_dir)) {
00149                 DEBUG(0,("change_dir_owner_to_parent: failed to get "
00150                          "current working directory\n"));
00151                 return;
00152         }
00153 
00154         /* Chdir into the new path. */
00155         if (vfs_ChDir(conn, fname) == -1) {
00156                 DEBUG(0,("change_dir_owner_to_parent: failed to change "
00157                          "current working directory to %s. Error "
00158                          "was %s\n", fname, strerror(errno) ));
00159                 goto out;
00160         }
00161 
00162         if (SMB_VFS_STAT(conn,".",&sbuf) == -1) {
00163                 DEBUG(0,("change_dir_owner_to_parent: failed to stat "
00164                          "directory '.' (%s) Error was %s\n",
00165                          fname, strerror(errno)));
00166                 goto out;
00167         }
00168 
00169         /* Ensure we're pointing at the same place. */
00170         if (sbuf.st_dev != psbuf->st_dev ||
00171             sbuf.st_ino != psbuf->st_ino ||
00172             sbuf.st_mode != psbuf->st_mode ) {
00173                 DEBUG(0,("change_dir_owner_to_parent: "
00174                          "device/inode/mode on directory %s changed. "
00175                          "Refusing to chown !\n", fname ));
00176                 goto out;
00177         }
00178 
00179         become_root();
00180         ret = SMB_VFS_CHOWN(conn, ".", parent_st.st_uid, (gid_t)-1);
00181         unbecome_root();
00182         if (ret == -1) {
00183                 DEBUG(10,("change_dir_owner_to_parent: failed to chown "
00184                           "directory %s to parent directory uid %u. "
00185                           "Error was %s\n", fname,
00186                           (unsigned int)parent_st.st_uid, strerror(errno) ));
00187                 goto out;
00188         }
00189 
00190         DEBUG(10,("change_dir_owner_to_parent: changed ownership of new "
00191                   "directory %s to parent directory uid %u.\n",
00192                   fname, (unsigned int)parent_st.st_uid ));
00193 
00194  out:
00195 
00196         vfs_ChDir(conn,saved_dir);
00197 }
00198 
00199 /****************************************************************************
00200  Open a file.
00201 ****************************************************************************/
00202 
00203 static NTSTATUS open_file(files_struct *fsp,
00204                           connection_struct *conn,
00205                           const char *parent_dir,
00206                           const char *name,
00207                           const char *path,
00208                           SMB_STRUCT_STAT *psbuf,
00209                           int flags,
00210                           mode_t unx_mode,
00211                           uint32 access_mask, /* client requested access mask. */
00212                           uint32 open_access_mask) /* what we're actually using in the open. */
00213 {
00214         NTSTATUS status = NT_STATUS_OK;
00215         int accmode = (flags & O_ACCMODE);
00216         int local_flags = flags;
00217         BOOL file_existed = VALID_STAT(*psbuf);
00218 
00219         fsp->fh->fd = -1;
00220         errno = EPERM;
00221 
00222         /* Check permissions */
00223 
00224         /*
00225          * This code was changed after seeing a client open request 
00226          * containing the open mode of (DENY_WRITE/read-only) with
00227          * the 'create if not exist' bit set. The previous code
00228          * would fail to open the file read only on a read-only share
00229          * as it was checking the flags parameter  directly against O_RDONLY,
00230          * this was failing as the flags parameter was set to O_RDONLY|O_CREAT.
00231          * JRA.
00232          */
00233 
00234         if (!CAN_WRITE(conn)) {
00235                 /* It's a read-only share - fail if we wanted to write. */
00236                 if(accmode != O_RDONLY) {
00237                         DEBUG(3,("Permission denied opening %s\n", path));
00238                         return NT_STATUS_ACCESS_DENIED;
00239                 } else if(flags & O_CREAT) {
00240                         /* We don't want to write - but we must make sure that
00241                            O_CREAT doesn't create the file if we have write
00242                            access into the directory.
00243                         */
00244                         flags &= ~O_CREAT;
00245                         local_flags &= ~O_CREAT;
00246                 }
00247         }
00248 
00249         /*
00250          * This little piece of insanity is inspired by the
00251          * fact that an NT client can open a file for O_RDONLY,
00252          * but set the create disposition to FILE_EXISTS_TRUNCATE.
00253          * If the client *can* write to the file, then it expects to
00254          * truncate the file, even though it is opening for readonly.
00255          * Quicken uses this stupid trick in backup file creation...
00256          * Thanks *greatly* to "David W. Chapman Jr." <dwcjr@inethouston.net>
00257          * for helping track this one down. It didn't bite us in 2.0.x
00258          * as we always opened files read-write in that release. JRA.
00259          */
00260 
00261         if ((accmode == O_RDONLY) && ((flags & O_TRUNC) == O_TRUNC)) {
00262                 DEBUG(10,("open_file: truncate requested on read-only open "
00263                           "for file %s\n", path));
00264                 local_flags = (flags & ~O_ACCMODE)|O_RDWR;
00265         }
00266 
00267         if ((open_access_mask & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
00268             (!file_existed && (local_flags & O_CREAT)) ||
00269             ((local_flags & O_TRUNC) == O_TRUNC) ) {
00270 
00271                 /*
00272                  * We can't actually truncate here as the file may be locked.
00273                  * open_file_ntcreate will take care of the truncate later. JRA.
00274                  */
00275 
00276                 local_flags &= ~O_TRUNC;
00277 
00278 #if defined(O_NONBLOCK) && defined(S_ISFIFO)
00279                 /*
00280                  * We would block on opening a FIFO with no one else on the
00281                  * other end. Do what we used to do and add O_NONBLOCK to the
00282                  * open flags. JRA.
00283                  */
00284 
00285                 if (file_existed && S_ISFIFO(psbuf->st_mode)) {
00286                         local_flags |= O_NONBLOCK;
00287                 }
00288 #endif
00289 
00290                 /* Don't create files with Microsoft wildcard characters. */
00291                 if ((local_flags & O_CREAT) && !file_existed &&
00292                     ms_has_wild(path))  {
00293                         return NT_STATUS_OBJECT_NAME_INVALID;
00294                 }
00295 
00296                 /* Actually do the open */
00297                 status = fd_open(conn, path, fsp, local_flags, unx_mode);
00298                 if (!NT_STATUS_IS_OK(status)) {
00299                         DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
00300                                  "(flags=%d)\n",
00301                                  path,nt_errstr(status),local_flags,flags));
00302                         return status;
00303                 }
00304 
00305                 if ((local_flags & O_CREAT) && !file_existed) {
00306 
00307                         /* Inherit the ACL if required */
00308                         if (lp_inherit_perms(SNUM(conn))) {
00309                                 inherit_access_acl(conn, parent_dir, path,
00310                                                    unx_mode);
00311                         }
00312 
00313                         /* Change the owner if required. */
00314                         if (lp_inherit_owner(SNUM(conn))) {
00315                                 change_file_owner_to_parent(conn, parent_dir,
00316                                                             fsp);
00317                         }
00318 
00319                         notify_fname(conn, NOTIFY_ACTION_ADDED,
00320                                      FILE_NOTIFY_CHANGE_FILE_NAME, path);
00321                 }
00322 
00323         } else {
00324                 fsp->fh->fd = -1; /* What we used to call a stat open. */
00325         }
00326 
00327         if (!file_existed) {
00328                 int ret;
00329 
00330                 if (fsp->fh->fd == -1) {
00331                         ret = SMB_VFS_STAT(conn, path, psbuf);
00332                 } else {
00333                         ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf);
00334                         /* If we have an fd, this stat should succeed. */
00335                         if (ret == -1) {
00336                                 DEBUG(0,("Error doing fstat on open file %s "
00337                                          "(%s)\n", path,strerror(errno) ));
00338                         }
00339                 }
00340 
00341                 /* For a non-io open, this stat failing means file not found. JRA */
00342                 if (ret == -1) {
00343                         status = map_nt_error_from_unix(errno);
00344                         fd_close(conn, fsp);
00345                         return status;
00346                 }
00347         }
00348 
00349         /*
00350          * POSIX allows read-only opens of directories. We don't
00351          * want to do this (we use a different code path for this)
00352          * so catch a directory open and return an EISDIR. JRA.
00353          */
00354 
00355         if(S_ISDIR(psbuf->st_mode)) {
00356                 fd_close(conn, fsp);
00357                 errno = EISDIR;
00358                 return NT_STATUS_FILE_IS_A_DIRECTORY;
00359         }
00360 
00361         fsp->mode = psbuf->st_mode;
00362         fsp->inode = psbuf->st_ino;
00363         fsp->dev = psbuf->st_dev;
00364         fsp->vuid = current_user.vuid;
00365         fsp->file_pid = global_smbpid;
00366         fsp->can_lock = True;
00367         fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
00368         if (!CAN_WRITE(conn)) {
00369                 fsp->can_write = False;
00370         } else {
00371                 fsp->can_write = (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) ?
00372                         True : False;
00373         }
00374         fsp->print_file = False;
00375         fsp->modified = False;
00376         fsp->sent_oplock_break = NO_BREAK_SENT;
00377         fsp->is_directory = False;
00378         fsp->is_stat = False;
00379         if (conn->aio_write_behind_list &&
00380             is_in_path(path, conn->aio_write_behind_list, conn->case_sensitive)) {
00381                 fsp->aio_write_behind = True;
00382         }
00383 
00384         string_set(&fsp->fsp_name, path);
00385         fsp->wcp = NULL; /* Write cache pointer. */
00386 
00387         DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
00388                  *current_user_info.smb_name ?
00389                  current_user_info.smb_name : conn->user,fsp->fsp_name,
00390                  BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
00391                  conn->num_files_open + 1));
00392 
00393         errno = 0;
00394         return NT_STATUS_OK;
00395 }
00396 
00397 /*******************************************************************
00398  Return True if the filename is one of the special executable types.
00399 ********************************************************************/
00400 
00401 static BOOL is_executable(const char *fname)
00402 {
00403         if ((fname = strrchr_m(fname,'.'))) {
00404                 if (strequal(fname,".com") ||
00405                     strequal(fname,".dll") ||
00406                     strequal(fname,".exe") ||
00407                     strequal(fname,".sym")) {
00408                         return True;
00409                 }
00410         }
00411         return False;
00412 }
00413 
00414 /****************************************************************************
00415  Check if we can open a file with a share mode.
00416  Returns True if conflict, False if not.
00417 ****************************************************************************/
00418 
00419 static BOOL share_conflict(struct share_mode_entry *entry,
00420                            uint32 access_mask,
00421                            uint32 share_access)
00422 {
00423         DEBUG(10,("share_conflict: entry->access_mask = 0x%x, "
00424                   "entry->share_access = 0x%x, "
00425                   "entry->private_options = 0x%x\n",
00426                   (unsigned int)entry->access_mask,
00427                   (unsigned int)entry->share_access,
00428                   (unsigned int)entry->private_options));
00429 
00430         DEBUG(10,("share_conflict: access_mask = 0x%x, share_access = 0x%x\n",
00431                   (unsigned int)access_mask, (unsigned int)share_access));
00432 
00433         if ((entry->access_mask & (FILE_WRITE_DATA|
00434                                    FILE_APPEND_DATA|
00435                                    FILE_READ_DATA|
00436                                    FILE_EXECUTE|
00437                                    DELETE_ACCESS)) == 0) {
00438                 DEBUG(10,("share_conflict: No conflict due to "
00439                           "entry->access_mask = 0x%x\n",
00440                           (unsigned int)entry->access_mask ));
00441                 return False;
00442         }
00443 
00444         if ((access_mask & (FILE_WRITE_DATA|
00445                             FILE_APPEND_DATA|
00446                             FILE_READ_DATA|
00447                             FILE_EXECUTE|
00448                             DELETE_ACCESS)) == 0) {
00449                 DEBUG(10,("share_conflict: No conflict due to "
00450                           "access_mask = 0x%x\n",
00451                           (unsigned int)access_mask ));
00452                 return False;
00453         }
00454 
00455 #if 1 /* JRA TEST - Superdebug. */
00456 #define CHECK_MASK(num, am, right, sa, share) \
00457         DEBUG(10,("share_conflict: [%d] am (0x%x) & right (0x%x) = 0x%x\n", \
00458                 (unsigned int)(num), (unsigned int)(am), \
00459                 (unsigned int)(right), (unsigned int)(am)&(right) )); \
00460         DEBUG(10,("share_conflict: [%d] sa (0x%x) & share (0x%x) = 0x%x\n", \
00461                 (unsigned int)(num), (unsigned int)(sa), \
00462                 (unsigned int)(share), (unsigned int)(sa)&(share) )); \
00463         if (((am) & (right)) && !((sa) & (share))) { \
00464                 DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \
00465 sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \
00466                         (unsigned int)(share) )); \
00467                 return True; \
00468         }
00469 #else
00470 #define CHECK_MASK(num, am, right, sa, share) \
00471         if (((am) & (right)) && !((sa) & (share))) { \
00472                 DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \
00473 sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \
00474                         (unsigned int)(share) )); \
00475                 return True; \
00476         }
00477 #endif
00478 
00479         CHECK_MASK(1, entry->access_mask, FILE_WRITE_DATA | FILE_APPEND_DATA,
00480                    share_access, FILE_SHARE_WRITE);
00481         CHECK_MASK(2, access_mask, FILE_WRITE_DATA | FILE_APPEND_DATA,
00482                    entry->share_access, FILE_SHARE_WRITE);
00483         
00484         CHECK_MASK(3, entry->access_mask, FILE_READ_DATA | FILE_EXECUTE,
00485                    share_access, FILE_SHARE_READ);
00486         CHECK_MASK(4, access_mask, FILE_READ_DATA | FILE_EXECUTE,
00487                    entry->share_access, FILE_SHARE_READ);
00488 
00489         CHECK_MASK(5, entry->access_mask, DELETE_ACCESS,
00490                    share_access, FILE_SHARE_DELETE);
00491         CHECK_MASK(6, access_mask, DELETE_ACCESS,
00492                    entry->share_access, FILE_SHARE_DELETE);
00493 
00494         DEBUG(10,("share_conflict: No conflict.\n"));
00495         return False;
00496 }
00497 
00498 #if defined(DEVELOPER)
00499 static void validate_my_share_entries(int num,
00500                                       struct share_mode_entry *share_entry)
00501 {
00502         files_struct *fsp;
00503 
00504         if (!procid_is_me(&share_entry->pid)) {
00505                 return;
00506         }
00507 
00508         if (is_deferred_open_entry(share_entry) &&
00509             !open_was_deferred(share_entry->op_mid)) {
00510                 pstring str;
00511                 pstr_sprintf(str, "Got a deferred entry without a request: "
00512                              "PANIC: %s\n", share_mode_str(num, share_entry));
00513                 smb_panic(str);
00514         }
00515 
00516         if (!is_valid_share_mode_entry(share_entry)) {
00517                 return;
00518         }
00519 
00520         fsp = file_find_dif(share_entry->dev, share_entry->inode,
00521                             share_entry->share_file_id);
00522         if (!fsp) {
00523                 DEBUG(0,("validate_my_share_entries: PANIC : %s\n",
00524                          share_mode_str(num, share_entry) ));
00525                 smb_panic("validate_my_share_entries: Cannot match a "
00526                           "share entry with an open file\n");
00527         }
00528 
00529         if (is_deferred_open_entry(share_entry) ||
00530             is_unused_share_mode_entry(share_entry)) {
00531                 goto panic;
00532         }
00533 
00534         if ((share_entry->op_type == NO_OPLOCK) &&
00535             (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK)) {
00536                 /* Someone has already written to it, but I haven't yet
00537                  * noticed */
00538                 return;
00539         }
00540 
00541         if (((uint16)fsp->oplock_type) != share_entry->op_type) {
00542                 goto panic;
00543         }
00544 
00545         return;
00546 
00547  panic:
00548         {
00549                 pstring str;
00550                 DEBUG(0,("validate_my_share_entries: PANIC : %s\n",
00551                          share_mode_str(num, share_entry) ));
00552                 slprintf(str, sizeof(str)-1, "validate_my_share_entries: "
00553                          "file %s, oplock_type = 0x%x, op_type = 0x%x\n",
00554                          fsp->fsp_name, (unsigned int)fsp->oplock_type,
00555                          (unsigned int)share_entry->op_type );
00556                 smb_panic(str);
00557         }
00558 }
00559 #endif
00560 
00561 static BOOL is_stat_open(uint32 access_mask)
00562 {
00563         return (access_mask &&
00564                 ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES|
00565                                   FILE_WRITE_ATTRIBUTES))==0) &&
00566                 ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES|
00567                                  FILE_WRITE_ATTRIBUTES)) != 0));
00568 }
00569 
00570 /****************************************************************************
00571  Deal with share modes
00572  Invarient: Share mode must be locked on entry and exit.
00573  Returns -1 on error, or number of share modes on success (may be zero).
00574 ****************************************************************************/
00575 
00576 static NTSTATUS open_mode_check(connection_struct *conn,
00577                                 const char *fname,
00578                                 struct share_mode_lock *lck,
00579                                 uint32 access_mask,
00580                                 uint32 share_access,
00581                                 uint32 create_options,
00582                                 BOOL *file_existed)
00583 {
00584         int i;
00585 
00586         if(lck->num_share_modes == 0) {
00587                 return NT_STATUS_OK;
00588         }
00589 
00590         *file_existed = True;
00591         
00592         if (is_stat_open(access_mask)) {
00593                 /* Stat open that doesn't trigger oplock breaks or share mode
00594                  * checks... ! JRA. */
00595                 return NT_STATUS_OK;
00596         }
00597 
00598         /* A delete on close prohibits everything */
00599 
00600         if (lck->delete_on_close) {
00601                 return NT_STATUS_DELETE_PENDING;
00602         }
00603 
00604         /*
00605          * Check if the share modes will give us access.
00606          */
00607         
00608 #if defined(DEVELOPER)
00609         for(i = 0; i < lck->num_share_modes; i++) {
00610                 validate_my_share_entries(i, &lck->share_modes[i]);
00611         }
00612 #endif
00613 
00614         if (!lp_share_modes(SNUM(conn))) {
00615                 return NT_STATUS_OK;
00616         }
00617 
00618         /* Now we check the share modes, after any oplock breaks. */
00619         for(i = 0; i < lck->num_share_modes; i++) {
00620 
00621                 if (!is_valid_share_mode_entry(&lck->share_modes[i])) {
00622                         continue;
00623                 }
00624 
00625                 /* someone else has a share lock on it, check to see if we can
00626                  * too */
00627                 if (share_conflict(&lck->share_modes[i],
00628                                    access_mask, share_access)) {
00629                         return NT_STATUS_SHARING_VIOLATION;
00630                 }
00631         }
00632         
00633         return NT_STATUS_OK;
00634 }
00635 
00636 static BOOL is_delete_request(files_struct *fsp) {
00637         return ((fsp->access_mask == DELETE_ACCESS) &&
00638                 (fsp->oplock_type == NO_OPLOCK));
00639 }
00640 
00641 /*
00642  * 1) No files open at all or internal open: Grant whatever the client wants.
00643  *
00644  * 2) Exclusive (or batch) oplock around: If the requested access is a delete
00645  *    request, break if the oplock around is a batch oplock. If it's another
00646  *    requested access type, break.
00647  * 
00648  * 3) Only level2 around: Grant level2 and do nothing else.
00649  */
00650 
00651 static BOOL delay_for_oplocks(struct share_mode_lock *lck,
00652                               files_struct *fsp,
00653                               int pass_number,
00654                               int oplock_request)
00655 {
00656         int i;
00657         struct share_mode_entry *exclusive = NULL;
00658         BOOL valid_entry = False;
00659         BOOL delay_it = False;
00660         BOOL have_level2 = False;
00661         NTSTATUS status;
00662         char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
00663 
00664         if (oplock_request & INTERNAL_OPEN_ONLY) {
00665                 fsp->oplock_type = NO_OPLOCK;
00666         }
00667 
00668         if ((oplock_request & INTERNAL_OPEN_ONLY) || is_stat_open(fsp->access_mask)) {
00669                 return False;
00670         }
00671 
00672         for (i=0; i<lck->num_share_modes; i++) {
00673 
00674                 if (!is_valid_share_mode_entry(&lck->share_modes[i])) {
00675                         continue;
00676                 }
00677 
00678                 /* At least one entry is not an invalid or deferred entry. */
00679                 valid_entry = True;
00680 
00681                 if (pass_number == 1) {
00682                         if (BATCH_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
00683                                 SMB_ASSERT(exclusive == NULL);                  
00684                                 exclusive = &lck->share_modes[i];
00685                         }
00686                 } else {
00687                         if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) {
00688                                 SMB_ASSERT(exclusive == NULL);                  
00689                                 exclusive = &lck->share_modes[i];
00690                         }
00691                 }
00692 
00693                 if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) {
00694                         SMB_ASSERT(exclusive == NULL);                  
00695                         have_level2 = True;
00696                 }
00697         }
00698 
00699         if (!valid_entry) {
00700                 /* All entries are placeholders or deferred.
00701                  * Directly grant whatever the client wants. */
00702                 if (fsp->oplock_type == NO_OPLOCK) {
00703                         /* Store a level2 oplock, but don't tell the client */
00704                         fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
00705                 }
00706                 return False;
00707         }
00708 
00709         if (exclusive != NULL) { /* Found an exclusive oplock */
00710                 SMB_ASSERT(!have_level2);
00711                 delay_it = is_delete_request(fsp) ?
00712                         BATCH_OPLOCK_TYPE(exclusive->op_type) : True;
00713         }
00714 
00715         if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
00716                 /* We can at most grant level2 as there are other
00717                  * level2 or NO_OPLOCK entries. */
00718                 fsp->oplock_type = LEVEL_II_OPLOCK;
00719         }
00720 
00721         if ((fsp->oplock_type == NO_OPLOCK) && have_level2) {
00722                 /* Store a level2 oplock, but don't tell the client */
00723                 fsp->oplock_type = FAKE_LEVEL_II_OPLOCK;
00724         }
00725 
00726         if (!delay_it) {
00727                 return False;
00728         }
00729 
00730         /*
00731          * Send a break message to the oplock holder and delay the open for
00732          * our client.
00733          */
00734 
00735         DEBUG(10, ("Sending break request to PID %s\n",
00736                    procid_str_static(&exclusive->pid)));
00737         exclusive->op_mid = get_current_mid();
00738 
00739         /* Create the message. */
00740         share_mode_entry_to_message(msg, exclusive);
00741 
00742         /* Add in the FORCE_OPLOCK_BREAK_TO_NONE bit in the message if set. We
00743            don't want this set in the share mode struct pointed to by lck. */
00744 
00745         if (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE) {
00746                 SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE);
00747         }
00748 
00749         status = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST,
00750                                   msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
00751         if (!NT_STATUS_IS_OK(status)) {
00752                 DEBUG(3, ("Could not send oplock break message: %s\n",
00753                           nt_errstr(status)));
00754         }
00755 
00756         return True;
00757 }
00758 
00759 static BOOL request_timed_out(struct timeval request_time,
00760                               struct timeval timeout)
00761 {
00762         struct timeval now, end_time;
00763         GetTimeOfDay(&now);
00764         end_time = timeval_sum(&request_time, &timeout);
00765         return (timeval_compare(&end_time, &now) < 0);
00766 }
00767 
00768 /****************************************************************************
00769  Handle the 1 second delay in returning a SHARING_VIOLATION error.
00770 ****************************************************************************/
00771 
00772 static void defer_open(struct share_mode_lock *lck,
00773                        struct timeval request_time,
00774                        struct timeval timeout,
00775                        struct deferred_open_record *state)
00776 {
00777         uint16 mid = get_current_mid();
00778         int i;
00779 
00780         /* Paranoia check */
00781 
00782         for (i=0; i<lck->num_share_modes; i++) {
00783                 struct share_mode_entry *e = &lck->share_modes[i];
00784 
00785                 if (!is_deferred_open_entry(e)) {
00786                         continue;
00787                 }
00788 
00789                 if (procid_is_me(&e->pid) && (e->op_mid == mid)) {
00790                         DEBUG(0, ("Trying to defer an already deferred "
00791                                   "request: mid=%d, exiting\n", mid));
00792                         exit_server("attempt to defer a deferred request");
00793                 }
00794         }
00795 
00796         /* End paranoia check */
00797 
00798         DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred "
00799                   "open entry for mid %u\n",
00800                   (unsigned int)request_time.tv_sec,
00801                   (unsigned int)request_time.tv_usec,
00802                   (unsigned int)mid));
00803 
00804         if (!push_deferred_smb_message(mid, request_time, timeout,
00805                                        (char *)state, sizeof(*state))) {
00806                 exit_server("push_deferred_smb_message failed");
00807         }
00808         add_deferred_open(lck, mid, request_time, state->dev, state->inode);
00809 
00810         /*
00811          * Push the MID of this packet on the signing queue.
00812          * We only do this once, the first time we push the packet
00813          * onto the deferred open queue, as this has a side effect
00814          * of incrementing the response sequence number.
00815          */
00816 
00817         srv_defer_sign_response(mid);
00818 }
00819 
00820 
00821 /****************************************************************************
00822  On overwrite open ensure that the attributes match.
00823 ****************************************************************************/
00824 
00825 static BOOL open_match_attributes(connection_struct *conn,
00826                                   const char *path,
00827                                   uint32 old_dos_attr,
00828                                   uint32 new_dos_attr,
00829                                   mode_t existing_unx_mode,
00830                                   mode_t new_unx_mode,
00831                                   mode_t *returned_unx_mode)
00832 {
00833         uint32 noarch_old_dos_attr, noarch_new_dos_attr;
00834 
00835         noarch_old_dos_attr = (old_dos_attr & ~FILE_ATTRIBUTE_ARCHIVE);
00836         noarch_new_dos_attr = (new_dos_attr & ~FILE_ATTRIBUTE_ARCHIVE);
00837 
00838         if((noarch_old_dos_attr == 0 && noarch_new_dos_attr != 0) || 
00839            (noarch_old_dos_attr != 0 && ((noarch_old_dos_attr & noarch_new_dos_attr) == noarch_old_dos_attr))) {
00840                 *returned_unx_mode = new_unx_mode;
00841         } else {
00842                 *returned_unx_mode = (mode_t)0;
00843         }
00844 
00845         DEBUG(10,("open_match_attributes: file %s old_dos_attr = 0x%x, "
00846                   "existing_unx_mode = 0%o, new_dos_attr = 0x%x "
00847                   "returned_unx_mode = 0%o\n",
00848                   path,
00849                   (unsigned int)old_dos_attr,
00850                   (unsigned int)existing_unx_mode,
00851                   (unsigned int)new_dos_attr,
00852                   (unsigned int)*returned_unx_mode ));
00853 
00854         /* If we're mapping SYSTEM and HIDDEN ensure they match. */
00855         if (lp_map_system(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) {
00856                 if ((old_dos_attr & FILE_ATTRIBUTE_SYSTEM) &&
00857                     !(new_dos_attr & FILE_ATTRIBUTE_SYSTEM)) {
00858                         return False;
00859                 }
00860         }
00861         if (lp_map_hidden(SNUM(conn)) || lp_store_dos_attributes(SNUM(conn))) {
00862                 if ((old_dos_attr & FILE_ATTRIBUTE_HIDDEN) &&
00863                     !(new_dos_attr & FILE_ATTRIBUTE_HIDDEN)) {
00864                         return False;
00865                 }
00866         }
00867         return True;
00868 }
00869 
00870 /****************************************************************************
00871  Special FCB or DOS processing in the case of a sharing violation.
00872  Try and find a duplicated file handle.
00873 ****************************************************************************/
00874 
00875 static files_struct *fcb_or_dos_open(connection_struct *conn,
00876                                      const char *fname, SMB_DEV_T dev,
00877                                      SMB_INO_T inode,
00878                                      uint32 access_mask,
00879                                      uint32 share_access,
00880                                      uint32 create_options)
00881 {
00882         files_struct *fsp;
00883         files_struct *dup_fsp;
00884 
00885         DEBUG(5,("fcb_or_dos_open: attempting old open semantics for "
00886                  "file %s.\n", fname ));
00887 
00888         for(fsp = file_find_di_first(dev, inode); fsp;
00889             fsp = file_find_di_next(fsp)) {
00890 
00891                 DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, "
00892                           "vuid = %u, file_pid = %u, private_options = 0x%x "
00893                           "access_mask = 0x%x\n", fsp->fsp_name,
00894                           fsp->fh->fd, (unsigned int)fsp->vuid,
00895                           (unsigned int)fsp->file_pid,
00896                           (unsigned int)fsp->fh->private_options,
00897                           (unsigned int)fsp->access_mask ));
00898 
00899                 if (fsp->fh->fd != -1 &&
00900                     fsp->vuid == current_user.vuid &&
00901                     fsp->file_pid == global_smbpid &&
00902                     (fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
00903                                                  NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) &&
00904                     (fsp->access_mask & FILE_WRITE_DATA) &&
00905                     strequal(fsp->fsp_name, fname)) {
00906                         DEBUG(10,("fcb_or_dos_open: file match\n"));
00907                         break;
00908                 }
00909         }
00910 
00911         if (!fsp) {
00912                 return NULL;
00913         }
00914 
00915         /* quite an insane set of semantics ... */
00916         if (is_executable(fname) &&
00917             (fsp->fh->private_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) {
00918                 DEBUG(10,("fcb_or_dos_open: file fail due to is_executable.\n"));
00919                 return NULL;
00920         }
00921 
00922         /* We need to duplicate this fsp. */
00923         if (!NT_STATUS_IS_OK(dup_file_fsp(fsp, access_mask, share_access,
00924                                           create_options, &dup_fsp))) {
00925                 return NULL;
00926         }
00927 
00928         return dup_fsp;
00929 }
00930 
00931 /****************************************************************************
00932  Open a file with a share mode - old openX method - map into NTCreate.
00933 ****************************************************************************/
00934 
00935 BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func,
00936                                  uint32 *paccess_mask,
00937                                  uint32 *pshare_mode,
00938                                  uint32 *pcreate_disposition,
00939                                  uint32 *pcreate_options)
00940 {
00941         uint32 access_mask;
00942         uint32 share_mode;
00943         uint32 create_disposition;
00944         uint32 create_options = 0;
00945 
00946         DEBUG(10,("map_open_params_to_ntcreate: fname = %s, deny_mode = 0x%x, "
00947                   "open_func = 0x%x\n",
00948                   fname, (unsigned int)deny_mode, (unsigned int)open_func ));
00949 
00950         /* Create the NT compatible access_mask. */
00951         switch (GET_OPENX_MODE(deny_mode)) {
00952                 case DOS_OPEN_EXEC: /* Implies read-only - used to be FILE_READ_DATA */
00953                 case DOS_OPEN_RDONLY:
00954                         access_mask = FILE_GENERIC_READ;
00955                         break;
00956                 case DOS_OPEN_WRONLY:
00957                         access_mask = FILE_GENERIC_WRITE;
00958                         break;
00959                 case DOS_OPEN_RDWR:
00960                 case DOS_OPEN_FCB:
00961                         access_mask = FILE_GENERIC_READ|FILE_GENERIC_WRITE;
00962                         break;
00963                 default:
00964                         DEBUG(10,("map_open_params_to_ntcreate: bad open mode = 0x%x\n",
00965                                   (unsigned int)GET_OPENX_MODE(deny_mode)));
00966                         return False;
00967         }
00968 
00969         /* Create the NT compatible create_disposition. */
00970         switch (open_func) {
00971                 case OPENX_FILE_EXISTS_FAIL|OPENX_FILE_CREATE_IF_NOT_EXIST:
00972                         create_disposition = FILE_CREATE;
00973                         break;
00974 
00975                 case OPENX_FILE_EXISTS_OPEN:
00976                         create_disposition = FILE_OPEN;
00977                         break;
00978 
00979                 case OPENX_FILE_EXISTS_OPEN|OPENX_FILE_CREATE_IF_NOT_EXIST:
00980                         create_disposition = FILE_OPEN_IF;
00981                         break;
00982        
00983                 case OPENX_FILE_EXISTS_TRUNCATE:
00984                         create_disposition = FILE_OVERWRITE;
00985                         break;
00986 
00987                 case OPENX_FILE_EXISTS_TRUNCATE|OPENX_FILE_CREATE_IF_NOT_EXIST:
00988                         create_disposition = FILE_OVERWRITE_IF;
00989                         break;
00990 
00991                 default:
00992                         /* From samba4 - to be confirmed. */
00993                         if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_EXEC) {
00994                                 create_disposition = FILE_CREATE;
00995                                 break;
00996                         }
00997                         DEBUG(10,("map_open_params_to_ntcreate: bad "
00998                                   "open_func 0x%x\n", (unsigned int)open_func));
00999                         return False;
01000         }
01001  
01002         /* Create the NT compatible share modes. */
01003         switch (GET_DENY_MODE(deny_mode)) {
01004                 case DENY_ALL:
01005                         share_mode = FILE_SHARE_NONE;
01006                         break;
01007 
01008                 case DENY_WRITE:
01009                         share_mode = FILE_SHARE_READ;
01010                         break;
01011 
01012                 case DENY_READ:
01013                         share_mode = FILE_SHARE_WRITE;
01014                         break;
01015 
01016                 case DENY_NONE:
01017                         share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
01018                         break;
01019 
01020                 case DENY_DOS:
01021                         create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_DOS;
01022                         if (is_executable(fname)) {
01023                                 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
01024                         } else {
01025                                 if (GET_OPENX_MODE(deny_mode) == DOS_OPEN_RDONLY) {
01026                                         share_mode = FILE_SHARE_READ;
01027                                 } else {
01028                                         share_mode = FILE_SHARE_NONE;
01029                                 }
01030                         }
01031                         break;
01032 
01033                 case DENY_FCB:
01034                         create_options |= NTCREATEX_OPTIONS_PRIVATE_DENY_FCB;
01035                         share_mode = FILE_SHARE_NONE;
01036                         break;
01037 
01038                 default:
01039                         DEBUG(10,("map_open_params_to_ntcreate: bad deny_mode 0x%x\n",
01040                                 (unsigned int)GET_DENY_MODE(deny_mode) ));
01041                         return False;
01042         }
01043 
01044         DEBUG(10,("map_open_params_to_ntcreate: file %s, access_mask = 0x%x, "
01045                   "share_mode = 0x%x, create_disposition = 0x%x, "
01046                   "create_options = 0x%x\n",
01047                   fname,
01048                   (unsigned int)access_mask,
01049                   (unsigned int)share_mode,
01050                   (unsigned int)create_disposition,
01051                   (unsigned int)create_options ));
01052 
01053         if (paccess_mask) {
01054                 *paccess_mask = access_mask;
01055         }
01056         if (pshare_mode) {
01057                 *pshare_mode = share_mode;
01058         }
01059         if (pcreate_disposition) {
01060                 *pcreate_disposition = create_disposition;
01061         }
01062         if (pcreate_options) {
01063                 *pcreate_options = create_options;
01064         }
01065 
01066         return True;
01067 
01068 }
01069 
01070 static void schedule_defer_open(struct share_mode_lock *lck, struct timeval request_time)
01071 {
01072         struct deferred_open_record state;
01073 
01074         /* This is a relative time, added to the absolute
01075            request_time value to get the absolute timeout time.
01076            Note that if this is the second or greater time we enter
01077            this codepath for this particular request mid then
01078            request_time is left as the absolute time of the *first*
01079            time this request mid was processed. This is what allows
01080            the request to eventually time out. */
01081 
01082         struct timeval timeout;
01083 
01084         /* Normally the smbd we asked should respond within
01085          * OPLOCK_BREAK_TIMEOUT seconds regardless of whether
01086          * the client did, give twice the timeout as a safety
01087          * measure here in case the other smbd is stuck
01088          * somewhere else. */
01089 
01090         timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0);
01091 
01092         /* Nothing actually uses state.delayed_for_oplocks
01093            but it's handy to differentiate in debug messages
01094            between a 30 second delay due to oplock break, and
01095            a 1 second delay for share mode conflicts. */
01096 
01097         state.delayed_for_oplocks = True;
01098         state.dev = lck->dev;
01099         state.inode = lck->ino;
01100 
01101         if (!request_timed_out(request_time, timeout)) {
01102                 defer_open(lck, request_time, timeout, &state);
01103         }
01104 }
01105 
01106 /****************************************************************************
01107  Open a file with a share mode.
01108 ****************************************************************************/
01109 
01110 NTSTATUS open_file_ntcreate(connection_struct *conn,
01111                             const char *fname,
01112                             SMB_STRUCT_STAT *psbuf,
01113                             uint32 access_mask,         /* access bits (FILE_READ_DATA etc.) */
01114                             uint32 share_access,        /* share constants (FILE_SHARE_READ etc) */
01115                             uint32 create_disposition,  /* FILE_OPEN_IF etc. */
01116                             uint32 create_options,      /* options such as delete on close. */
01117                             uint32 new_dos_attributes,  /* attributes used for new file. */
01118                             int oplock_request,         /* internal Samba oplock codes. */
01119                                                         /* Information (FILE_EXISTS etc.) */
01120                             int *pinfo,
01121                             files_struct **result)
01122 {
01123         int flags=0;
01124         int flags2=0;
01125         BOOL file_existed = VALID_STAT(*psbuf);
01126         BOOL def_acl = False;
01127         BOOL posix_open = False;
01128         BOOL new_file_created = False;
01129         SMB_DEV_T dev = 0;
01130         SMB_INO_T inode = 0;
01131         NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED;
01132         files_struct *fsp = NULL;
01133         mode_t new_unx_mode = (mode_t)0;
01134         mode_t unx_mode = (mode_t)0;
01135         int info;
01136         uint32 existing_dos_attributes = 0;
01137         struct pending_message_list *pml = NULL;
01138         uint16 mid = get_current_mid();
01139         struct timeval request_time = timeval_zero();
01140         struct share_mode_lock *lck = NULL;
01141         uint32 open_access_mask = access_mask;
01142         NTSTATUS status;
01143         int ret_flock;
01144         char *parent_dir;
01145         const char *newname;
01146 
01147         if (conn->printer) {
01148                 /* 
01149                  * Printers are handled completely differently.
01150                  * Most of the passed parameters are ignored.
01151                  */
01152 
01153                 if (pinfo) {
01154                         *pinfo = FILE_WAS_CREATED;
01155                 }
01156 
01157                 DEBUG(10, ("open_file_ntcreate: printer open fname=%s\n", fname));
01158 
01159                 return print_fsp_open(conn, fname, result);
01160         }
01161 
01162         if (!parent_dirname_talloc(tmp_talloc_ctx(), fname, &parent_dir,
01163                                    &newname)) {
01164                 return NT_STATUS_NO_MEMORY;
01165         }
01166 
01167         if (new_dos_attributes & FILE_FLAG_POSIX_SEMANTICS) {
01168                 posix_open = True;
01169                 unx_mode = (mode_t)(new_dos_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
01170                 new_dos_attributes = 0;
01171         } else {
01172                 /* We add aARCH to this as this mode is only used if the file is
01173                  * created new. */
01174                 unx_mode = unix_mode(conn, new_dos_attributes | aARCH, fname,
01175                                      parent_dir);
01176         }
01177 
01178         DEBUG(10, ("open_file_ntcreate: fname=%s, dos_attrs=0x%x "
01179                    "access_mask=0x%x share_access=0x%x "
01180                    "create_disposition = 0x%x create_options=0x%x "
01181                    "unix mode=0%o oplock_request=%d\n",
01182                    fname, new_dos_attributes, access_mask, share_access,
01183                    create_disposition, create_options, unx_mode,
01184                    oplock_request));
01185 
01186         if ((pml = get_open_deferred_message(mid)) != NULL) {
01187                 struct deferred_open_record *state =
01188                         (struct deferred_open_record *)pml->private_data.data;
01189 
01190                 /* Remember the absolute time of the original
01191                    request with this mid. We'll use it later to
01192                    see if this has timed out. */
01193 
01194                 request_time = pml->request_time;
01195 
01196                 /* Remove the deferred open entry under lock. */
01197                 lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL);
01198                 if (lck == NULL) {
01199                         DEBUG(0, ("could not get share mode lock\n"));
01200                 } else {
01201                         del_deferred_open_entry(lck, mid);
01202                         TALLOC_FREE(lck);
01203                 }
01204 
01205                 /* Ensure we don't reprocess this message. */
01206                 remove_deferred_open_smb_message(mid);
01207         }
01208 
01209         status = check_name(conn, fname);
01210         if (!NT_STATUS_IS_OK(status)) {
01211                 return status;
01212         } 
01213 
01214         if (!posix_open) {
01215                 new_dos_attributes &= SAMBA_ATTRIBUTES_MASK;
01216                 if (file_existed) {
01217                         existing_dos_attributes = dos_mode(conn, fname, psbuf);
01218                 }
01219         }
01220 
01221         /* ignore any oplock requests if oplocks are disabled */
01222         if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break ||
01223             IS_VETO_OPLOCK_PATH(conn, fname)) {
01224                 /* Mask off everything except the private Samba bits. */
01225                 oplock_request &= SAMBA_PRIVATE_OPLOCK_MASK;
01226         }
01227 
01228         /* this is for OS/2 long file names - say we don't support them */
01229         if (!lp_posix_pathnames() && strstr(fname,".+,;=[].")) {
01230                 /* OS/2 Workplace shell fix may be main code stream in a later
01231                  * release. */
01232                 DEBUG(5,("open_file_ntcreate: OS/2 long filenames are not "
01233                          "supported.\n"));
01234                 if (use_nt_status()) {
01235                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
01236                 }
01237                 return NT_STATUS_DOS(ERRDOS, ERRcannotopen);
01238         }
01239 
01240         switch( create_disposition ) {
01241                 /*
01242                  * Currently we're using FILE_SUPERSEDE as the same as
01243                  * FILE_OVERWRITE_IF but they really are
01244                  * different. FILE_SUPERSEDE deletes an existing file
01245                  * (requiring delete access) then recreates it.
01246                  */
01247                 case FILE_SUPERSEDE:
01248                         /* If file exists replace/overwrite. If file doesn't
01249                          * exist create. */
01250                         flags2 |= (O_CREAT | O_TRUNC);
01251                         break;
01252 
01253                 case FILE_OVERWRITE_IF:
01254                         /* If file exists replace/overwrite. If file doesn't
01255                          * exist create. */
01256                         flags2 |= (O_CREAT | O_TRUNC);
01257                         break;
01258 
01259                 case FILE_OPEN:
01260                         /* If file exists open. If file doesn't exist error. */
01261                         if (!file_existed) {
01262                                 DEBUG(5,("open_file_ntcreate: FILE_OPEN "
01263                                          "requested for file %s and file "
01264                                          "doesn't exist.\n", fname ));
01265                                 errno = ENOENT;
01266                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
01267                         }
01268                         break;
01269 
01270                 case FILE_OVERWRITE:
01271                         /* If file exists overwrite. If file doesn't exist
01272                          * error. */
01273                         if (!file_existed) {
01274                                 DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE "
01275                                          "requested for file %s and file "
01276                                          "doesn't exist.\n", fname ));
01277                                 errno = ENOENT;
01278                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
01279                         }
01280                         flags2 |= O_TRUNC;
01281                         break;
01282 
01283                 case FILE_CREATE:
01284                         /* If file exists error. If file doesn't exist
01285                          * create. */
01286                         if (file_existed) {
01287                                 DEBUG(5,("open_file_ntcreate: FILE_CREATE "
01288                                          "requested for file %s and file "
01289                                          "already exists.\n", fname ));
01290                                 if (S_ISDIR(psbuf->st_mode)) {
01291                                         errno = EISDIR;
01292                                 } else {
01293                                         errno = EEXIST;
01294                                 }
01295                                 return map_nt_error_from_unix(errno);
01296                         }
01297                         flags2 |= (O_CREAT|O_EXCL);
01298                         break;
01299 
01300                 case FILE_OPEN_IF:
01301                         /* If file exists open. If file doesn't exist
01302                          * create. */
01303                         flags2 |= O_CREAT;
01304                         break;
01305 
01306                 default:
01307                         return NT_STATUS_INVALID_PARAMETER;
01308         }
01309 
01310         /* We only care about matching attributes on file exists and
01311          * overwrite. */
01312 
01313         if (!posix_open && file_existed && ((create_disposition == FILE_OVERWRITE) ||
01314                              (create_disposition == FILE_OVERWRITE_IF))) {
01315                 if (!open_match_attributes(conn, fname,
01316                                            existing_dos_attributes,
01317                                            new_dos_attributes, psbuf->st_mode,
01318                                            unx_mode, &new_unx_mode)) {
01319                         DEBUG(5,("open_file_ntcreate: attributes missmatch "
01320                                  "for file %s (%x %x) (0%o, 0%o)\n",
01321                                  fname, existing_dos_attributes,
01322                                  new_dos_attributes,
01323                                  (unsigned int)psbuf->st_mode,
01324                                  (unsigned int)unx_mode ));
01325                         errno = EACCES;
01326                         return NT_STATUS_ACCESS_DENIED;
01327                 }
01328         }
01329 
01330         /* This is a nasty hack - must fix... JRA. */
01331         if (access_mask == MAXIMUM_ALLOWED_ACCESS) {
01332                 open_access_mask = access_mask = FILE_GENERIC_ALL;
01333         }
01334 
01335         /*
01336          * Convert GENERIC bits to specific bits.
01337          */
01338 
01339         se_map_generic(&access_mask, &file_generic_mapping);
01340         open_access_mask = access_mask;
01341 
01342         if (flags2 & O_TRUNC) {
01343                 open_access_mask |= FILE_WRITE_DATA; /* This will cause oplock breaks. */
01344         }
01345 
01346         DEBUG(10, ("open_file_ntcreate: fname=%s, after mapping "
01347                    "access_mask=0x%x\n", fname, access_mask ));
01348 
01349         /*
01350          * Note that we ignore the append flag as append does not
01351          * mean the same thing under DOS and Unix.
01352          */
01353 
01354         if (access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) {
01355                 /* DENY_DOS opens are always underlying read-write on the
01356                    file handle, no matter what the requested access mask
01357                     says. */
01358                 if ((create_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS) ||
01359                         access_mask & (FILE_READ_ATTRIBUTES|FILE_READ_DATA|FILE_READ_EA|FILE_EXECUTE)) {
01360                         flags = O_RDWR;
01361                 } else {
01362                         flags = O_WRONLY;
01363                 }
01364         } else {
01365                 flags = O_RDONLY;
01366         }
01367 
01368         /*
01369          * Currently we only look at FILE_WRITE_THROUGH for create options.
01370          */
01371 
01372 #if defined(O_SYNC)
01373         if ((create_options & FILE_WRITE_THROUGH) && lp_strict_sync(SNUM(conn))) {
01374                 flags2 |= O_SYNC;
01375         }
01376 #endif /* O_SYNC */
01377   
01378         if (posix_open && (access_mask & FILE_APPEND_DATA)) {
01379                 flags2 |= O_APPEND;
01380         }
01381 
01382         if (!posix_open && !CAN_WRITE(conn)) {
01383                 /*
01384                  * We should really return a permission denied error if either
01385                  * O_CREAT or O_TRUNC are set, but for compatibility with
01386                  * older versions of Samba we just AND them out.
01387                  */
01388                 flags2 &= ~(O_CREAT|O_TRUNC);
01389         }
01390 
01391         /*
01392          * Ensure we can't write on a read-only share or file.
01393          */
01394 
01395         if (flags != O_RDONLY && file_existed &&
01396             (!CAN_WRITE(conn) || IS_DOS_READONLY(existing_dos_attributes))) {
01397                 DEBUG(5,("open_file_ntcreate: write access requested for "
01398                          "file %s on read only %s\n",
01399                          fname, !CAN_WRITE(conn) ? "share" : "file" ));
01400                 errno = EACCES;
01401                 return NT_STATUS_ACCESS_DENIED;
01402         }
01403 
01404         status = file_new(conn, &fsp);
01405         if(!NT_STATUS_IS_OK(status)) {
01406                 return status;
01407         }
01408 
01409         fsp->dev = psbuf->st_dev;
01410         fsp->inode = psbuf->st_ino;
01411         fsp->share_access = share_access;
01412         fsp->fh->private_options = create_options;
01413         fsp->access_mask = open_access_mask; /* We change this to the
01414                                               * requested access_mask after
01415                                               * the open is done. */
01416         fsp->posix_open = posix_open;
01417 
01418         /* Ensure no SAMBA_PRIVATE bits can be set. */
01419         fsp->oplock_type = (oplock_request & ~SAMBA_PRIVATE_OPLOCK_MASK);
01420 
01421         if (timeval_is_zero(&request_time)) {
01422                 request_time = fsp->open_time;
01423         }
01424 
01425         if (file_existed) {
01426                 dev = psbuf->st_dev;
01427                 inode = psbuf->st_ino;
01428 
01429                 lck = get_share_mode_lock(NULL, dev, inode,
01430                                           conn->connectpath,
01431                                           fname);
01432 
01433                 if (lck == NULL) {
01434                         file_free(fsp);
01435                         DEBUG(0, ("Could not get share mode lock\n"));
01436                         return NT_STATUS_SHARING_VIOLATION;
01437                 }
01438 
01439                 /* First pass - send break only on batch oplocks. */
01440                 if (delay_for_oplocks(lck, fsp, 1, oplock_request)) {
01441                         schedule_defer_open(lck, request_time);
01442                         TALLOC_FREE(lck);
01443                         file_free(fsp);
01444                         return NT_STATUS_SHARING_VIOLATION;
01445                 }
01446 
01447                 /* Use the client requested access mask here, not the one we
01448                  * open with. */
01449                 status = open_mode_check(conn, fname, lck,
01450                                          access_mask, share_access,
01451                                          create_options, &file_existed);
01452 
01453                 if (NT_STATUS_IS_OK(status)) {
01454                         /* We might be going to allow this open. Check oplock
01455                          * status again. */
01456                         /* Second pass - send break for both batch or
01457                          * exclusive oplocks. */
01458                         if (delay_for_oplocks(lck, fsp, 2, oplock_request)) {
01459                                 schedule_defer_open(lck, request_time);
01460                                 TALLOC_FREE(lck);
01461                                 file_free(fsp);
01462                                 return NT_STATUS_SHARING_VIOLATION;
01463                         }
01464                 }
01465 
01466                 if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) {
01467                         /* DELETE_PENDING is not deferred for a second */
01468                         TALLOC_FREE(lck);
01469                         file_free(fsp);
01470                         return status;
01471                 }
01472 
01473                 if (!NT_STATUS_IS_OK(status)) {
01474                         uint32 can_access_mask;
01475                         BOOL can_access = True;
01476 
01477                         SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION));
01478 
01479                         /* Check if this can be done with the deny_dos and fcb
01480                          * calls. */
01481                         if (create_options &
01482                             (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS|
01483                              NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
01484                                 files_struct *fsp_dup;
01485 
01486                                 /* Use the client requested access mask here,
01487                                  * not the one we open with. */
01488                                 fsp_dup = fcb_or_dos_open(conn, fname, dev,
01489                                                           inode, access_mask,
01490                                                           share_access,
01491                                                           create_options);
01492 
01493                                 if (fsp_dup) {
01494                                         TALLOC_FREE(lck);
01495                                         file_free(fsp);
01496                                         if (pinfo) {
01497                                                 *pinfo = FILE_WAS_OPENED;
01498                                         }
01499                                         conn->num_files_open++;
01500                                         *result = fsp_dup;
01501                                         return NT_STATUS_OK;
01502                                 }
01503                         }
01504 
01505                         /*
01506                          * This next line is a subtlety we need for
01507                          * MS-Access. If a file open will fail due to share
01508                          * permissions and also for security (access) reasons,
01509                          * we need to return the access failed error, not the
01510                          * share error. We can't open the file due to kernel
01511                          * oplock deadlock (it's possible we failed above on
01512                          * the open_mode_check()) so use a userspace check.
01513                          */
01514 
01515                         if (flags & O_RDWR) {
01516                                 can_access_mask = FILE_READ_DATA|FILE_WRITE_DATA;
01517                         } else if (flags & O_WRONLY) {
01518                                 can_access_mask = FILE_WRITE_DATA;
01519                         } else {
01520                                 can_access_mask = FILE_READ_DATA;
01521                         }
01522 
01523                         if (((can_access_mask & FILE_WRITE_DATA) && !CAN_WRITE(conn)) ||
01524                             !can_access_file(conn,fname,psbuf,can_access_mask)) {
01525                                 can_access = False;
01526                         }
01527 
01528                         /* 
01529                          * If we're returning a share violation, ensure we
01530                          * cope with the braindead 1 second delay.
01531                          */
01532 
01533                         if (!(oplock_request & INTERNAL_OPEN_ONLY) &&
01534                             lp_defer_sharing_violations()) {
01535                                 struct timeval timeout;
01536                                 struct deferred_open_record state;
01537                                 int timeout_usecs;
01538 
01539                                 /* this is a hack to speed up torture tests
01540                                    in 'make test' */
01541                                 timeout_usecs = lp_parm_int(SNUM(conn),
01542                                                             "smbd","sharedelay",
01543                                                             SHARING_VIOLATION_USEC_WAIT);
01544 
01545                                 /* This is a relative time, added to the absolute
01546                                    request_time value to get the absolute timeout time.
01547                                    Note that if this is the second or greater time we enter
01548                                    this codepath for this particular request mid then
01549                                    request_time is left as the absolute time of the *first*
01550                                    time this request mid was processed. This is what allows
01551                                    the request to eventually time out. */
01552 
01553                                 timeout = timeval_set(0, timeout_usecs);
01554 
01555                                 /* Nothing actually uses state.delayed_for_oplocks
01556                                    but it's handy to differentiate in debug messages
01557                                    between a 30 second delay due to oplock break, and
01558                                    a 1 second delay for share mode conflicts. */
01559 
01560                                 state.delayed_for_oplocks = False;
01561                                 state.dev = dev;
01562                                 state.inode = inode;
01563 
01564                                 if (!request_timed_out(request_time,
01565                                                        timeout)) {
01566                                         defer_open(lck, request_time, timeout,
01567                                                    &state);
01568                                 }
01569                         }
01570 
01571                         TALLOC_FREE(lck);
01572                         if (can_access) {
01573                                 /*
01574                                  * We have detected a sharing violation here
01575                                  * so return the correct error code
01576                                  */
01577                                 status = NT_STATUS_SHARING_VIOLATION;
01578                         } else {
01579                                 status = NT_STATUS_ACCESS_DENIED;
01580                         }
01581                         file_free(fsp);
01582                         return status;
01583                 }
01584 
01585                 /*
01586                  * We exit this block with the share entry *locked*.....
01587                  */
01588         }
01589 
01590         SMB_ASSERT(!file_existed || (lck != NULL));
01591 
01592         /*
01593          * Ensure we pay attention to default ACLs on directories if required.
01594          */
01595 
01596         if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) &&
01597             (def_acl = directory_has_default_acl(conn, parent_dir))) {
01598                 unx_mode = 0777;
01599         }
01600 
01601         DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o, "
01602                 "access_mask = 0x%x, open_access_mask = 0x%x\n",
01603                  (unsigned int)flags, (unsigned int)flags2,
01604                  (unsigned int)unx_mode, (unsigned int)access_mask,
01605                  (unsigned int)open_access_mask));
01606 
01607         /*
01608          * open_file strips any O_TRUNC flags itself.
01609          */
01610 
01611         fsp_open = open_file(fsp, conn, parent_dir, newname, fname, psbuf,
01612                              flags|flags2, unx_mode, access_mask,
01613                              open_access_mask);
01614 
01615         if (!NT_STATUS_IS_OK(fsp_open)) {
01616                 if (lck != NULL) {
01617                         TALLOC_FREE(lck);
01618                 }
01619                 file_free(fsp);
01620                 return fsp_open;
01621         }
01622 
01623         if (!file_existed) {
01624 
01625                 /*
01626                  * Deal with the race condition where two smbd's detect the
01627                  * file doesn't exist and do the create at the same time. One
01628                  * of them will win and set a share mode, the other (ie. this
01629                  * one) should check if the requested share mode for this
01630                  * create is allowed.
01631                  */
01632 
01633                 /*
01634                  * Now the file exists and fsp is successfully opened,
01635                  * fsp->dev and fsp->inode are valid and should replace the
01636                  * dev=0,inode=0 from a non existent file. Spotted by
01637                  * Nadav Danieli <nadavd@exanet.com>. JRA.
01638                  */
01639 
01640                 dev = fsp->dev;
01641                 inode = fsp->inode;
01642 
01643                 lck = get_share_mode_lock(NULL, dev, inode,
01644                                           conn->connectpath,
01645                                           fname);
01646 
01647                 if (lck == NULL) {
01648                         DEBUG(0, ("open_file_ntcreate: Could not get share "
01649                                   "mode lock for %s\n", fname));
01650                         fd_close(conn, fsp);
01651                         file_free(fsp);
01652                         return NT_STATUS_SHARING_VIOLATION;
01653                 }
01654 
01655                 /* First pass - send break only on batch oplocks. */
01656                 if (delay_for_oplocks(lck, fsp, 1, oplock_request)) {
01657                         schedule_defer_open(lck, request_time);
01658                         TALLOC_FREE(lck);
01659                         fd_close(conn, fsp);
01660                         file_free(fsp);
01661                         return NT_STATUS_SHARING_VIOLATION;
01662                 }
01663 
01664                 status = open_mode_check(conn, fname, lck,
01665                                          access_mask, share_access,
01666                                          create_options, &file_existed);
01667 
01668                 if (NT_STATUS_IS_OK(status)) {
01669                         /* We might be going to allow this open. Check oplock
01670                          * status again. */
01671                         /* Second pass - send break for both batch or
01672                          * exclusive oplocks. */
01673                         if (delay_for_oplocks(lck, fsp, 2, oplock_request)) {
01674                                 schedule_defer_open(lck, request_time);
01675                                 TALLOC_FREE(lck);
01676                                 fd_close(conn, fsp);
01677                                 file_free(fsp);
01678                                 return NT_STATUS_SHARING_VIOLATION;
01679                         }
01680                 }
01681 
01682                 if (!NT_STATUS_IS_OK(status)) {
01683                         struct deferred_open_record state;
01684 
01685                         fd_close(conn, fsp);
01686                         file_free(fsp);
01687 
01688                         state.delayed_for_oplocks = False;
01689                         state.dev = dev;
01690                         state.inode = inode;
01691 
01692                         /* Do it all over again immediately. In the second
01693                          * round we will find that the file existed and handle
01694                          * the DELETE_PENDING and FCB cases correctly. No need
01695                          * to duplicate the code here. Essentially this is a
01696                          * "goto top of this function", but don't tell
01697                          * anybody... */
01698 
01699                         defer_open(lck, request_time, timeval_zero(),
01700                                    &state);
01701                         TALLOC_FREE(lck);
01702                         return status;
01703                 }
01704 
01705                 /*
01706                  * We exit this block with the share entry *locked*.....
01707                  */
01708 
01709         }
01710 
01711         SMB_ASSERT(lck != NULL);
01712 
01713         /* note that we ignore failure for the following. It is
01714            basically a hack for NFS, and NFS will never set one of
01715            these only read them. Nobody but Samba can ever set a deny
01716            mode and we have already checked our more authoritative
01717            locking database for permission to set this deny mode. If
01718            the kernel refuses the operations then the kernel is wrong.
01719            note that GPFS supports it as well - jmcd */
01720 
01721         ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, fsp->fh->fd, share_access);
01722         if(ret_flock == -1 ){
01723 
01724                 TALLOC_FREE(lck);
01725                 fd_close(conn, fsp);
01726                 file_free(fsp);
01727                 
01728                 return NT_STATUS_SHARING_VIOLATION;
01729         }
01730 
01731         /*
01732          * At this point onwards, we can guarentee that the share entry
01733          * is locked, whether we created the file or not, and that the
01734          * deny mode is compatible with all current opens.
01735          */
01736 
01737         /*
01738          * If requested, truncate the file.
01739          */
01740 
01741         if (flags2&O_TRUNC) {
01742                 /*
01743                  * We are modifing the file after open - update the stat
01744                  * struct..
01745                  */
01746                 if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) ||
01747                     (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) {
01748                         status = map_nt_error_from_unix(errno);
01749                         TALLOC_FREE(lck);
01750                         fd_close(conn,fsp);
01751                         file_free(fsp);
01752                         return status;
01753                 }
01754         }
01755 
01756         /* Record the options we were opened with. */
01757         fsp->share_access = share_access;
01758         fsp->fh->private_options = create_options;
01759         fsp->access_mask = access_mask;
01760 
01761         if (file_existed) {
01762                 /* stat opens on existing files don't get oplocks. */
01763                 if (is_stat_open(open_access_mask)) {
01764                         fsp->oplock_type = NO_OPLOCK;
01765                 }
01766 
01767                 if (!(flags2 & O_TRUNC)) {
01768                         info = FILE_WAS_OPENED;
01769                 } else {
01770                         info = FILE_WAS_OVERWRITTEN;
01771                 }
01772         } else {
01773                 info = FILE_WAS_CREATED;
01774         }
01775 
01776         if (pinfo) {
01777                 *pinfo = info;
01778         }
01779 
01780         /* 
01781          * Setup the oplock info in both the shared memory and
01782          * file structs.
01783          */
01784 
01785         if ((fsp->oplock_type != NO_OPLOCK) &&
01786             (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
01787                 if (!set_file_oplock(fsp, fsp->oplock_type)) {
01788                         /* Could not get the kernel oplock */
01789                         fsp->oplock_type = NO_OPLOCK;
01790                 }
01791         }
01792 
01793         if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || info == FILE_WAS_SUPERSEDED) {
01794                 new_file_created = True;
01795         }
01796 
01797         set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type, new_file_created);
01798 
01799         /* Handle strange delete on close create semantics. */
01800         if ((create_options & FILE_DELETE_ON_CLOSE) && can_set_initial_delete_on_close(lck)) {
01801                 status = can_set_delete_on_close(fsp, True, new_dos_attributes);
01802 
01803                 if (!NT_STATUS_IS_OK(status)) {
01804                         /* Remember to delete the mode we just added. */
01805                         del_share_mode(lck, fsp);
01806                         TALLOC_FREE(lck);
01807                         fd_close(conn,fsp);
01808                         file_free(fsp);
01809                         return status;
01810                 }
01811                 /* Note that here we set the *inital* delete on close flag,
01812                    not the regular one. The magic gets handled in close. */
01813                 fsp->initial_delete_on_close = True;
01814         }
01815         
01816         if (new_file_created) {
01817                 /* Files should be initially set as archive */
01818                 if (lp_map_archive(SNUM(conn)) ||
01819                     lp_store_dos_attributes(SNUM(conn))) {
01820                         if (!posix_open) {
01821                                 SMB_STRUCT_STAT tmp_sbuf;
01822                                 SET_STAT_INVALID(tmp_sbuf);
01823                                 if (file_set_dosmode(
01824                                                 conn, fname,
01825                                                 new_dos_attributes | aARCH,
01826                                                 &tmp_sbuf,
01827                                                 parent_dir) == 0) {
01828                                         unx_mode = tmp_sbuf.st_mode;
01829                                 }
01830                         }
01831                 }
01832         }
01833 
01834         /*
01835          * Take care of inherited ACLs on created files - if default ACL not
01836          * selected.
01837          */
01838 
01839         if (!posix_open && !file_existed && !def_acl) {
01840 
01841                 int saved_errno = errno; /* We might get ENOSYS in the next
01842                                           * call.. */
01843 
01844                 if (SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd, unx_mode) == -1 &&
01845                     errno == ENOSYS) {
01846                         errno = saved_errno; /* Ignore ENOSYS */
01847                 }
01848 
01849         } else if (new_unx_mode) {
01850 
01851                 int ret = -1;
01852 
01853                 /* Attributes need changing. File already existed. */
01854 
01855                 {
01856                         int saved_errno = errno; /* We might get ENOSYS in the
01857                                                   * next call.. */
01858                         ret = SMB_VFS_FCHMOD_ACL(fsp, fsp->fh->fd,
01859                                                  new_unx_mode);
01860 
01861                         if (ret == -1 && errno == ENOSYS) {
01862                                 errno = saved_errno; /* Ignore ENOSYS */
01863                         } else {
01864                                 DEBUG(5, ("open_file_ntcreate: reset "
01865                                           "attributes of file %s to 0%o\n",
01866                                           fname, (unsigned int)new_unx_mode));
01867                                 ret = 0; /* Don't do the fchmod below. */
01868                         }
01869                 }
01870 
01871                 if ((ret == -1) &&
01872                     (SMB_VFS_FCHMOD(fsp, fsp->fh->fd, new_unx_mode) == -1))
01873                         DEBUG(5, ("open_file_ntcreate: failed to reset "
01874                                   "attributes of file %s to 0%o\n",
01875                                   fname, (unsigned int)new_unx_mode));
01876         }
01877 
01878         /* If this is a successful open, we must remove any deferred open
01879          * records. */
01880         del_deferred_open_entry(lck, mid);
01881         TALLOC_FREE(lck);
01882 
01883         conn->num_files_open++;
01884 
01885         *result = fsp;
01886         return NT_STATUS_OK;
01887 }
01888 
01889 /****************************************************************************
01890  Open a file for for write to ensure that we can fchmod it.
01891 ****************************************************************************/
01892 
01893 NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname,
01894                           SMB_STRUCT_STAT *psbuf, files_struct **result)
01895 {
01896         files_struct *fsp = NULL;
01897         NTSTATUS status;
01898 
01899         if (!VALID_STAT(*psbuf)) {
01900                 return NT_STATUS_INVALID_PARAMETER;
01901         }
01902 
01903         status = file_new(conn, &fsp);
01904         if(!NT_STATUS_IS_OK(status)) {
01905                 return status;
01906         }
01907 
01908         /* note! we must use a non-zero desired access or we don't get
01909            a real file descriptor. Oh what a twisted web we weave. */
01910         status = open_file(fsp, conn, NULL, NULL, fname, psbuf, O_WRONLY, 0,
01911                            FILE_WRITE_DATA, FILE_WRITE_DATA);
01912 
01913         /* 
01914          * This is not a user visible file open.
01915          * Don't set a share mode and don't increment
01916          * the conn->num_files_open.
01917          */
01918 
01919         if (!NT_STATUS_IS_OK(status)) {
01920                 file_free(fsp);
01921                 return status;
01922         }
01923 
01924         *result = fsp;
01925         return NT_STATUS_OK;
01926 }
01927 
01928 /****************************************************************************
01929  Close the fchmod file fd - ensure no locks are lost.
01930 ****************************************************************************/
01931 
01932 NTSTATUS close_file_fchmod(files_struct *fsp)
01933 {
01934         NTSTATUS status = fd_close(fsp->conn, fsp);
01935         file_free(fsp);
01936         return status;
01937 }
01938 
01939 static NTSTATUS mkdir_internal(connection_struct *conn,
01940                                 const char *name,
01941                                 uint32 file_attributes,
01942                                 SMB_STRUCT_STAT *psbuf)
01943 {
01944         mode_t mode;
01945         char *parent_dir;
01946         const char *dirname;
01947         NTSTATUS status;
01948         BOOL posix_open = False;
01949 
01950         if(!CAN_WRITE(conn)) {
01951                 DEBUG(5,("mkdir_internal: failing create on read-only share "
01952                          "%s\n", lp_servicename(SNUM(conn))));
01953                 return NT_STATUS_ACCESS_DENIED;
01954         }
01955 
01956         status = check_name(conn, name);
01957         if (!NT_STATUS_IS_OK(status)) {
01958                 return status;
01959         }
01960 
01961         if (!parent_dirname_talloc(tmp_talloc_ctx(), name, &parent_dir,
01962                                    &dirname)) {
01963                 return NT_STATUS_NO_MEMORY;
01964         }
01965 
01966         if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
01967                 posix_open = True;
01968                 mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
01969         } else {
01970                 mode = unix_mode(conn, aDIR, name, parent_dir);
01971         }
01972 
01973         if (SMB_VFS_MKDIR(conn, name, mode) != 0) {
01974                 return map_nt_error_from_unix(errno);
01975         }
01976 
01977         /* Ensure we're checking for a symlink here.... */
01978         /* We don't want to get caught by a symlink racer. */
01979 
01980         if (SMB_VFS_LSTAT(conn, name, psbuf) == -1) {
01981                 DEBUG(2, ("Could not stat directory '%s' just created: %s\n",
01982                           name, strerror(errno)));
01983                 return map_nt_error_from_unix(errno);
01984         }
01985 
01986         if (!S_ISDIR(psbuf->st_mode)) {
01987                 DEBUG(0, ("Directory just '%s' created is not a directory\n",
01988                           name));
01989                 return NT_STATUS_ACCESS_DENIED;
01990         }
01991 
01992         if (lp_store_dos_attributes(SNUM(conn))) {
01993                 if (!posix_open) {
01994                         file_set_dosmode(conn, name,
01995                                  file_attributes | aDIR, NULL,
01996                                  parent_dir);
01997                 }
01998         }
01999 
02000         if (lp_inherit_perms(SNUM(conn))) {
02001                 inherit_access_acl(conn, parent_dir, name, mode);
02002         }
02003 
02004         if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
02005                 /*
02006                  * Check if high bits should have been set,
02007                  * then (if bits are missing): add them.
02008                  * Consider bits automagically set by UNIX, i.e. SGID bit from parent
02009                  * dir.
02010                  */
02011                 if (mode & ~(S_IRWXU|S_IRWXG|S_IRWXO) && (mode & ~psbuf->st_mode)) {
02012                         SMB_VFS_CHMOD(conn, name,
02013                                       psbuf->st_mode | (mode & ~psbuf->st_mode));
02014                 }
02015         }
02016 
02017         /* Change the owner if required. */
02018         if (lp_inherit_owner(SNUM(conn))) {
02019                 change_dir_owner_to_parent(conn, parent_dir, name, psbuf);
02020         }
02021 
02022         notify_fname(conn, NOTIFY_ACTION_ADDED, FILE_NOTIFY_CHANGE_DIR_NAME,
02023                      name);
02024 
02025         return NT_STATUS_OK;
02026 }
02027 
02028 /****************************************************************************
02029  Open a directory from an NT SMB call.
02030 ****************************************************************************/
02031 
02032 NTSTATUS open_directory(connection_struct *conn,
02033                         const char *fname,
02034                         SMB_STRUCT_STAT *psbuf,
02035                         uint32 access_mask,
02036                         uint32 share_access,
02037                         uint32 create_disposition,
02038                         uint32 create_options,
02039                         uint32 file_attributes,
02040                         int *pinfo,
02041                         files_struct **result)
02042 {
02043         files_struct *fsp = NULL;
02044         BOOL dir_existed = VALID_STAT(*psbuf) ? True : False;
02045         struct share_mode_lock *lck = NULL;
02046         NTSTATUS status;
02047         int info = 0;
02048 
02049         DEBUG(5,("open_directory: opening directory %s, access_mask = 0x%x, "
02050                  "share_access = 0x%x create_options = 0x%x, "
02051                  "create_disposition = 0x%x, file_attributes = 0x%x\n",
02052                  fname,
02053                  (unsigned int)access_mask,
02054                  (unsigned int)share_access,
02055                  (unsigned int)create_options,
02056                  (unsigned int)create_disposition,
02057                  (unsigned int)file_attributes));
02058 
02059         if (is_ntfs_stream_name(fname)) {
02060                 DEBUG(0,("open_directory: %s is a stream name!\n", fname ));
02061                 return NT_STATUS_NOT_A_DIRECTORY;
02062         }
02063 
02064         switch( create_disposition ) {
02065                 case FILE_OPEN:
02066 
02067                         info = FILE_WAS_OPENED;
02068 
02069                         /*
02070                          * We want to follow symlinks here.
02071                          */
02072 
02073                         if (SMB_VFS_STAT(conn, fname, psbuf) != 0) {
02074                                 return map_nt_error_from_unix(errno);
02075                         }
02076                                 
02077                         break;
02078 
02079                 case FILE_CREATE:
02080 
02081                         /* If directory exists error. If directory doesn't
02082                          * exist create. */
02083 
02084                         status = mkdir_internal(conn,
02085                                                 fname,
02086                                                 file_attributes,
02087                                                 psbuf);
02088 
02089                         if (!NT_STATUS_IS_OK(status)) {
02090                                 DEBUG(2, ("open_directory: unable to create "
02091                                           "%s. Error was %s\n", fname,
02092                                           nt_errstr(status)));
02093                                 return status;
02094                         }
02095 
02096                         info = FILE_WAS_CREATED;
02097                         break;
02098 
02099                 case FILE_OPEN_IF:
02100                         /*
02101                          * If directory exists open. If directory doesn't
02102                          * exist create.
02103                          */
02104 
02105                         status = mkdir_internal(conn,
02106                                                 fname,
02107                                                 file_attributes,
02108                                                 psbuf);
02109 
02110                         if (NT_STATUS_IS_OK(status)) {
02111                                 info = FILE_WAS_CREATED;
02112                         }
02113 
02114                         if (NT_STATUS_EQUAL(status,
02115                                             NT_STATUS_OBJECT_NAME_COLLISION)) {
02116                                 info = FILE_WAS_OPENED;
02117                                 status = NT_STATUS_OK;
02118                         }
02119                                 
02120                         break;
02121 
02122                 case FILE_SUPERSEDE:
02123                 case FILE_OVERWRITE:
02124                 case FILE_OVERWRITE_IF:
02125                 default:
02126                         DEBUG(5,("open_directory: invalid create_disposition "
02127                                  "0x%x for directory %s\n",
02128                                  (unsigned int)create_disposition, fname));
02129                         return NT_STATUS_INVALID_PARAMETER;
02130         }
02131 
02132         if(!S_ISDIR(psbuf->st_mode)) {
02133                 DEBUG(5,("open_directory: %s is not a directory !\n",
02134                          fname ));
02135                 return NT_STATUS_NOT_A_DIRECTORY;
02136         }
02137 
02138         status = file_new(conn, &fsp);
02139         if(!NT_STATUS_IS_OK(status)) {
02140                 return status;
02141         }
02142 
02143         /*
02144          * Setup the files_struct for it.
02145          */
02146         
02147         fsp->mode = psbuf->st_mode;
02148         fsp->inode = psbuf->st_ino;
02149         fsp->dev = psbuf->st_dev;
02150         fsp->vuid = current_user.vuid;
02151         fsp->file_pid = global_smbpid;
02152         fsp->can_lock = False;
02153         fsp->can_read = False;
02154         fsp->can_write = False;
02155 
02156         fsp->share_access = share_access;
02157         fsp->fh->private_options = create_options;
02158         fsp->access_mask = access_mask;
02159 
02160         fsp->print_file = False;
02161         fsp->modified = False;
02162         fsp->oplock_type = NO_OPLOCK;
02163         fsp->sent_oplock_break = NO_BREAK_SENT;
02164         fsp->is_directory = True;
02165         fsp->is_stat = False;
02166         fsp->posix_open = (file_attributes & FILE_FLAG_POSIX_SEMANTICS) ? True : False;
02167 
02168         string_set(&fsp->fsp_name,fname);
02169 
02170         lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode,
02171                                   conn->connectpath,
02172                                   fname);
02173 
02174         if (lck == NULL) {
02175                 DEBUG(0, ("open_directory: Could not get share mode lock for %s\n", fname));
02176                 file_free(fsp);
02177                 return NT_STATUS_SHARING_VIOLATION;
02178         }
02179 
02180         status = open_mode_check(conn, fname, lck,
02181                                 access_mask, share_access,
02182                                 create_options, &dir_existed);
02183 
02184         if (!NT_STATUS_IS_OK(status)) {
02185                 TALLOC_FREE(lck);
02186                 file_free(fsp);
02187                 return status;
02188         }
02189 
02190         set_share_mode(lck, fsp, current_user.ut.uid, 0, NO_OPLOCK, True);
02191 
02192         /* For directories the delete on close bit at open time seems
02193            always to be honored on close... See test 19 in Samba4 BASE-DELETE. */
02194         if (create_options & FILE_DELETE_ON_CLOSE) {
02195                 status = can_set_delete_on_close(fsp, True, 0);
02196                 if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_DIRECTORY_NOT_EMPTY)) {
02197                         TALLOC_FREE(lck);
02198                         file_free(fsp);
02199                         return status;
02200                 }
02201 
02202                 if (NT_STATUS_IS_OK(status)) {
02203                         /* Note that here we set the *inital* delete on close flag,
02204                            not the regular one. The magic gets handled in close. */
02205                         fsp->initial_delete_on_close = True;
02206                 }
02207         }
02208 
02209         TALLOC_FREE(lck);
02210 
02211         if (pinfo) {
02212                 *pinfo = info;
02213         }
02214 
02215         conn->num_files_open++;
02216 
02217         *result = fsp;
02218         return NT_STATUS_OK;
02219 }
02220 
02221 NTSTATUS create_directory(connection_struct *conn, const char *directory)
02222 {
02223         NTSTATUS status;
02224         SMB_STRUCT_STAT sbuf;
02225         files_struct *fsp;
02226 
02227         SET_STAT_INVALID(sbuf);
02228         
02229         status = open_directory(conn, directory, &sbuf,
02230                                 FILE_READ_ATTRIBUTES, /* Just a stat open */
02231                                 FILE_SHARE_NONE, /* Ignored for stat opens */
02232                                 FILE_CREATE,
02233                                 0,
02234                                 FILE_ATTRIBUTE_DIRECTORY,
02235                                 NULL,
02236                                 &fsp);
02237 
02238         if (NT_STATUS_IS_OK(status)) {
02239                 close_file(fsp, NORMAL_CLOSE);
02240         }
02241 
02242         return status;
02243 }
02244 
02245 /****************************************************************************
02246  Open a pseudo-file (no locking checks - a 'stat' open).
02247 ****************************************************************************/
02248 
02249 NTSTATUS open_file_stat(connection_struct *conn, const char *fname,
02250                         SMB_STRUCT_STAT *psbuf, files_struct **result)
02251 {
02252         files_struct *fsp = NULL;
02253         NTSTATUS status;
02254 
02255         if (!VALID_STAT(*psbuf)) {
02256                 return NT_STATUS_INVALID_PARAMETER;
02257         }
02258 
02259         /* Can't 'stat' open directories. */
02260         if(S_ISDIR(psbuf->st_mode)) {
02261                 return NT_STATUS_FILE_IS_A_DIRECTORY;
02262         }
02263 
02264         status = file_new(conn, &fsp);
02265         if(!NT_STATUS_IS_OK(status)) {
02266                 return status;
02267         }
02268 
02269         DEBUG(5,("open_file_stat: 'opening' file %s\n", fname));
02270 
02271         /*
02272          * Setup the files_struct for it.
02273          */
02274         
02275         fsp->mode = psbuf->st_mode;
02276         fsp->inode = psbuf->st_ino;
02277         fsp->dev = psbuf->st_dev;
02278         fsp->vuid = current_user.vuid;
02279         fsp->file_pid = global_smbpid;
02280         fsp->can_lock = False;
02281         fsp->can_read = False;
02282         fsp->can_write = False;
02283         fsp->print_file = False;
02284         fsp->modified = False;
02285         fsp->oplock_type = NO_OPLOCK;
02286         fsp->sent_oplock_break = NO_BREAK_SENT;
02287         fsp->is_directory = False;
02288         fsp->is_stat = True;
02289         string_set(&fsp->fsp_name,fname);
02290 
02291         conn->num_files_open++;
02292 
02293         *result = fsp;
02294         return NT_STATUS_OK;
02295 }
02296 
02297 /****************************************************************************
02298  Receive notification that one of our open files has been renamed by another
02299  smbd process.
02300 ****************************************************************************/
02301 
02302 void msg_file_was_renamed(int msg_type, struct process_id src,
02303                           void *buf, size_t len, void *private_data)
02304 {
02305         files_struct *fsp;
02306         char *frm = (char *)buf;
02307         SMB_DEV_T dev;
02308         SMB_INO_T inode;
02309         const char *sharepath;
02310         const char *newname;
02311         size_t sp_len;
02312 
02313         if (buf == NULL || len < MSG_FILE_RENAMED_MIN_SIZE + 2) {
02314                 DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", (int)len));
02315                 return;
02316         }
02317 
02318         /* Unpack the message. */
02319         dev = DEV_T_VAL(frm,0);
02320         inode = INO_T_VAL(frm,8);
02321         sharepath = &frm[16];
02322         newname = sharepath + strlen(sharepath) + 1;
02323         sp_len = strlen(sharepath);
02324 
02325         DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, "
02326                 "dev %x, inode  %.0f\n",
02327                 sharepath, newname, (unsigned int)dev, (double)inode ));
02328 
02329         for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
02330                 if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) {
02331                         DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n",
02332                                 fsp->fnum, fsp->fsp_name, newname ));
02333                         string_set(&fsp->fsp_name, newname);
02334                 } else {
02335                         /* TODO. JRA. */
02336                         /* Now we have the complete path we can work out if this is
02337                            actually within this share and adjust newname accordingly. */
02338                         DEBUG(10,("msg_file_was_renamed: share mismatch (sharepath %s "
02339                                 "not sharepath %s) "
02340                                 "fnum %d from %s -> %s\n",
02341                                 fsp->conn->connectpath,
02342                                 sharepath,
02343                                 fsp->fnum,
02344                                 fsp->fsp_name,
02345                                 newname ));
02346                 }
02347         }
02348 }

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