diff options
-rw-r--r-- | source3/include/smb.h | 1 | ||||
-rw-r--r-- | source3/smbd/blocking.c | 4 | ||||
-rw-r--r-- | source3/smbd/close.c | 16 | ||||
-rw-r--r-- | source3/smbd/negprot.c | 8 | ||||
-rw-r--r-- | source3/smbd/open.c | 1 | ||||
-rw-r--r-- | source3/smbd/reply.c | 20 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 90 |
7 files changed, 105 insertions, 35 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h index 3e68f1c4ca..5a90f08258 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -576,6 +576,7 @@ typedef struct files_struct BOOL granted_oplock; BOOL sent_oplock_break; BOOL is_directory; + BOOL delete_on_close; char *fsp_name; } files_struct; diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 051e276ca7..27a5183952 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -222,7 +222,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, int eclass, int32 ec offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); } -#endif +#endif /* LARGE_SMB_OFF_T */ do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } @@ -412,7 +412,7 @@ static BOOL process_lockingX(blocking_lock_record *blr) offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(blr->lock_num))) << 32) | ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(blr->lock_num))); } -#endif +#endif /* LARGE_SMB_OFF_T */ errno = 0; if(!do_lock(fsp,conn,count,offset, ((locktype & 1) ? F_RDLCK : F_WRLCK), &eclass, &ecode)) diff --git a/source3/smbd/close.c b/source3/smbd/close.c index e9606cdfbe..981c0d77bb 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -102,6 +102,7 @@ void close_file(files_struct *fsp, BOOL normal_close) SMB_DEV_T dev = fsp->fd_ptr->dev; SMB_INO_T inode = fsp->fd_ptr->inode; int token; + BOOL last_reference = False; connection_struct *conn = fsp->conn; remove_pending_lock_requests_by_fid(fsp); @@ -118,7 +119,9 @@ void close_file(files_struct *fsp, BOOL normal_close) } if(fd_attempt_close(fsp->fd_ptr) == 0) - fsp->fd_ptr = NULL; + last_reference = True; + + fsp->fd_ptr = NULL; if (lp_share_modes(SNUM(conn))) unlock_share_entry(conn, dev, inode, token); @@ -132,6 +135,17 @@ void close_file(files_struct *fsp, BOOL normal_close) check_magic(fsp,conn); } + /* + * NT can set delete_on_close of the last open + * reference to a file. + */ + + if (normal_close && last_reference && fsp->delete_on_close) { + if(dos_unlink(fsp->fsp_name) != 0) + DEBUG(0,("close_file: file %s. Delete on close was set and unlink failed \ +with error %s\n", fsp->fsp_name, strerror(errno) )); + } + if(fsp->granted_oplock == True) global_oplocks_open--; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 6a9cc9fb9b..e9dd4614c4 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -157,11 +157,15 @@ static int reply_nt1(char *outbuf) { /* dual names + lock_and_read + nt SMBs + remote API calls */ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ| - (lp_nt_smb_support() ? CAP_NT_SMBS | CAP_RPC_REMOTE_APIS : 0); + (lp_nt_smb_support() ? CAP_NT_SMBS | CAP_RPC_REMOTE_APIS : 0) | +#ifdef LARGE_SMB_OFF_T + (sizeof(SMB_OFF_T) == 8 ? CAP_LARGE_FILES : 0); +#else + 0; +#endif /* other valid capabilities which we may support at some time... - CAP_LARGE_FILES| CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS; */ diff --git a/source3/smbd/open.c b/source3/smbd/open.c index bdd4816aa7..42b0fba425 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -507,6 +507,7 @@ static void open_file(files_struct *fsp,connection_struct *conn, fsp->granted_oplock = False; fsp->sent_oplock_break = False; fsp->is_directory = False; + fsp->delete_on_close = False; fsp->conn = conn; /* * Note that the file name here is the *untranslated* name diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 8ec2715d0d..e956ab6cd9 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -2006,14 +2006,14 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt set_message(outbuf,12,0,True); data = smb_buf(outbuf); -#ifdef LARGE_SMB_INO_T +#ifdef LARGE_SMB_OFF_T if(SVAL(inbuf,smb_wct) == 12) { /* * This is a large offset (64 bit) read. */ startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32); } -#endif /* LARGE_SMB_INO_T */ +#endif /* LARGE_SMB_OFF_T */ if (is_locked(fsp,conn,smb_maxcnt,startpos, F_RDLCK)) return(ERROR(ERRDOS,ERRlock)); @@ -2264,14 +2264,14 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng data = smb_base(inbuf) + smb_doff; -#ifdef LLARGE_SMB_INO_T +#ifdef LLARGE_SMB_OFF_T if(SVAL(inbuf,smb_wct) == 14) { /* * This is a large offset (64 bit) write. */ startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32); } -#endif /* LARGE_SMB_INO_T */ +#endif /* LARGE_SMB_OFF_T */ if (is_locked(fsp,conn,numtowrite,startpos, F_WRLCK)) return(ERROR(ERRDOS,ERRlock)); @@ -2408,8 +2408,8 @@ int reply_close(connection_struct *conn, * We can only use CHECK_FSP if we know it's not a directory. */ - if(!(fsp && fsp->open && fsp->is_directory)) - CHECK_FSP(fsp,conn); + if(!fsp || !fsp->open || (fsp->conn != conn)) + return(ERROR(ERRDOS,ERRbadfid)); if(HAS_CACHED_ERROR(fsp)) { eclass = fsp->wbmpx_ptr->wr_errclass; @@ -3631,7 +3631,7 @@ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); } -#endif +#endif /* LARGE_SMB_OFF_T */ DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for file %s\n", (double)offset, (double)count, fsp->fsp_name )); @@ -3661,8 +3661,8 @@ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); } -#endif - +#endif /* LARGE_SMB_OFF_T */ + DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for file %s\n", (double)offset, (double)count, fsp->fsp_name )); @@ -3696,7 +3696,7 @@ dev = %x, inode = %.0f\n", fsp->fnum, (unsigned int)dev, (double)inode)); offset = (((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(i))) << 32) | ((SMB_OFF_T) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(i))); } -#endif +#endif /* LARGE_SMB_OFF_T */ do_unlock(fsp,conn,count,offset,&dummy1,&dummy2); } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 709b8daecd..87d1ea27d0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -415,8 +415,8 @@ static int get_lanman2_dir_entry(connection_struct *conn, { case 1: if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; + SIVAL(p,0,reskey); + p += 4; } put_dos_date2(p,l1_fdateCreation,cdate); put_dos_date2(p,l1_fdateLastAccess,adate); @@ -433,8 +433,8 @@ static int get_lanman2_dir_entry(connection_struct *conn, case 2: /* info_level 2 */ if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; + SIVAL(p,0,reskey); + p += 4; } put_dos_date2(p,l2_fdateCreation,cdate); put_dos_date2(p,l2_fdateLastAccess,adate); @@ -466,8 +466,8 @@ static int get_lanman2_dir_entry(connection_struct *conn, case 4: if(requires_resume_key) { - SIVAL(p,0,reskey); - p += 4; + SIVAL(p,0,reskey); + p += 4; } SIVAL(p,0,33+strlen(fname)+1); put_dos_date2(p,4,cdate); @@ -492,17 +492,22 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SIVAL(p,0,size); p += 8; - SIVAL(p,0,size); p += 8; + SIVAL(p,0,size); + SIVAL(p,8,size); +#ifdef LARGE_SMB_OFF_T + SIVAL(p,4,size >> 32); + SIVAL(p,12,size >> 32); +#endif /* LARGE_SMB_OFF_T */ + p += 16; SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; SIVAL(p,0,0); p += 4; if (!was_8_3) { - pstrcpy(p+2,fname); - if (!name_map_mangle(p+2,True,SNUM(conn))) - (p+2)[12] = 0; + pstrcpy(p+2,fname); + if (!name_map_mangle(p+2,True,SNUM(conn))) + (p+2)[12] = 0; } else - *(p+2) = 0; + *(p+2) = 0; strupper(p+2); SSVAL(p,0,strlen(p+2)); p += 2 + 24; @@ -520,8 +525,13 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SIVAL(p,0,size); p += 8; - SIVAL(p,0,size); p += 8; + SIVAL(p,0,size); + SIVAL(p,8,size); +#ifdef LARGE_SMB_OFF_T + SIVAL(p,4,size >> 32); + SIVAL(p,12,size >> 32); +#endif /* LARGE_SMB_OFF_T */ + p += 16; SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; pstrcpy(p,fname); @@ -538,8 +548,13 @@ static int get_lanman2_dir_entry(connection_struct *conn, put_long_date(p,adate); p += 8; put_long_date(p,mdate); p += 8; put_long_date(p,mdate); p += 8; - SIVAL(p,0,size); p += 8; - SIVAL(p,0,size); p += 8; + SIVAL(p,0,size); + SIVAL(p,8,size); +#ifdef LARGE_SMB_OFF_T + SIVAL(p,4,size >> 32); + SIVAL(p,12,size >> 32); +#endif /* LARGE_SMB_OFF_T */ + p += 16; SIVAL(p,0,nt_extmode); p += 4; SIVAL(p,0,strlen(fname)); p += 4; SIVAL(p,0,0); p += 4; @@ -1055,6 +1070,7 @@ resume_key = %d resume name = %s continue=%d level = %d\n", /**************************************************************************** reply to a TRANS2_QFSINFO (query filesystem info) ****************************************************************************/ + static int call_trans2qfsinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize, @@ -1329,6 +1345,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, data_size = 22; SIVAL(pdata,0,size); SIVAL(pdata,8,size); +#ifdef LARGE_SMB_OFF_T + SIVAL(pdata,4,size>>32); + SIVAL(pdata,12,size>>32); +#endif /* LARGE_SMB_OFF_T */ SIVAL(pdata,16,sbuf.st_nlink); CVAL(pdata,20) = 0; CVAL(pdata,21) = (mode&aDIR)?1:0; @@ -1367,6 +1387,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, case SMB_QUERY_FILE_END_OF_FILEINFO: data_size = 8; SIVAL(pdata,0,size); +#ifdef LARGE_SMB_OFF_T + SIVAL(pdata,4,size >> 32); +#endif /* LARGE_SMB_OFF_T */ break; case SMB_QUERY_FILE_ALL_INFO: @@ -1378,6 +1401,10 @@ static int call_trans2qfilepathinfo(connection_struct *conn, pdata += 40; SIVAL(pdata,0,size); SIVAL(pdata,8,size); +#ifdef LARGE_SMB_OFF_T + SIVAL(pdata,4,size >> 32); + SIVAL(pdata,12,size >> 32); +#endif /* LARGE_SMB_OFF_T */ SIVAL(pdata,16,sbuf.st_nlink); CVAL(pdata,20) = 0; CVAL(pdata,21) = (mode&aDIR)?1:0; @@ -1385,9 +1412,9 @@ static int call_trans2qfilepathinfo(connection_struct *conn, pdata += 8; /* index number */ pdata += 4; /* EA info */ if (mode & aRONLY) - SIVAL(pdata,0,0xA9); + SIVAL(pdata,0,0xA9); else - SIVAL(pdata,0,0xd01BF); + SIVAL(pdata,0,0xd01BF); pdata += 4; SIVAL(pdata,0,pos); /* current offset */ pdata += 8; @@ -1566,16 +1593,39 @@ static int call_trans2setfilepathinfo(connection_struct *conn, case SMB_SET_FILE_END_OF_FILE_INFO: { + size = IVAL(pdata,0); +#ifdef LARGE_SMB_OFF_T + size |= (((SMB_OFF_T)IVAL(pdata,4)) << 32); +#else /* LARGE_SMB_OFF_T */ if (IVAL(pdata,4) != 0) /* more than 32 bits? */ return(ERROR(ERRDOS,ERRunknownlevel)); - size = IVAL(pdata,0); +#endif /* LARGE_SMB_OFF_T */ break; } case SMB_SET_FILE_ALLOCATION_INFO: break; /* We don't need to do anything for this call. */ - case SMB_SET_FILE_DISPOSITION_INFO: /* not supported yet */ + case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */ + { + if (tran_call == TRANSACT2_SETFILEINFO) { + files_struct *fsp = file_fsp(params,0); + if(fsp->is_directory) + return(ERROR(ERRDOS,ERRnoaccess)); + /* + * TODO - check here is this means set + * this flag bit on all open files that + * reference this particular dev/inode pair. + * If so we'll need to search the open + * file entries here and set this flag on + * all of them that match. JRA. + */ + fsp->delete_on_close = CVAL(pdata,0); + } else + return(ERROR(ERRDOS,ERRunknownlevel)); + break; + } + default: { return(ERROR(ERRDOS,ERRunknownlevel)); |