r13316: Let the carnage begin....
[kai/samba.git] / source / smbd / open.c
index e6c749fab9cf48c58a2f4cabd72c81d702985437..4f28e291cd67caca2e4ae9eccdd62aef2db75830 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "includes.h"
 
+extern struct generic_mapping file_generic_mapping;
 extern struct current_user current_user;
 extern userdom_struct current_user_info;
 extern uint16 global_smbpid;
@@ -73,23 +74,6 @@ int fd_close(struct connection_struct *conn,
        return fd_close_posix(conn, fsp);
 }
 
-
-/****************************************************************************
- Check a filename for the pipe string.
-****************************************************************************/
-
-static void check_for_pipe(const char *fname)
-{
-       /* special case of pipe opens */
-       char s[10];
-       StrnCpy(s,fname,sizeof(s)-1);
-       strlower_m(s);
-       if (strstr(s,"pipe/")) {
-               DEBUG(3,("Rejecting named pipe open for %s\n",fname));
-               set_saved_error_triple(ERRSRV, ERRaccess, NT_STATUS_ACCESS_DENIED);
-       }
-}
-
 /****************************************************************************
  Change the ownership of a file to that of the parent directory.
  Do this by fd if possible.
@@ -226,7 +210,6 @@ static BOOL open_file(files_struct *fsp,
                /* It's a read-only share - fail if we wanted to write. */
                if(accmode != O_RDONLY) {
                        DEBUG(3,("Permission denied opening %s\n",fname));
-                       check_for_pipe(fname);
                        return False;
                } else if(flags & O_CREAT) {
                        /* We don't want to write - but we must make sure that
@@ -292,7 +275,6 @@ static BOOL open_file(files_struct *fsp,
                        DEBUG(3,("Error opening file %s (%s) (local_flags=%d) "
                                 "(flags=%d)\n",
                                 fname,strerror(errno),local_flags,flags));
-                       check_for_pipe(fname);
                        return False;
                }
 
@@ -683,12 +665,17 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp)
 
        if (delay_it) {
                BOOL ret;
+               char msg[MSG_SMB_SHARE_MODE_ENTRY_SIZE];
+
                DEBUG(10, ("Sending break request to PID %s\n",
                           procid_str_static(&exclusive->pid)));
                exclusive->op_mid = get_current_mid();
+
+               share_mode_entry_to_message(msg, exclusive);
+
                become_root();
                ret = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST,
-                                      exclusive, sizeof(*exclusive), True);
+                                      msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
                unbecome_root();
                if (!ret) {
                        DEBUG(3, ("Could not send oplock break message\n"));
@@ -1032,15 +1019,6 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func
 
 }
 
-/* Map generic permissions to file object specific permissions */
-                                                                                                               
-struct generic_mapping file_generic_mapping = {
-       FILE_GENERIC_READ,
-       FILE_GENERIC_WRITE,
-       FILE_GENERIC_EXECUTE,
-       FILE_GENERIC_ALL
-};
-
 /****************************************************************************
  Open a file with a share mode.
 ****************************************************************************/
@@ -1655,32 +1633,29 @@ files_struct *open_file_ntcreate(connection_struct *conn,
        }
        set_share_mode(lck, fsp, 0, fsp->oplock_type);
 
-       if (create_options & FILE_DELETE_ON_CLOSE) {
-               uint32 dosattr= existing_dos_attributes;
-               NTSTATUS result;
-
-               if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED ||
+       if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED ||
                                info == FILE_WAS_SUPERSEDED) {
-                       dosattr = new_dos_attributes;
-               }
 
-               result = can_set_delete_on_close(fsp, True, dosattr);
-
-               if (!NT_STATUS_IS_OK(result)) {
-                       /* Remember to delete the mode we just added. */
-                       del_share_mode(lck, fsp);
-                       talloc_free(lck);
-                       fd_close(conn,fsp);
-                       file_free(fsp);
-                       set_saved_ntstatus(result);
-                       return NULL;
+               /* Handle strange delete on close create semantics. */
+               if (create_options & FILE_DELETE_ON_CLOSE) {
+                       NTSTATUS result = can_set_delete_on_close(fsp, True, new_dos_attributes);
+
+                       if (!NT_STATUS_IS_OK(result)) {
+                               /* Remember to delete the mode we just added. */
+                               del_share_mode(lck, fsp);
+                               talloc_free(lck);
+                               fd_close(conn,fsp);
+                               file_free(fsp);
+                               set_saved_ntstatus(result);
+                               return NULL;
+                       }
+                       /* Note that here we set the *inital* delete on close flag,
+                          not the regular one. */
+                       set_delete_on_close_token(lck, &current_user.ut);
+                       lck->initial_delete_on_close = True;
+                       lck->modified = True;
                }
-               lck->delete_on_close = True;
-               lck->modified = True;
-       }
        
-       if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED ||
-                               info == FILE_WAS_SUPERSEDED) {
                /* Files should be initially set as archive */
                if (lp_map_archive(SNUM(conn)) ||
                    lp_store_dos_attributes(SNUM(conn))) {
@@ -1971,6 +1946,8 @@ files_struct *open_directory(connection_struct *conn,
 
        set_share_mode(lck, fsp, 0, NO_OPLOCK);
 
+       /* For directories the delete on close bit at open time seems
+          always to be honored on close... See test 19 in Samba4 BASE-DELETE. */
        if (create_options & FILE_DELETE_ON_CLOSE) {
                status = can_set_delete_on_close(fsp, True, 0);
                if (!NT_STATUS_IS_OK(status)) {
@@ -1980,7 +1957,8 @@ files_struct *open_directory(connection_struct *conn,
                        return NULL;
                }
 
-               lck->delete_on_close = True;
+               set_delete_on_close_token(lck, &current_user.ut);
+               lck->initial_delete_on_close = True;
                lck->modified = True;
        }
 
@@ -2055,25 +2033,30 @@ files_struct *open_file_stat(connection_struct *conn, char *fname,
 void msg_file_was_renamed(int msg_type, struct process_id src, void *buf, size_t len)
 {
        files_struct *fsp;
-       struct file_renamed_message *frm = (struct file_renamed_message *)buf;
+       char *frm = (char *)buf;
+       SMB_DEV_T dev;
+       SMB_INO_T inode;
        const char *sharepath;
        const char *newname;
        size_t sp_len;
 
-       if (buf == NULL || len < sizeof(*frm)) {
+       if (buf == NULL || len < MSG_FILE_RENAMED_MIN_SIZE + 2) {
                 DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", (int)len));
                 return;
         }
 
-       sharepath = &frm->names[0];
+       /* Unpack the message. */
+       dev = DEV_T_VAL(frm,0);
+       inode = INO_T_VAL(frm,8);
+       sharepath = &frm[16];
        newname = sharepath + strlen(sharepath) + 1;
        sp_len = strlen(sharepath);
 
        DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, "
                "dev %x, inode  %.0f\n",
-               sharepath, newname, (unsigned int)frm->dev, (double)frm->inode ));
+               sharepath, newname, (unsigned int)dev, (double)inode ));
 
-       for(fsp = file_find_di_first(frm->dev, frm->inode); fsp; fsp = file_find_di_next(fsp)) {
+       for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
                if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) {
                        DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n",
                                fsp->fnum, fsp->fsp_name, newname ));