2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
28 /* look in server.c for some explanation of these variables */
32 extern char magic_char
;
33 extern BOOL case_sensitive
;
34 extern BOOL case_preserve
;
35 extern BOOL short_case_preserve
;
36 extern int global_oplock_break
;
37 unsigned int smb_echo_count
= 0;
39 extern BOOL global_encrypted_passwords_negotiated
;
41 /****************************************************************************
42 Ensure we check the path in *exactly* the same way as W2K.
43 ****************************************************************************/
45 NTSTATUS
check_path_syntax(const char *name
)
47 while (*name
== '\\' || *name
== '/')
49 if (name
[0] == '.' && name
[1] == '\0')
50 return NT_STATUS_OBJECT_NAME_INVALID
;
51 else if (name
[0] == '.' && name
[1] == '.' &&
52 (name
[2] == '\\' || name
[2] == '/' || name
[2] == '\0'))
53 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD
;
57 /****************************************************************************
58 Pull a string and check the path - provide for error return.
59 ****************************************************************************/
61 size_t srvstr_get_path(char *inbuf
, char *dest
, const char *src
, size_t dest_len
, int flags
, NTSTATUS
*err
)
63 size_t ret
= srvstr_pull_buf( inbuf
, dest
, src
, dest_len
, flags
);
64 *err
= check_path_syntax(dest
);
68 /****************************************************************************
69 Reply to a special message.
70 ****************************************************************************/
72 int reply_special(char *inbuf
,char *outbuf
)
75 int msg_type
= CVAL(inbuf
,0);
76 int msg_flags
= CVAL(inbuf
,1);
80 static BOOL already_got_session
= False
;
84 memset(outbuf
,'\0',smb_size
);
89 case 0x81: /* session request */
91 if (already_got_session
) {
92 exit_server("multiple session request not permitted");
97 if (name_len(inbuf
+4) > 50 ||
98 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
99 DEBUG(0,("Invalid name length in session request\n"));
102 name_extract(inbuf
,4,name1
);
103 name_type
= name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
104 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
107 set_local_machine_name(name1
, True
);
108 set_remote_machine_name(name2
, True
);
110 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
111 get_local_machine_name(), get_remote_machine_name(),
114 if (name_type
== 'R') {
115 /* We are being asked for a pathworks session ---
117 SCVAL(outbuf
, 0,0x83);
121 /* only add the client's machine name to the list
122 of possibly valid usernames if we are operating
123 in share mode security */
124 if (lp_security() == SEC_SHARE
) {
125 add_session_user(get_remote_machine_name());
128 reload_services(True
);
131 claim_connection(NULL
,"",0,True
,FLAG_MSG_GENERAL
|FLAG_MSG_SMBD
);
133 already_got_session
= True
;
136 case 0x89: /* session keepalive request
137 (some old clients produce this?) */
138 SCVAL(outbuf
,0,SMBkeepalive
);
142 case 0x82: /* positive session response */
143 case 0x83: /* negative session response */
144 case 0x84: /* retarget session response */
145 DEBUG(0,("Unexpected session response\n"));
148 case SMBkeepalive
: /* session keepalive */
153 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
154 msg_type
, msg_flags
));
159 /****************************************************************************
161 ****************************************************************************/
163 int reply_tcon(connection_struct
*conn
,
164 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
171 uint16 vuid
= SVAL(inbuf
,smb_uid
);
175 DATA_BLOB password_blob
;
177 START_PROFILE(SMBtcon
);
179 *service_buf
= *password
= *dev
= 0;
181 p
= smb_buf(inbuf
)+1;
182 p
+= srvstr_pull_buf(inbuf
, service_buf
, p
, sizeof(service_buf
), STR_TERMINATE
) + 1;
183 pwlen
= srvstr_pull_buf(inbuf
, password
, p
, sizeof(password
), STR_TERMINATE
) + 1;
185 p
+= srvstr_pull_buf(inbuf
, dev
, p
, sizeof(dev
), STR_TERMINATE
) + 1;
187 p
= strrchr_m(service_buf
,'\\');
191 service
= service_buf
;
194 password_blob
= data_blob(password
, pwlen
+1);
196 conn
= make_connection(service
,password_blob
,dev
,vuid
,&nt_status
);
198 data_blob_clear_free(&password_blob
);
201 END_PROFILE(SMBtcon
);
202 return ERROR_NT(nt_status
);
205 outsize
= set_message(outbuf
,2,0,True
);
206 SSVAL(outbuf
,smb_vwv0
,max_recv
);
207 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
208 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
210 DEBUG(3,("tcon service=%s cnum=%d\n",
211 service
, conn
->cnum
));
213 END_PROFILE(SMBtcon
);
217 /****************************************************************************
218 Reply to a tcon and X.
219 ****************************************************************************/
221 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
226 /* what the cleint thinks the device is */
227 fstring client_devicetype
;
228 /* what the server tells the client the share represents */
229 const char *server_devicetype
;
231 uint16 vuid
= SVAL(inbuf
,smb_uid
);
232 int passlen
= SVAL(inbuf
,smb_vwv3
);
235 extern BOOL global_encrypted_passwords_negotiated
;
237 START_PROFILE(SMBtconX
);
239 *service
= *client_devicetype
= 0;
241 /* we might have to close an old one */
242 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
243 close_cnum(conn
,vuid
);
246 if (passlen
> MAX_PASS_LEN
) {
247 return ERROR_DOS(ERRDOS
,ERRbuftoosmall
);
250 if (global_encrypted_passwords_negotiated
) {
251 password
= data_blob(smb_buf(inbuf
),passlen
);
253 password
= data_blob(smb_buf(inbuf
),passlen
+1);
254 /* Ensure correct termination */
255 password
.data
[passlen
]=0;
258 p
= smb_buf(inbuf
) + passlen
;
259 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
262 * the service name can be either: \\server\share
263 * or share directly like on the DELL PowerVault 705
266 q
= strchr_m(path
+2,'\\');
268 END_PROFILE(SMBtconX
);
269 return(ERROR_DOS(ERRDOS
,ERRnosuchshare
));
271 fstrcpy(service
,q
+1);
274 fstrcpy(service
,path
);
276 p
+= srvstr_pull(inbuf
, client_devicetype
, p
, sizeof(client_devicetype
), 6, STR_ASCII
);
278 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype
, service
));
280 conn
= make_connection(service
,password
,client_devicetype
,vuid
,&nt_status
);
282 data_blob_clear_free(&password
);
285 END_PROFILE(SMBtconX
);
286 return ERROR_NT(nt_status
);
290 server_devicetype
= "IPC";
291 else if ( IS_PRINT(conn
) )
292 server_devicetype
= "LPT1:";
294 server_devicetype
= "A:";
296 if (Protocol
< PROTOCOL_NT1
) {
297 set_message(outbuf
,2,0,True
);
299 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
300 STR_TERMINATE
|STR_ASCII
);
301 set_message_end(outbuf
,p
);
303 /* NT sets the fstype of IPC$ to the null string */
304 const char *fstype
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
306 set_message(outbuf
,3,0,True
);
309 p
+= srvstr_push(outbuf
, p
, server_devicetype
, -1,
310 STR_TERMINATE
|STR_ASCII
);
311 p
+= srvstr_push(outbuf
, p
, fstype
, -1,
314 set_message_end(outbuf
,p
);
316 /* what does setting this bit do? It is set by NT4 and
317 may affect the ability to autorun mounted cdroms */
318 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
319 (lp_csc_policy(SNUM(conn
)) << 2));
321 init_dfsroot(conn
, inbuf
, outbuf
);
325 DEBUG(3,("tconX service=%s \n",
328 /* set the incoming and outgoing tid to the just created one */
329 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
330 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
332 END_PROFILE(SMBtconX
);
333 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
336 /****************************************************************************
337 Reply to an unknown type.
338 ****************************************************************************/
340 int reply_unknown(char *inbuf
,char *outbuf
)
343 type
= CVAL(inbuf
,smb_com
);
345 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
346 smb_fn_name(type
), type
, type
));
348 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
351 /****************************************************************************
353 ****************************************************************************/
355 int reply_ioctl(connection_struct
*conn
,
356 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
358 uint16 device
= SVAL(inbuf
,smb_vwv1
);
359 uint16 function
= SVAL(inbuf
,smb_vwv2
);
360 uint32 ioctl_code
= (device
<< 16) + function
;
361 int replysize
, outsize
;
363 START_PROFILE(SMBioctl
);
365 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
367 switch (ioctl_code
) {
368 case IOCTL_QUERY_JOB_INFO
:
372 END_PROFILE(SMBioctl
);
373 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
376 outsize
= set_message(outbuf
,8,replysize
+1,True
);
377 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
378 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
379 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
380 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
382 switch (ioctl_code
) {
383 case IOCTL_QUERY_JOB_INFO
:
385 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
387 END_PROFILE(SMBioctl
);
388 return(UNIXERROR(ERRDOS
,ERRbadfid
));
390 SSVAL(p
,0,fsp
->rap_print_jobid
); /* Job number */
391 srvstr_push(outbuf
, p
+2, global_myname(), 15, STR_TERMINATE
|STR_ASCII
);
392 srvstr_push(outbuf
, p
+18, lp_servicename(SNUM(conn
)), 13, STR_TERMINATE
|STR_ASCII
);
397 END_PROFILE(SMBioctl
);
401 /****************************************************************************
403 ****************************************************************************/
405 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
411 BOOL bad_path
= False
;
412 SMB_STRUCT_STAT sbuf
;
415 START_PROFILE(SMBchkpth
);
417 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), STR_TERMINATE
, &status
);
418 if (!NT_STATUS_IS_OK(status
)) {
419 END_PROFILE(SMBchkpth
);
420 return ERROR_NT(status
);
423 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
425 unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
427 mode
= SVAL(inbuf
,smb_vwv0
);
429 if (check_name(name
,conn
)) {
430 if (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,name
,&sbuf
) == 0)
431 if (!(ok
= S_ISDIR(sbuf
.st_mode
))) {
432 END_PROFILE(SMBchkpth
);
433 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY
,ERRDOS
,ERRbadpath
);
438 /* We special case this - as when a Windows machine
439 is parsing a path is steps through the components
440 one at a time - if a component fails it expects
441 ERRbadpath, not ERRbadfile.
443 if(errno
== ENOENT
) {
445 * Windows returns different error codes if
446 * the parent directory is valid but not the
447 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
448 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
449 * if the path is invalid.
452 END_PROFILE(SMBchkpth
);
453 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
455 END_PROFILE(SMBchkpth
);
456 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND
);
458 } else if (errno
== ENOTDIR
) {
459 END_PROFILE(SMBchkpth
);
460 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY
);
463 END_PROFILE(SMBchkpth
);
464 return(UNIXERROR(ERRDOS
,ERRbadpath
));
467 outsize
= set_message(outbuf
,0,0,True
);
469 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
471 END_PROFILE(SMBchkpth
);
475 /****************************************************************************
477 ****************************************************************************/
479 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
483 SMB_STRUCT_STAT sbuf
;
488 BOOL bad_path
= False
;
492 START_PROFILE(SMBgetatr
);
494 p
= smb_buf(inbuf
) + 1;
495 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), STR_TERMINATE
,&status
);
496 if (!NT_STATUS_IS_OK(status
)) {
497 END_PROFILE(SMBgetatr
);
498 return ERROR_NT(status
);
501 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
503 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
504 under WfWg - weird! */
506 mode
= aHIDDEN
| aDIR
;
507 if (!CAN_WRITE(conn
))
513 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
514 if (check_name(fname
,conn
)) {
515 if (VALID_STAT(sbuf
) || SMB_VFS_STAT(conn
,fname
,&sbuf
) == 0) {
516 mode
= dos_mode(conn
,fname
,&sbuf
);
518 mtime
= sbuf
.st_mtime
;
523 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
529 END_PROFILE(SMBgetatr
);
530 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
,ERRbadfile
);
533 outsize
= set_message(outbuf
,10,0,True
);
535 SSVAL(outbuf
,smb_vwv0
,mode
);
536 if(lp_dos_filetime_resolution(SNUM(conn
)) )
537 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
539 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
540 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
542 if (Protocol
>= PROTOCOL_NT1
)
543 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
545 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
547 END_PROFILE(SMBgetatr
);
551 /****************************************************************************
553 ****************************************************************************/
555 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
562 SMB_STRUCT_STAT sbuf
;
563 BOOL bad_path
= False
;
567 START_PROFILE(SMBsetatr
);
569 p
= smb_buf(inbuf
) + 1;
570 p
+= srvstr_get_path(inbuf
, fname
, p
, sizeof(fname
), STR_TERMINATE
,&status
);
571 if (!NT_STATUS_IS_OK(status
)) {
572 END_PROFILE(SMBsetatr
);
573 return ERROR_NT(status
);
576 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
578 mode
= SVAL(inbuf
,smb_vwv0
);
579 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
581 if (mode
!= FILE_ATTRIBUTE_NORMAL
) {
582 if (VALID_STAT_OF_DIR(sbuf
))
587 if (check_name(fname
,conn
))
588 ok
= (file_chmod(conn
,fname
,mode
,NULL
) == 0);
594 ok
= set_filetime(conn
,fname
,mtime
);
597 END_PROFILE(SMBsetatr
);
598 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
601 outsize
= set_message(outbuf
,0,0,True
);
603 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
605 END_PROFILE(SMBsetatr
);
609 /****************************************************************************
611 ****************************************************************************/
613 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
616 SMB_BIG_UINT dfree
,dsize
,bsize
;
617 START_PROFILE(SMBdskattr
);
619 SMB_VFS_DISK_FREE(conn
,".",True
,&bsize
,&dfree
,&dsize
);
621 outsize
= set_message(outbuf
,5,0,True
);
623 if (Protocol
<= PROTOCOL_LANMAN2
) {
624 double total_space
, free_space
;
625 /* we need to scale this to a number that DOS6 can handle. We
626 use floating point so we can handle large drives on systems
627 that don't have 64 bit integers
629 we end up displaying a maximum of 2G to DOS systems
631 total_space
= dsize
* (double)bsize
;
632 free_space
= dfree
* (double)bsize
;
634 dsize
= (total_space
+63*512) / (64*512);
635 dfree
= (free_space
+63*512) / (64*512);
637 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
638 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
640 SSVAL(outbuf
,smb_vwv0
,dsize
);
641 SSVAL(outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
642 SSVAL(outbuf
,smb_vwv2
,512); /* and this must be 512 */
643 SSVAL(outbuf
,smb_vwv3
,dfree
);
645 SSVAL(outbuf
,smb_vwv0
,dsize
);
646 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
647 SSVAL(outbuf
,smb_vwv2
,512);
648 SSVAL(outbuf
,smb_vwv3
,dfree
);
651 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
653 END_PROFILE(SMBdskattr
);
657 /****************************************************************************
659 Can be called from SMBsearch, SMBffirst or SMBfunique.
660 ****************************************************************************/
662 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
673 BOOL finished
= False
;
682 BOOL check_descend
= False
;
683 BOOL expect_close
= False
;
684 BOOL can_open
= True
;
685 BOOL bad_path
= False
;
687 START_PROFILE(SMBsearch
);
689 *mask
= *directory
= *fname
= 0;
691 /* If we were called as SMBffirst then we must expect close. */
692 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
695 outsize
= set_message(outbuf
,1,3,True
);
696 maxentries
= SVAL(inbuf
,smb_vwv0
);
697 dirtype
= SVAL(inbuf
,smb_vwv1
);
698 p
= smb_buf(inbuf
) + 1;
699 p
+= srvstr_get_path(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
,&nt_status
);
700 if (!NT_STATUS_IS_OK(nt_status
)) {
701 END_PROFILE(SMBsearch
);
702 return ERROR_NT(nt_status
);
705 status_len
= SVAL(p
, 0);
708 /* dirtype &= ~aDIR; */
710 if (status_len
== 0) {
711 SMB_STRUCT_STAT sbuf
;
714 pstrcpy(directory
,path
);
716 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
719 if (!check_name(directory
,conn
))
722 p
= strrchr_m(dir2
,'/');
731 p
= strrchr_m(directory
,'/');
737 if (strlen(directory
) == 0)
738 pstrcpy(directory
,".");
739 memset((char *)status
,'\0',21);
740 SCVAL(status
,0,(dirtype
& 0x1F));
745 status_dirtype
= CVAL(status
,0) & 0x1F;
746 if (status_dirtype
!= (dirtype
& 0x1F))
747 dirtype
= status_dirtype
;
749 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
752 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
753 pstrcpy(mask
, dptr_wcard(dptr_num
));
757 p
= smb_buf(outbuf
) + 3;
760 if (status_len
== 0) {
761 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
));
764 END_PROFILE(SMBsearch
);
765 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnofids
);
767 END_PROFILE(SMBsearch
);
768 return ERROR_DOS(ERRDOS
,ERRnofids
);
770 dptr_set_wcard(dptr_num
, strdup(mask
));
771 dptr_set_attr(dptr_num
, dirtype
);
773 dirtype
= dptr_attr(dptr_num
);
776 DEBUG(4,("dptr_num is %d\n",dptr_num
));
779 if ((dirtype
&0x1F) == aVOLID
) {
781 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
782 dptr_fill(p
+12,dptr_num
);
783 if (dptr_zero(p
+12) && (status_len
==0))
787 p
+= DIR_STRUCT_SIZE
;
789 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
790 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
791 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
792 check_descend
= True
;
794 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++) {
795 finished
= !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
798 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
799 dptr_fill(p
+12,dptr_num
);
802 p
+= DIR_STRUCT_SIZE
;
811 /* If we were called as SMBffirst with smb_search_id == NULL
812 and no entries were found then return error and close dirptr
815 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0) {
816 if (Protocol
< PROTOCOL_NT1
) {
817 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
818 SSVAL(outbuf
,smb_err
,ERRnofiles
);
820 /* Also close the dptr - we know it's gone */
821 dptr_close(&dptr_num
);
822 } else if (numentries
== 0 || !ok
) {
823 if (Protocol
< PROTOCOL_NT1
) {
824 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
825 SSVAL(outbuf
,smb_err
,ERRnofiles
);
827 dptr_close(&dptr_num
);
830 /* If we were called as SMBfunique, then we can close the dirptr now ! */
831 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
832 dptr_close(&dptr_num
);
834 SSVAL(outbuf
,smb_vwv0
,numentries
);
835 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
836 SCVAL(smb_buf(outbuf
),0,5);
837 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
839 if (Protocol
>= PROTOCOL_NT1
)
840 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
842 outsize
+= DIR_STRUCT_SIZE
*numentries
;
843 smb_setlen(outbuf
,outsize
- 4);
845 if ((! *directory
) && dptr_path(dptr_num
))
846 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
848 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
849 smb_fn_name(CVAL(inbuf
,smb_com
)),
850 mask
, directory
, dirtype
, numentries
, maxentries
) );
852 END_PROFILE(SMBsearch
);
856 /****************************************************************************
857 Reply to a fclose (stop directory search).
858 ****************************************************************************/
860 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
870 START_PROFILE(SMBfclose
);
872 outsize
= set_message(outbuf
,1,0,True
);
873 p
= smb_buf(inbuf
) + 1;
874 p
+= srvstr_get_path(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
,&err
);
875 if (!NT_STATUS_IS_OK(err
)) {
876 END_PROFILE(SMBfclose
);
877 return ERROR_NT(err
);
880 status_len
= SVAL(p
,0);
883 if (status_len
== 0) {
884 END_PROFILE(SMBfclose
);
885 return ERROR_DOS(ERRSRV
,ERRsrverror
);
890 if(dptr_fetch(status
+12,&dptr_num
)) {
891 /* Close the dptr - we know it's gone */
892 dptr_close(&dptr_num
);
895 SSVAL(outbuf
,smb_vwv0
,0);
897 DEBUG(3,("search close\n"));
899 END_PROFILE(SMBfclose
);
903 /****************************************************************************
905 ****************************************************************************/
907 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
917 SMB_STRUCT_STAT sbuf
;
918 BOOL bad_path
= False
;
920 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
922 START_PROFILE(SMBopen
);
924 share_mode
= SVAL(inbuf
,smb_vwv0
);
926 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), STR_TERMINATE
,&status
);
927 if (!NT_STATUS_IS_OK(status
)) {
928 END_PROFILE(SMBopen
);
929 return ERROR_NT(status
);
932 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
934 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
936 unixmode
= unix_mode(conn
,aARCH
,fname
);
938 fsp
= open_file_shared(conn
,fname
,&sbuf
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
939 unixmode
, oplock_request
,&rmode
,NULL
);
942 END_PROFILE(SMBopen
);
943 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
947 fmode
= dos_mode(conn
,fname
,&sbuf
);
948 mtime
= sbuf
.st_mtime
;
951 DEBUG(3,("attempt to open a directory %s\n",fname
));
952 close_file(fsp
,False
);
953 END_PROFILE(SMBopen
);
954 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
957 outsize
= set_message(outbuf
,7,0,True
);
958 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
959 SSVAL(outbuf
,smb_vwv1
,fmode
);
960 if(lp_dos_filetime_resolution(SNUM(conn
)) )
961 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
963 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
964 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
965 SSVAL(outbuf
,smb_vwv6
,rmode
);
967 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
968 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
970 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
971 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
972 END_PROFILE(SMBopen
);
976 /****************************************************************************
977 Reply to an open and X.
978 ****************************************************************************/
980 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
983 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
984 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
985 /* Breakout the oplock request bits so we can set the
986 reply bits separately. */
987 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
988 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
989 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
991 int open_flags
= SVAL(inbuf
,smb_vwv2
);
992 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
993 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
995 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
998 int fmode
=0,mtime
=0,rmode
=0;
999 SMB_STRUCT_STAT sbuf
;
1001 BOOL bad_path
= False
;
1004 START_PROFILE(SMBopenX
);
1006 /* If it's an IPC, pass off the pipe handler. */
1008 if (lp_nt_pipe_support()) {
1009 END_PROFILE(SMBopenX
);
1010 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
1012 END_PROFILE(SMBopenX
);
1013 return ERROR_DOS(ERRSRV
,ERRaccess
);
1017 /* XXXX we need to handle passed times, sattr and flags */
1018 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
), sizeof(fname
), STR_TERMINATE
,&status
);
1019 if (!NT_STATUS_IS_OK(status
)) {
1020 END_PROFILE(SMBopenX
);
1021 return ERROR_NT(status
);
1024 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1026 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1028 unixmode
= unix_mode(conn
,smb_attr
| aARCH
, fname
);
1030 fsp
= open_file_shared(conn
,fname
,&sbuf
,smb_mode
,smb_ofun
,unixmode
,
1031 oplock_request
, &rmode
,&smb_action
);
1034 END_PROFILE(SMBopenX
);
1035 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1038 size
= sbuf
.st_size
;
1039 fmode
= dos_mode(conn
,fname
,&sbuf
);
1040 mtime
= sbuf
.st_mtime
;
1042 close_file(fsp
,False
);
1043 END_PROFILE(SMBopenX
);
1044 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
1047 /* If the caller set the extended oplock request bit
1048 and we granted one (by whatever means) - set the
1049 correct bit for extended oplock reply.
1052 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1053 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1055 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1056 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
1058 /* If the caller set the core oplock request bit
1059 and we granted one (by whatever means) - set the
1060 correct bit for core oplock reply.
1063 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1064 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1066 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1067 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1069 set_message(outbuf
,15,0,True
);
1070 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1071 SSVAL(outbuf
,smb_vwv3
,fmode
);
1072 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1073 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1075 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1076 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1077 SSVAL(outbuf
,smb_vwv8
,rmode
);
1078 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1080 END_PROFILE(SMBopenX
);
1081 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1084 /****************************************************************************
1085 Reply to a SMBulogoffX.
1086 ****************************************************************************/
1088 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1090 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1091 user_struct
*vuser
= get_valid_user_struct(vuid
);
1092 START_PROFILE(SMBulogoffX
);
1095 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1097 /* in user level security we are supposed to close any files
1098 open by this user */
1099 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
))
1100 file_close_user(vuid
);
1102 invalidate_vuid(vuid
);
1104 set_message(outbuf
,2,0,True
);
1106 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1108 END_PROFILE(SMBulogoffX
);
1109 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1112 /****************************************************************************
1113 Reply to a mknew or a create.
1114 ****************************************************************************/
1116 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1124 BOOL bad_path
= False
;
1126 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1127 SMB_STRUCT_STAT sbuf
;
1129 START_PROFILE(SMBcreate
);
1131 com
= SVAL(inbuf
,smb_com
);
1133 createmode
= SVAL(inbuf
,smb_vwv0
);
1134 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
) + 1, sizeof(fname
), STR_TERMINATE
,&status
);
1135 if (!NT_STATUS_IS_OK(status
)) {
1136 END_PROFILE(SMBcreate
);
1137 return ERROR_NT(status
);
1140 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1142 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1144 if (createmode
& aVOLID
)
1145 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1147 unixmode
= unix_mode(conn
,createmode
,fname
);
1149 if(com
== SMBmknew
) {
1150 /* We should fail if file exists. */
1151 ofun
= FILE_CREATE_IF_NOT_EXIST
;
1153 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1154 ofun
= FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
;
1157 /* Open file in dos compatibility share mode. */
1158 fsp
= open_file_shared(conn
,fname
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1159 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1162 END_PROFILE(SMBcreate
);
1163 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1166 outsize
= set_message(outbuf
,1,0,True
);
1167 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1169 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1170 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1172 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1173 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1175 DEBUG( 2, ( "new file %s\n", fname
) );
1176 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1178 END_PROFILE(SMBcreate
);
1182 /****************************************************************************
1183 Reply to a create temporary file.
1184 ****************************************************************************/
1186 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1192 BOOL bad_path
= False
;
1194 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1196 SMB_STRUCT_STAT sbuf
;
1200 START_PROFILE(SMBctemp
);
1202 createmode
= SVAL(inbuf
,smb_vwv0
);
1203 srvstr_get_path(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), STR_TERMINATE
,&status
);
1204 if (!NT_STATUS_IS_OK(status
)) {
1205 END_PROFILE(SMBctemp
);
1206 return ERROR_NT(status
);
1208 pstrcat(fname
,"\\TMXXXXXX");
1210 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1212 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1214 unixmode
= unix_mode(conn
,createmode
,fname
);
1216 tmpfd
= smb_mkstemp(fname
);
1218 END_PROFILE(SMBctemp
);
1219 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1222 SMB_VFS_STAT(conn
,fname
,&sbuf
);
1224 /* Open file in dos compatibility share mode. */
1225 /* We should fail if file does not exist. */
1226 fsp
= open_file_shared(conn
,fname
,&sbuf
,
1227 SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1228 FILE_EXISTS_OPEN
|FILE_FAIL_IF_NOT_EXIST
,
1229 unixmode
, oplock_request
, NULL
, NULL
);
1231 /* close fd from smb_mkstemp() */
1235 END_PROFILE(SMBctemp
);
1236 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRnoaccess
);
1239 outsize
= set_message(outbuf
,1,0,True
);
1240 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1242 /* the returned filename is relative to the directory */
1243 s
= strrchr_m(fname
, '/');
1249 p
= smb_buf(outbuf
);
1250 SSVALS(p
, 0, -1); /* what is this? not in spec */
1251 SSVAL(p
, 2, strlen(s
));
1253 p
+= srvstr_push(outbuf
, p
, s
, -1, STR_ASCII
);
1254 outsize
= set_message_end(outbuf
, p
);
1256 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
)))
1257 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1259 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1260 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1262 DEBUG( 2, ( "created temp file %s\n", fname
) );
1263 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1264 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1266 END_PROFILE(SMBctemp
);
1270 /*******************************************************************
1271 Check if a user is allowed to rename a file.
1272 ********************************************************************/
1274 static NTSTATUS
can_rename(char *fname
,connection_struct
*conn
, SMB_STRUCT_STAT
*pst
)
1280 if (!CAN_WRITE(conn
))
1281 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1283 if (S_ISDIR(pst
->st_mode
))
1284 return NT_STATUS_OK
;
1286 /* We need a better way to return NT status codes from open... */
1290 fsp
= open_file_shared1(conn
, fname
, pst
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1291 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1294 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1295 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1296 ret
= NT_STATUS_SHARING_VIOLATION
;
1299 unix_ERR_ntstatus
= NT_STATUS_OK
;
1302 close_file(fsp
,False
);
1303 return NT_STATUS_OK
;
1306 /*******************************************************************
1307 Check if a user is allowed to delete a file.
1308 ********************************************************************/
1310 static NTSTATUS
can_delete(char *fname
,connection_struct
*conn
, int dirtype
)
1312 SMB_STRUCT_STAT sbuf
;
1318 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1321 if (!CAN_WRITE(conn
))
1322 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1324 if (SMB_VFS_LSTAT(conn
,fname
,&sbuf
) != 0)
1325 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1327 fmode
= dos_mode(conn
,fname
,&sbuf
);
1329 /* Can't delete a directory. */
1331 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1333 else if (dirtype
& aDIR
) /* Asked for a directory and it isn't. */
1334 return NT_STATUS_OBJECT_NAME_INVALID
;
1335 #endif /* JRATEST */
1337 if (!lp_delete_readonly(SNUM(conn
))) {
1339 return NT_STATUS_CANNOT_DELETE
;
1341 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1342 return NT_STATUS_NO_SUCH_FILE
;
1344 /* We need a better way to return NT status codes from open... */
1348 fsp
= open_file_shared1(conn
, fname
, &sbuf
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1349 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1352 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1353 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus
))
1354 ret
= unix_ERR_ntstatus
;
1355 else if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1356 ret
= NT_STATUS_SHARING_VIOLATION
;
1359 unix_ERR_ntstatus
= NT_STATUS_OK
;
1362 close_file(fsp
,False
);
1363 return NT_STATUS_OK
;
1366 /****************************************************************************
1367 The guts of the unlink command, split out so it may be called by the NT SMB
1369 ****************************************************************************/
1371 NTSTATUS
unlink_internals(connection_struct
*conn
, int dirtype
, char *name
)
1377 NTSTATUS error
= NT_STATUS_OK
;
1379 BOOL bad_path
= False
;
1381 SMB_STRUCT_STAT sbuf
;
1383 *directory
= *mask
= 0;
1385 /* We must check for wildcards in the name given
1386 * directly by the client - before any unmangling.
1387 * This prevents an unmangling of a UNIX name containing
1388 * a DOS wildcard like '*' or '?' from unmangling into
1389 * a wildcard delete which was not intended.
1390 * FIX for #226. JRA.
1393 has_wild
= ms_has_wild(name
);
1395 rc
= unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
1397 p
= strrchr_m(name
,'/');
1399 pstrcpy(directory
,".");
1403 pstrcpy(directory
,name
);
1408 * We should only check the mangled cache
1409 * here if unix_convert failed. This means
1410 * that the path in 'mask' doesn't exist
1411 * on the file system and so we need to look
1412 * for a possible mangle. This patch from
1413 * Tine Smukavec <valentin.smukavec@hermes.si>.
1416 if (!rc
&& mangle_is_mangled(mask
))
1417 mangle_check_cache( mask
);
1420 pstrcat(directory
,"/");
1421 pstrcat(directory
,mask
);
1422 error
= can_delete(directory
,conn
,dirtype
);
1423 if (!NT_STATUS_IS_OK(error
))
1426 if (SMB_VFS_UNLINK(conn
,directory
) == 0) {
1430 void *dirptr
= NULL
;
1433 if (check_name(directory
,conn
))
1434 dirptr
= OpenDir(conn
, directory
, True
);
1436 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1437 the pattern matches against the long name, otherwise the short name
1438 We don't implement this yet XXXX
1442 error
= NT_STATUS_NO_SUCH_FILE
;
1444 if (strequal(mask
,"????????.???"))
1447 while ((dname
= ReadDirName(dirptr
))) {
1449 pstrcpy(fname
,dname
);
1451 if(!mask_match(fname
, mask
, case_sensitive
))
1454 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1455 error
= can_delete(fname
,conn
,dirtype
);
1456 if (!NT_STATUS_IS_OK(error
))
1458 if (SMB_VFS_UNLINK(conn
,fname
) == 0)
1460 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
1466 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
1467 error
= map_nt_error_from_unix(errno
);
1473 /****************************************************************************
1475 ****************************************************************************/
1477 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
1484 START_PROFILE(SMBunlink
);
1486 dirtype
= SVAL(inbuf
,smb_vwv0
);
1488 srvstr_get_path(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), STR_TERMINATE
,&status
);
1489 if (!NT_STATUS_IS_OK(status
)) {
1490 END_PROFILE(SMBunlink
);
1491 return ERROR_NT(status
);
1494 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
1496 DEBUG(3,("reply_unlink : %s\n",name
));
1498 status
= unlink_internals(conn
, dirtype
, name
);
1499 if (!NT_STATUS_IS_OK(status
))
1500 return ERROR_NT(status
);
1503 * Win2k needs a changenotify request response before it will
1504 * update after a rename..
1506 process_pending_change_notify_queue((time_t)0);
1508 outsize
= set_message(outbuf
,0,0,True
);
1510 END_PROFILE(SMBunlink
);
1514 /****************************************************************************
1516 ****************************************************************************/
1518 void fail_readraw(void)
1521 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1523 exit_server(errstr
);
1526 /****************************************************************************
1527 Use sendfile in readbraw.
1528 ****************************************************************************/
1530 void send_file_readbraw(connection_struct
*conn
, files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
,
1531 ssize_t mincount
, char *outbuf
)
1535 #if defined(WITH_SENDFILE)
1537 * We can only use sendfile on a non-chained packet and on a file
1538 * that is exclusively oplocked. reply_readbraw has already checked the length.
1541 if ((nread
> 0) && (lp_write_cache_size(SNUM(conn
)) == 0) &&
1542 EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) && lp_use_sendfile(SNUM(conn
)) ) {
1545 _smb_setlen(outbuf
,nread
);
1546 header
.data
= outbuf
;
1550 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, nread
) == -1) {
1552 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1553 * return ENOSYS then pretend we just got a normal read.
1555 if (errno
== ENOSYS
)
1558 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1559 fsp
->fsp_name
, strerror(errno
) ));
1560 exit_server("send_file_readbraw sendfile failed");
1569 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
1570 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1579 _smb_setlen(outbuf
,ret
);
1580 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
1584 /****************************************************************************
1585 Reply to a readbraw (core+ protocol).
1586 ****************************************************************************/
1588 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
1590 extern struct current_user current_user
;
1591 ssize_t maxcount
,mincount
;
1594 char *header
= outbuf
;
1596 START_PROFILE(SMBreadbraw
);
1598 if (srv_is_signing_active()) {
1599 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1603 * Special check if an oplock break has been issued
1604 * and the readraw request croses on the wire, we must
1605 * return a zero length response here.
1608 if(global_oplock_break
) {
1609 _smb_setlen(header
,0);
1610 if (write_data(smbd_server_fd(),header
,4) != 4)
1612 DEBUG(5,("readbraw - oplock break finished\n"));
1613 END_PROFILE(SMBreadbraw
);
1617 fsp
= file_fsp(inbuf
,smb_vwv0
);
1619 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
1621 * fsp could be NULL here so use the value from the packet. JRA.
1623 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
1624 _smb_setlen(header
,0);
1625 if (write_data(smbd_server_fd(),header
,4) != 4)
1627 END_PROFILE(SMBreadbraw
);
1631 CHECK_FSP(fsp
,conn
);
1633 flush_write_cache(fsp
, READRAW_FLUSH
);
1635 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
1636 if(CVAL(inbuf
,smb_wct
) == 10) {
1638 * This is a large offset (64 bit) read.
1640 #ifdef LARGE_SMB_OFF_T
1642 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
1644 #else /* !LARGE_SMB_OFF_T */
1647 * Ensure we haven't been sent a >32 bit offset.
1650 if(IVAL(inbuf
,smb_vwv8
) != 0) {
1651 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1652 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
1653 _smb_setlen(header
,0);
1654 if (write_data(smbd_server_fd(),header
,4) != 4)
1656 END_PROFILE(SMBreadbraw
);
1660 #endif /* LARGE_SMB_OFF_T */
1663 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
1664 _smb_setlen(header
,0);
1665 if (write_data(smbd_server_fd(),header
,4) != 4)
1667 END_PROFILE(SMBreadbraw
);
1671 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
1672 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
1674 /* ensure we don't overrun the packet size */
1675 maxcount
= MIN(65535,maxcount
);
1677 if (!is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1678 SMB_OFF_T size
= fsp
->size
;
1679 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
1681 if (size
< sizeneeded
) {
1683 if (SMB_VFS_FSTAT(fsp
,fsp
->fd
,&st
) == 0)
1685 if (!fsp
->can_write
)
1689 if (startpos
>= size
)
1692 nread
= MIN(maxcount
,(size
- startpos
));
1695 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1696 if (nread
< mincount
)
1700 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp
->fnum
, (double)startpos
,
1701 (int)maxcount
, (int)mincount
, (int)nread
) );
1703 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
, outbuf
);
1705 DEBUG(5,("readbraw finished\n"));
1706 END_PROFILE(SMBreadbraw
);
1710 /****************************************************************************
1711 Reply to a lockread (core+ protocol).
1712 ****************************************************************************/
1714 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
1722 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1723 BOOL my_lock_ctx
= False
;
1724 START_PROFILE(SMBlockread
);
1726 CHECK_FSP(fsp
,conn
);
1729 release_level_2_oplocks_on_change(fsp
);
1731 numtoread
= SVAL(inbuf
,smb_vwv1
);
1732 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1734 outsize
= set_message(outbuf
,5,3,True
);
1735 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1736 data
= smb_buf(outbuf
) + 3;
1739 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1740 * protocol request that predates the read/write lock concept.
1741 * Thus instead of asking for a read lock here we need to ask
1742 * for a write lock. JRA.
1743 * Note that the requested lock size is unaffected by max_recv.
1746 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
),
1747 (SMB_BIG_UINT
)numtoread
, (SMB_BIG_UINT
)startpos
, WRITE_LOCK
, &my_lock_ctx
);
1749 if (NT_STATUS_V(status
)) {
1752 * We used to make lockread a blocking lock. It turns out
1753 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1757 if (lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
1759 * A blocking lock was requested. Package up
1760 * this smb into a queued request and push it
1761 * onto the blocking lock queue.
1763 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)startpos
,
1764 (SMB_BIG_UINT
)numtoread
)) {
1765 END_PROFILE(SMBlockread
);
1770 END_PROFILE(SMBlockread
);
1771 return ERROR_NT(status
);
1775 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1778 if (numtoread
> max_recv
) {
1779 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1780 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1781 (unsigned int)numtoread
, (unsigned int)max_recv
));
1782 numtoread
= MIN(numtoread
,max_recv
);
1784 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1787 END_PROFILE(SMBlockread
);
1788 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1792 SSVAL(outbuf
,smb_vwv0
,nread
);
1793 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1794 SSVAL(smb_buf(outbuf
),1,nread
);
1796 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1797 fsp
->fnum
, (int)numtoread
, (int)nread
));
1799 END_PROFILE(SMBlockread
);
1803 /****************************************************************************
1805 ****************************************************************************/
1807 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
1814 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1815 START_PROFILE(SMBread
);
1817 CHECK_FSP(fsp
,conn
);
1820 numtoread
= SVAL(inbuf
,smb_vwv1
);
1821 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
1823 outsize
= set_message(outbuf
,5,3,True
);
1824 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1826 * The requested read size cannot be greater than max_recv. JRA.
1828 if (numtoread
> max_recv
) {
1829 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1830 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1831 (unsigned int)numtoread
, (unsigned int)max_recv
));
1832 numtoread
= MIN(numtoread
,max_recv
);
1835 data
= smb_buf(outbuf
) + 3;
1837 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1838 END_PROFILE(SMBread
);
1839 return ERROR_DOS(ERRDOS
,ERRlock
);
1843 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1846 END_PROFILE(SMBread
);
1847 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1851 SSVAL(outbuf
,smb_vwv0
,nread
);
1852 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1853 SCVAL(smb_buf(outbuf
),0,1);
1854 SSVAL(smb_buf(outbuf
),1,nread
);
1856 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1857 fsp
->fnum
, (int)numtoread
, (int)nread
) );
1859 END_PROFILE(SMBread
);
1863 /****************************************************************************
1864 Reply to a read and X - possibly using sendfile.
1865 ****************************************************************************/
1867 int send_file_readX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,
1868 files_struct
*fsp
, SMB_OFF_T startpos
, size_t smb_maxcnt
)
1871 char *data
= smb_buf(outbuf
);
1873 #if defined(WITH_SENDFILE)
1875 * We can only use sendfile on a non-chained packet and on a file
1876 * that is exclusively oplocked.
1879 if ((CVAL(inbuf
,smb_vwv0
) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) &&
1880 lp_use_sendfile(SNUM(conn
)) && (lp_write_cache_size(SNUM(conn
)) == 0) ) {
1881 SMB_STRUCT_STAT sbuf
;
1884 if(SMB_VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1)
1885 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1887 if (startpos
> sbuf
.st_size
)
1890 if (smb_maxcnt
> (sbuf
.st_size
- startpos
))
1891 smb_maxcnt
= (sbuf
.st_size
- startpos
);
1893 if (smb_maxcnt
== 0)
1897 * Set up the packet header before send. We
1898 * assume here the sendfile will work (get the
1899 * correct amount of data).
1902 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
1903 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
1904 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
1905 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
1906 SCVAL(outbuf
,smb_vwv0
,0xFF);
1907 set_message(outbuf
,12,smb_maxcnt
,False
);
1908 header
.data
= outbuf
;
1909 header
.length
= data
- outbuf
;
1912 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, smb_maxcnt
) == -1) {
1914 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1915 * return ENOSYS then pretend we just got a normal read.
1917 if (errno
== ENOSYS
)
1920 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1921 fsp
->fsp_name
, strerror(errno
) ));
1922 exit_server("send_file_readX sendfile failed");
1925 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1926 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
1934 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
1937 END_PROFILE(SMBreadX
);
1938 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1941 SSVAL(outbuf
,smb_vwv2
,0xFFFF); /* Remaining - must be -1. */
1942 SSVAL(outbuf
,smb_vwv5
,nread
);
1943 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
1944 SSVAL(smb_buf(outbuf
),-2,nread
);
1946 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1947 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
1952 /****************************************************************************
1953 Reply to a read and X.
1954 ****************************************************************************/
1956 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1958 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
1959 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
1961 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
1963 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
1966 START_PROFILE(SMBreadX
);
1968 /* If it's an IPC, pass off the pipe handler. */
1970 END_PROFILE(SMBreadX
);
1971 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
1974 CHECK_FSP(fsp
,conn
);
1977 set_message(outbuf
,12,0,True
);
1979 if(CVAL(inbuf
,smb_wct
) == 12) {
1980 #ifdef LARGE_SMB_OFF_T
1982 * This is a large offset (64 bit) read.
1984 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
1986 #else /* !LARGE_SMB_OFF_T */
1989 * Ensure we haven't been sent a >32 bit offset.
1992 if(IVAL(inbuf
,smb_vwv10
) != 0) {
1993 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1994 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
1995 END_PROFILE(SMBreadX
);
1996 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
1999 #endif /* LARGE_SMB_OFF_T */
2003 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
2004 END_PROFILE(SMBreadX
);
2005 return ERROR_DOS(ERRDOS
,ERRlock
);
2008 nread
= send_file_readX(conn
, inbuf
, outbuf
, length
, fsp
, startpos
, smb_maxcnt
);
2010 nread
= chain_reply(inbuf
,outbuf
,length
,bufsize
);
2012 END_PROFILE(SMBreadX
);
2016 /****************************************************************************
2017 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2018 ****************************************************************************/
2020 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2023 ssize_t total_written
=0;
2024 size_t numtowrite
=0;
2029 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2031 START_PROFILE(SMBwritebraw
);
2033 if (srv_is_signing_active()) {
2034 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2037 CHECK_FSP(fsp
,conn
);
2040 tcount
= IVAL(inbuf
,smb_vwv1
);
2041 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2042 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2044 /* We have to deal with slightly different formats depending
2045 on whether we are using the core+ or lanman1.0 protocol */
2047 if(Protocol
<= PROTOCOL_COREPLUS
) {
2048 numtowrite
= SVAL(smb_buf(inbuf
),-2);
2049 data
= smb_buf(inbuf
);
2051 numtowrite
= SVAL(inbuf
,smb_vwv10
);
2052 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
2055 /* force the error type */
2056 SCVAL(inbuf
,smb_com
,SMBwritec
);
2057 SCVAL(outbuf
,smb_com
,SMBwritec
);
2059 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2060 END_PROFILE(SMBwritebraw
);
2061 return(ERROR_DOS(ERRDOS
,ERRlock
));
2065 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2067 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2068 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
2070 if (nwritten
< (ssize_t
)numtowrite
) {
2071 END_PROFILE(SMBwritebraw
);
2072 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2075 total_written
= nwritten
;
2077 /* Return a message to the redirector to tell it to send more bytes */
2078 SCVAL(outbuf
,smb_com
,SMBwritebraw
);
2079 SSVALS(outbuf
,smb_vwv0
,-1);
2080 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
2081 if (!send_smb(smbd_server_fd(),outbuf
))
2082 exit_server("reply_writebraw: send_smb failed.");
2084 /* Now read the raw data into the buffer and write it */
2085 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
2086 exit_server("secondary writebraw failed");
2089 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2090 numtowrite
= smb_len(inbuf
);
2092 /* Set up outbuf to return the correct return */
2093 outsize
= set_message(outbuf
,1,0,True
);
2094 SCVAL(outbuf
,smb_com
,SMBwritec
);
2095 SSVAL(outbuf
,smb_vwv0
,total_written
);
2097 if (numtowrite
!= 0) {
2099 if (numtowrite
> BUFFER_SIZE
) {
2100 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2101 (unsigned int)numtowrite
));
2102 exit_server("secondary writebraw failed");
2105 if (tcount
> nwritten
+numtowrite
) {
2106 DEBUG(3,("Client overestimated the write %d %d %d\n",
2107 (int)tcount
,(int)nwritten
,(int)numtowrite
));
2110 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
2111 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2113 exit_server("secondary writebraw failed");
2116 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
2118 if (nwritten
< (ssize_t
)numtowrite
) {
2119 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2120 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2124 total_written
+= nwritten
;
2127 if ((lp_syncalways(SNUM(conn
)) || write_through
) && lp_strict_sync(SNUM(conn
)))
2128 sync_file(conn
,fsp
);
2130 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2131 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
2133 /* we won't return a status if write through is not selected - this follows what WfWg does */
2134 END_PROFILE(SMBwritebraw
);
2135 if (!write_through
&& total_written
==tcount
) {
2137 #if RABBIT_PELLET_FIX
2139 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2140 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2142 if (!send_keepalive(smbd_server_fd()))
2143 exit_server("reply_writebraw: send of keepalive failed");
2151 /****************************************************************************
2152 Reply to a writeunlock (core+).
2153 ****************************************************************************/
2155 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
,
2156 int size
, int dum_buffsize
)
2158 ssize_t nwritten
= -1;
2162 NTSTATUS status
= NT_STATUS_OK
;
2163 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2165 START_PROFILE(SMBwriteunlock
);
2167 CHECK_FSP(fsp
,conn
);
2170 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2171 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2172 data
= smb_buf(inbuf
) + 3;
2174 if (numtowrite
&& is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
,
2175 WRITE_LOCK
,False
)) {
2176 END_PROFILE(SMBwriteunlock
);
2177 return ERROR_DOS(ERRDOS
,ERRlock
);
2180 /* The special X/Open SMB protocol handling of
2181 zero length writes is *NOT* done for
2186 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2188 if (lp_syncalways(SNUM(conn
)))
2189 sync_file(conn
,fsp
);
2191 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2192 END_PROFILE(SMBwriteunlock
);
2193 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2197 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)numtowrite
,
2198 (SMB_BIG_UINT
)startpos
);
2199 if (NT_STATUS_V(status
)) {
2200 END_PROFILE(SMBwriteunlock
);
2201 return ERROR_NT(status
);
2205 outsize
= set_message(outbuf
,1,0,True
);
2207 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2209 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2210 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2212 END_PROFILE(SMBwriteunlock
);
2216 /****************************************************************************
2218 ****************************************************************************/
2220 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2223 ssize_t nwritten
= -1;
2226 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2228 START_PROFILE(SMBwrite
);
2230 /* If it's an IPC, pass off the pipe handler. */
2232 END_PROFILE(SMBwrite
);
2233 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2236 CHECK_FSP(fsp
,conn
);
2239 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2240 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2241 data
= smb_buf(inbuf
) + 3;
2243 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2244 END_PROFILE(SMBwrite
);
2245 return ERROR_DOS(ERRDOS
,ERRlock
);
2249 * X/Open SMB protocol says that if smb_vwv1 is
2250 * zero then the file size should be extended or
2251 * truncated to the size given in smb_vwv[2-3].
2254 if(numtowrite
== 0) {
2256 * This is actually an allocate call, and set EOF. JRA.
2258 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
2260 END_PROFILE(SMBwrite
);
2261 return ERROR_NT(NT_STATUS_DISK_FULL
);
2263 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
2265 END_PROFILE(SMBwrite
);
2266 return ERROR_NT(NT_STATUS_DISK_FULL
);
2269 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2271 if (lp_syncalways(SNUM(conn
)))
2272 sync_file(conn
,fsp
);
2274 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2275 END_PROFILE(SMBwrite
);
2276 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2279 outsize
= set_message(outbuf
,1,0,True
);
2281 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2283 if (nwritten
< (ssize_t
)numtowrite
) {
2284 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2285 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2288 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2290 END_PROFILE(SMBwrite
);
2294 /****************************************************************************
2295 Reply to a write and X.
2296 ****************************************************************************/
2298 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2300 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2301 SMB_OFF_T startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
2302 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2303 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2304 ssize_t nwritten
= -1;
2305 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2306 unsigned int smblen
= smb_len(inbuf
);
2308 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
2309 START_PROFILE(SMBwriteX
);
2311 /* If it's an IPC, pass off the pipe handler. */
2313 END_PROFILE(SMBwriteX
);
2314 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2317 CHECK_FSP(fsp
,conn
);
2320 /* Deal with possible LARGE_WRITEX */
2322 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
2324 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
2325 END_PROFILE(SMBwriteX
);
2326 return ERROR_DOS(ERRDOS
,ERRbadmem
);
2329 data
= smb_base(inbuf
) + smb_doff
;
2331 if(CVAL(inbuf
,smb_wct
) == 14) {
2332 #ifdef LARGE_SMB_OFF_T
2334 * This is a large offset (64 bit) write.
2336 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2338 #else /* !LARGE_SMB_OFF_T */
2341 * Ensure we haven't been sent a >32 bit offset.
2344 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2345 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2346 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2347 END_PROFILE(SMBwriteX
);
2348 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2351 #endif /* LARGE_SMB_OFF_T */
2354 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2355 END_PROFILE(SMBwriteX
);
2356 return ERROR_DOS(ERRDOS
,ERRlock
);
2359 /* X/Open SMB protocol says that, unlike SMBwrite
2360 if the length is zero then NO truncation is
2361 done, just a write of zero. To truncate a file,
2367 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2369 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2370 END_PROFILE(SMBwriteX
);
2371 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2374 set_message(outbuf
,6,0,True
);
2376 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2378 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
2380 if (nwritten
< (ssize_t
)numtowrite
) {
2381 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2382 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2385 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2386 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2388 if (lp_syncalways(SNUM(conn
)) || write_through
)
2389 sync_file(conn
,fsp
);
2391 END_PROFILE(SMBwriteX
);
2392 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2395 /****************************************************************************
2397 ****************************************************************************/
2399 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2405 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2406 START_PROFILE(SMBlseek
);
2408 CHECK_FSP(fsp
,conn
);
2410 flush_write_cache(fsp
, SEEK_FLUSH
);
2412 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2413 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2414 startpos
= (SMB_OFF_T
)IVALS(inbuf
,smb_vwv2
);
2423 res
= fsp
->pos
+ startpos
;
2434 if (umode
== SEEK_END
) {
2435 if((res
= SMB_VFS_LSEEK(fsp
,fsp
->fd
,startpos
,umode
)) == -1) {
2436 if(errno
== EINVAL
) {
2437 SMB_OFF_T current_pos
= startpos
;
2438 SMB_STRUCT_STAT sbuf
;
2440 if(SMB_VFS_FSTAT(fsp
,fsp
->fd
, &sbuf
) == -1) {
2441 END_PROFILE(SMBlseek
);
2442 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2445 current_pos
+= sbuf
.st_size
;
2447 res
= SMB_VFS_LSEEK(fsp
,fsp
->fd
,0,SEEK_SET
);
2452 END_PROFILE(SMBlseek
);
2453 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2459 outsize
= set_message(outbuf
,2,0,True
);
2460 SIVAL(outbuf
,smb_vwv0
,res
);
2462 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2463 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
2465 END_PROFILE(SMBlseek
);
2469 /****************************************************************************
2471 ****************************************************************************/
2473 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2475 int outsize
= set_message(outbuf
,0,0,True
);
2476 uint16 fnum
= SVAL(inbuf
,smb_vwv0
);
2477 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2478 START_PROFILE(SMBflush
);
2481 CHECK_FSP(fsp
,conn
);
2484 file_sync_all(conn
);
2486 sync_file(conn
,fsp
);
2489 DEBUG(3,("flush\n"));
2490 END_PROFILE(SMBflush
);
2494 /****************************************************************************
2496 ****************************************************************************/
2498 int reply_exit(connection_struct
*conn
,
2499 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2502 START_PROFILE(SMBexit
);
2504 file_close_pid(SVAL(inbuf
,smb_pid
));
2506 outsize
= set_message(outbuf
,0,0,True
);
2508 DEBUG(3,("exit\n"));
2510 END_PROFILE(SMBexit
);
2514 /****************************************************************************
2515 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2516 ****************************************************************************/
2518 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2521 extern struct current_user current_user
;
2524 int32 eclass
= 0, err
= 0;
2525 files_struct
*fsp
= NULL
;
2526 START_PROFILE(SMBclose
);
2528 outsize
= set_message(outbuf
,0,0,True
);
2530 /* If it's an IPC, pass off to the pipe handler. */
2532 END_PROFILE(SMBclose
);
2533 return reply_pipe_close(conn
, inbuf
,outbuf
);
2536 fsp
= file_fsp(inbuf
,smb_vwv0
);
2539 * We can only use CHECK_FSP if we know it's not a directory.
2542 if(!fsp
|| (fsp
->conn
!= conn
) || (fsp
->vuid
!= current_user
.vuid
)) {
2543 END_PROFILE(SMBclose
);
2544 return ERROR_DOS(ERRDOS
,ERRbadfid
);
2547 if(fsp
->is_directory
) {
2549 * Special case - close NT SMB directory handle.
2551 DEBUG(3,("close %s fnum=%d\n", fsp
->is_directory
? "directory" : "stat file open", fsp
->fnum
));
2552 close_file(fsp
,True
);
2555 * Close ordinary file.
2560 /* Save the name for time set in close. */
2561 pstrcpy( file_name
, fsp
->fsp_name
);
2563 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2565 conn
->num_files_open
));
2568 * close_file() returns the unix errno if an error
2569 * was detected on close - normally this is due to
2570 * a disk full error. If not then it was probably an I/O error.
2573 if((close_err
= close_file(fsp
,True
)) != 0) {
2575 END_PROFILE(SMBclose
);
2576 return (UNIXERROR(ERRHRD
,ERRgeneral
));
2580 * Now take care of any time sent in the close.
2583 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2585 /* try and set the date */
2586 set_filetime(conn
, file_name
, mtime
);
2590 /* We have a cached error */
2592 END_PROFILE(SMBclose
);
2593 return ERROR_DOS(eclass
,err
);
2596 END_PROFILE(SMBclose
);
2600 /****************************************************************************
2601 Reply to a writeclose (Core+ protocol).
2602 ****************************************************************************/
2604 int reply_writeclose(connection_struct
*conn
,
2605 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2608 ssize_t nwritten
= -1;
2614 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2615 START_PROFILE(SMBwriteclose
);
2617 CHECK_FSP(fsp
,conn
);
2620 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2621 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
2622 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2623 data
= smb_buf(inbuf
) + 1;
2625 if (numtowrite
&& is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2626 END_PROFILE(SMBwriteclose
);
2627 return ERROR_DOS(ERRDOS
,ERRlock
);
2630 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2632 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2635 * More insanity. W2K only closes the file if writelen > 0.
2640 DEBUG(3,("reply_writeclose: zero length write doesn't close file %s\n",
2642 close_err
= close_file(fsp
,True
);
2645 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2646 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
2647 conn
->num_files_open
));
2649 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2650 END_PROFILE(SMBwriteclose
);
2651 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2654 if(close_err
!= 0) {
2656 END_PROFILE(SMBwriteclose
);
2657 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2660 outsize
= set_message(outbuf
,1,0,True
);
2662 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2663 END_PROFILE(SMBwriteclose
);
2667 /****************************************************************************
2669 ****************************************************************************/
2671 int reply_lock(connection_struct
*conn
,
2672 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
2674 int outsize
= set_message(outbuf
,0,0,True
);
2675 SMB_BIG_UINT count
,offset
;
2677 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2678 BOOL my_lock_ctx
= False
;
2680 START_PROFILE(SMBlock
);
2682 CHECK_FSP(fsp
,conn
);
2684 release_level_2_oplocks_on_change(fsp
);
2686 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2687 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2689 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2690 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
2692 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
, WRITE_LOCK
, &my_lock_ctx
);
2693 if (NT_STATUS_V(status
)) {
2695 /* Tests using Samba4 against W2K show this call never creates a blocking lock. */
2696 if (lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
2698 * A blocking lock was requested. Package up
2699 * this smb into a queued request and push it
2700 * onto the blocking lock queue.
2702 if(push_blocking_lock_request(inbuf
, length
, -1, 0, SVAL(inbuf
,smb_pid
), offset
, count
)) {
2703 END_PROFILE(SMBlock
);
2708 END_PROFILE(SMBlock
);
2709 return ERROR_NT(status
);
2712 END_PROFILE(SMBlock
);
2716 /****************************************************************************
2718 ****************************************************************************/
2720 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2723 int outsize
= set_message(outbuf
,0,0,True
);
2724 SMB_BIG_UINT count
,offset
;
2726 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2727 START_PROFILE(SMBunlock
);
2729 CHECK_FSP(fsp
,conn
);
2731 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2732 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2734 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
);
2735 if (NT_STATUS_V(status
)) {
2736 END_PROFILE(SMBunlock
);
2737 return ERROR_NT(status
);
2740 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2741 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
2743 END_PROFILE(SMBunlock
);
2747 /****************************************************************************
2749 ****************************************************************************/
2751 int reply_tdis(connection_struct
*conn
,
2752 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2754 int outsize
= set_message(outbuf
,0,0,True
);
2756 START_PROFILE(SMBtdis
);
2758 vuid
= SVAL(inbuf
,smb_uid
);
2761 DEBUG(4,("Invalid connection in tdis\n"));
2762 END_PROFILE(SMBtdis
);
2763 return ERROR_DOS(ERRSRV
,ERRinvnid
);
2768 close_cnum(conn
,vuid
);
2770 END_PROFILE(SMBtdis
);
2774 /****************************************************************************
2776 ****************************************************************************/
2778 int reply_echo(connection_struct
*conn
,
2779 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2781 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2783 unsigned int data_len
= smb_buflen(inbuf
);
2784 int outsize
= set_message(outbuf
,1,data_len
,True
);
2785 START_PROFILE(SMBecho
);
2787 if (data_len
> BUFFER_SIZE
) {
2788 DEBUG(0,("reply_echo: data_len too large.\n"));
2789 END_PROFILE(SMBecho
);
2793 /* copy any incoming data back out */
2795 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2797 if (smb_reverb
> 100) {
2798 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2802 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
2803 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2805 smb_setlen(outbuf
,outsize
- 4);
2807 if (!send_smb(smbd_server_fd(),outbuf
))
2808 exit_server("reply_echo: send_smb failed.");
2811 DEBUG(3,("echo %d times\n", smb_reverb
));
2815 END_PROFILE(SMBecho
);
2819 /****************************************************************************
2820 Reply to a printopen.
2821 ****************************************************************************/
2823 int reply_printopen(connection_struct
*conn
,
2824 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2828 START_PROFILE(SMBsplopen
);
2830 if (!CAN_PRINT(conn
)) {
2831 END_PROFILE(SMBsplopen
);
2832 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2835 /* Open for exclusive use, write only. */
2836 fsp
= print_fsp_open(conn
, NULL
);
2839 END_PROFILE(SMBsplopen
);
2840 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2843 outsize
= set_message(outbuf
,1,0,True
);
2844 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
2846 DEBUG(3,("openprint fd=%d fnum=%d\n",
2847 fsp
->fd
, fsp
->fnum
));
2849 END_PROFILE(SMBsplopen
);
2853 /****************************************************************************
2854 Reply to a printclose.
2855 ****************************************************************************/
2857 int reply_printclose(connection_struct
*conn
,
2858 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2860 int outsize
= set_message(outbuf
,0,0,True
);
2861 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2863 START_PROFILE(SMBsplclose
);
2865 CHECK_FSP(fsp
,conn
);
2867 if (!CAN_PRINT(conn
)) {
2868 END_PROFILE(SMBsplclose
);
2869 return ERROR_NT(NT_STATUS_UNSUCCESSFUL
);
2872 DEBUG(3,("printclose fd=%d fnum=%d\n",
2873 fsp
->fd
,fsp
->fnum
));
2875 close_err
= close_file(fsp
,True
);
2877 if(close_err
!= 0) {
2879 END_PROFILE(SMBsplclose
);
2880 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2883 END_PROFILE(SMBsplclose
);
2887 /****************************************************************************
2888 Reply to a printqueue.
2889 ****************************************************************************/
2891 int reply_printqueue(connection_struct
*conn
,
2892 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2894 int outsize
= set_message(outbuf
,2,3,True
);
2895 int max_count
= SVAL(inbuf
,smb_vwv0
);
2896 int start_index
= SVAL(inbuf
,smb_vwv1
);
2897 START_PROFILE(SMBsplretq
);
2899 /* we used to allow the client to get the cnum wrong, but that
2900 is really quite gross and only worked when there was only
2901 one printer - I think we should now only accept it if they
2902 get it right (tridge) */
2903 if (!CAN_PRINT(conn
)) {
2904 END_PROFILE(SMBsplretq
);
2905 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2908 SSVAL(outbuf
,smb_vwv0
,0);
2909 SSVAL(outbuf
,smb_vwv1
,0);
2910 SCVAL(smb_buf(outbuf
),0,1);
2911 SSVAL(smb_buf(outbuf
),1,0);
2913 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2914 start_index
, max_count
));
2917 print_queue_struct
*queue
= NULL
;
2918 print_status_struct status
;
2919 char *p
= smb_buf(outbuf
) + 3;
2920 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
2921 int num_to_get
= ABS(max_count
);
2922 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
2928 num_to_get
= MIN(num_to_get
,count
-first
);
2931 for (i
=first
;i
<first
+num_to_get
;i
++) {
2932 put_dos_date2(p
,0,queue
[i
].time
);
2933 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
2934 SSVAL(p
,5, queue
[i
].job
);
2935 SIVAL(p
,7,queue
[i
].size
);
2937 srvstr_push(outbuf
, p
+12, queue
[i
].fs_user
, 16, STR_ASCII
);
2942 outsize
= set_message(outbuf
,2,28*count
+3,False
);
2943 SSVAL(outbuf
,smb_vwv0
,count
);
2944 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
2945 SCVAL(smb_buf(outbuf
),0,1);
2946 SSVAL(smb_buf(outbuf
),1,28*count
);
2951 DEBUG(3,("%d entries returned in queue\n",count
));
2954 END_PROFILE(SMBsplretq
);
2958 /****************************************************************************
2959 Reply to a printwrite.
2960 ****************************************************************************/
2962 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2965 int outsize
= set_message(outbuf
,0,0,True
);
2967 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2969 START_PROFILE(SMBsplwr
);
2971 if (!CAN_PRINT(conn
)) {
2972 END_PROFILE(SMBsplwr
);
2973 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2976 CHECK_FSP(fsp
,conn
);
2979 numtowrite
= SVAL(smb_buf(inbuf
),1);
2980 data
= smb_buf(inbuf
) + 3;
2982 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
2983 END_PROFILE(SMBsplwr
);
2984 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
2987 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
2989 END_PROFILE(SMBsplwr
);
2993 /****************************************************************************
2994 The guts of the mkdir command, split out so it may be called by the NT SMB
2996 ****************************************************************************/
2998 NTSTATUS
mkdir_internal(connection_struct
*conn
, pstring directory
)
3000 BOOL bad_path
= False
;
3001 SMB_STRUCT_STAT sbuf
;
3004 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
3006 if (ms_has_wild(directory
)) {
3007 return NT_STATUS_OBJECT_NAME_INVALID
;
3010 if (check_name(directory
, conn
))
3011 ret
= vfs_MkDir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
3014 NTSTATUS nterr
= NT_STATUS_OK
;
3015 if(errno
== ENOENT
) {
3016 unix_ERR_class
= ERRDOS
;
3018 unix_ERR_code
= ERRbadpath
;
3019 nterr
= NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3021 unix_ERR_code
= ERRbadfile
;
3022 nterr
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3025 if (!NT_STATUS_IS_OK(nterr
))
3027 return map_nt_error_from_unix(errno
);
3030 return NT_STATUS_OK
;
3033 /****************************************************************************
3035 ****************************************************************************/
3037 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3042 START_PROFILE(SMBmkdir
);
3044 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), STR_TERMINATE
,&status
);
3045 if (!NT_STATUS_IS_OK(status
)) {
3046 END_PROFILE(SMBmkdir
);
3047 return ERROR_NT(status
);
3050 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
);
3052 status
= mkdir_internal(conn
, directory
);
3053 if (!NT_STATUS_IS_OK(status
)) {
3054 END_PROFILE(SMBmkdir
);
3055 return ERROR_NT(status
);
3058 outsize
= set_message(outbuf
,0,0,True
);
3060 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
3062 END_PROFILE(SMBmkdir
);
3066 /****************************************************************************
3067 Static function used by reply_rmdir to delete an entire directory
3068 tree recursively. Return False on ok, True on fail.
3069 ****************************************************************************/
3071 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
3073 const char *dname
= NULL
;
3075 void *dirptr
= OpenDir(conn
, directory
, False
);
3080 while((dname
= ReadDirName(dirptr
))) {
3084 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3087 /* Construct the full name. */
3088 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3094 pstrcpy(fullname
, directory
);
3095 pstrcat(fullname
, "/");
3096 pstrcat(fullname
, dname
);
3098 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0) {
3103 if(st
.st_mode
& S_IFDIR
) {
3104 if(recursive_rmdir(conn
, fullname
)!=0) {
3108 if(SMB_VFS_RMDIR(conn
,fullname
) != 0) {
3112 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0) {
3121 /****************************************************************************
3122 The internals of the rmdir code - called elsewhere.
3123 ****************************************************************************/
3125 BOOL
rmdir_internals(connection_struct
*conn
, char *directory
)
3129 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3130 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
3132 * Check to see if the only thing in this directory are
3133 * vetoed files/directories. If so then delete them and
3134 * retry. If we fail to delete any of them (and we *don't*
3135 * do a recursive delete) then fail the rmdir.
3137 BOOL all_veto_files
= True
;
3139 void *dirptr
= OpenDir(conn
, directory
, False
);
3141 if(dirptr
!= NULL
) {
3142 int dirpos
= TellDir(dirptr
);
3143 while ((dname
= ReadDirName(dirptr
))) {
3144 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3146 if(!IS_VETO_PATH(conn
, dname
)) {
3147 all_veto_files
= False
;
3152 if(all_veto_files
) {
3153 SeekDir(dirptr
,dirpos
);
3154 while ((dname
= ReadDirName(dirptr
))) {
3158 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
3161 /* Construct the full name. */
3162 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
3167 pstrcpy(fullname
, directory
);
3168 pstrcat(fullname
, "/");
3169 pstrcat(fullname
, dname
);
3171 if(SMB_VFS_LSTAT(conn
,fullname
, &st
) != 0)
3173 if(st
.st_mode
& S_IFDIR
) {
3174 if(lp_recursive_veto_delete(SNUM(conn
))) {
3175 if(recursive_rmdir(conn
, fullname
) != 0)
3178 if(SMB_VFS_RMDIR(conn
,fullname
) != 0)
3180 } else if(SMB_VFS_UNLINK(conn
,fullname
) != 0)
3184 /* Retry the rmdir */
3185 ok
= (SMB_VFS_RMDIR(conn
,directory
) == 0);
3195 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory
,strerror(errno
)));
3200 /****************************************************************************
3202 ****************************************************************************/
3204 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3209 BOOL bad_path
= False
;
3210 SMB_STRUCT_STAT sbuf
;
3212 START_PROFILE(SMBrmdir
);
3214 srvstr_get_path(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), STR_TERMINATE
,&status
);
3215 if (!NT_STATUS_IS_OK(status
)) {
3216 END_PROFILE(SMBrmdir
);
3217 return ERROR_NT(status
);
3220 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3222 unix_convert(directory
,conn
, NULL
,&bad_path
,&sbuf
);
3224 if (check_name(directory
,conn
)) {
3225 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3226 ok
= rmdir_internals(conn
, directory
);
3230 END_PROFILE(SMBrmdir
);
3231 return set_bad_path_error(errno
, bad_path
, outbuf
, ERRDOS
, ERRbadpath
);
3234 outsize
= set_message(outbuf
,0,0,True
);
3236 DEBUG( 3, ( "rmdir %s\n", directory
) );
3238 END_PROFILE(SMBrmdir
);
3242 /*******************************************************************
3243 Resolve wildcards in a filename rename.
3244 ********************************************************************/
3246 static BOOL
resolve_wildcards(const char *name1
, char *name2
)
3248 fstring root1
,root2
;
3250 char *p
,*p2
, *pname1
, *pname2
;
3251 int available_space
;
3254 pname1
= strrchr_m(name1
,'/');
3255 pname2
= strrchr_m(name2
,'/');
3257 if (!pname1
|| !pname2
)
3260 fstrcpy(root1
,pname1
);
3261 fstrcpy(root2
,pname2
);
3262 p
= strrchr_m(root1
,'.');
3269 p
= strrchr_m(root2
,'.');
3303 available_space
= sizeof(pstring
) - PTR_DIFF(pname2
, name2
);
3306 snprintf(pname2
, available_space
- 1, "%s.%s", root2
, ext2
);
3308 pstrcpy_base(pname2
, root2
, name2
);
3314 /****************************************************************************
3315 Ensure open files have their names updates.
3316 ****************************************************************************/
3318 static void rename_open_files(connection_struct
*conn
, SMB_DEV_T dev
, SMB_INO_T inode
, char *newname
)
3321 BOOL did_rename
= False
;
3323 for(fsp
= file_find_di_first(dev
, inode
); fsp
; fsp
= file_find_di_next(fsp
)) {
3324 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3325 fsp
->fnum
, (unsigned int)fsp
->dev
, (double)fsp
->inode
,
3326 fsp
->fsp_name
, newname
));
3327 string_set(&fsp
->fsp_name
, newname
);
3332 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3333 (unsigned int)dev
, (double)inode
, newname
));
3336 /****************************************************************************
3337 Rename an open file - given an fsp.
3338 ****************************************************************************/
3340 NTSTATUS
rename_internals_fsp(connection_struct
*conn
, files_struct
*fsp
, char *newname
, BOOL replace_if_exists
)
3342 SMB_STRUCT_STAT sbuf
;
3343 BOOL bad_path
= False
;
3344 pstring newname_last_component
;
3345 NTSTATUS error
= NT_STATUS_OK
;
3349 unix_convert(newname
,conn
,newname_last_component
,&bad_path
,&sbuf
);
3351 /* Ensure newname contains a '/' */
3352 if(strrchr_m(newname
,'/') == 0) {
3355 pstrcpy(tmpstr
, "./");
3356 pstrcat(tmpstr
, newname
);
3357 pstrcpy(newname
, tmpstr
);
3361 * Check for special case with case preserving and not
3362 * case sensitive. If the old last component differs from the original
3363 * last component only by case, then we should allow
3364 * the rename (user is trying to change the case of the
3368 if((case_sensitive
== False
) && (case_preserve
== True
) &&
3369 strequal(newname
, fsp
->fsp_name
)) {
3371 pstring newname_modified_last_component
;
3374 * Get the last component of the modified name.
3375 * Note that we guarantee that newname contains a '/'
3378 p
= strrchr_m(newname
,'/');
3379 pstrcpy(newname_modified_last_component
,p
+1);
3381 if(strcsequal(newname_modified_last_component
,
3382 newname_last_component
) == False
) {
3384 * Replace the modified last component with
3387 pstrcpy(p
+1, newname_last_component
);
3392 * If the src and dest names are identical - including case,
3393 * don't do the rename, just return success.
3396 if (strcsequal(fsp
->fsp_name
, newname
)) {
3397 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3399 return NT_STATUS_OK
;
3402 dest_exists
= vfs_object_exist(conn
,newname
,NULL
);
3404 if(!replace_if_exists
&& dest_exists
) {
3405 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3406 fsp
->fsp_name
,newname
));
3407 return NT_STATUS_OBJECT_NAME_COLLISION
;
3410 error
= can_rename(newname
,conn
,&sbuf
);
3412 if (dest_exists
&& !NT_STATUS_IS_OK(error
)) {
3413 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3414 nt_errstr(error
), fsp
->fsp_name
,newname
));
3415 if (NT_STATUS_EQUAL(error
,NT_STATUS_SHARING_VIOLATION
))
3416 error
= NT_STATUS_ACCESS_DENIED
;
3420 if(SMB_VFS_RENAME(conn
,fsp
->fsp_name
, newname
) == 0) {
3421 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3422 fsp
->fsp_name
,newname
));
3423 rename_open_files(conn
, fsp
->dev
, fsp
->inode
, newname
);
3424 return NT_STATUS_OK
;
3427 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3428 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3430 error
= map_nt_error_from_unix(errno
);
3432 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3433 nt_errstr(error
), fsp
->fsp_name
,newname
));
3438 /****************************************************************************
3439 The guts of the rename command, split out so it may be called by the NT SMB
3441 ****************************************************************************/
3443 NTSTATUS
rename_internals(connection_struct
*conn
, char *name
, char *newname
, BOOL replace_if_exists
)
3447 pstring newname_last_component
;
3450 BOOL bad_path1
= False
;
3451 BOOL bad_path2
= False
;
3453 NTSTATUS error
= NT_STATUS_OK
;
3455 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3457 *directory
= *mask
= 0;
3461 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
3462 unix_convert(newname
,conn
,newname_last_component
,&bad_path2
,&sbuf2
);
3465 * Split the old name into directory and last component
3466 * strings. Note that unix_convert may have stripped off a
3467 * leading ./ from both name and newname if the rename is
3468 * at the root of the share. We need to make sure either both
3469 * name and newname contain a / character or neither of them do
3470 * as this is checked in resolve_wildcards().
3473 p
= strrchr_m(name
,'/');
3475 pstrcpy(directory
,".");
3479 pstrcpy(directory
,name
);
3481 *p
= '/'; /* Replace needed for exceptional test below. */
3485 * We should only check the mangled cache
3486 * here if unix_convert failed. This means
3487 * that the path in 'mask' doesn't exist
3488 * on the file system and so we need to look
3489 * for a possible mangle. This patch from
3490 * Tine Smukavec <valentin.smukavec@hermes.si>.
3493 if (!rc
&& mangle_is_mangled(mask
))
3494 mangle_check_cache( mask
);
3496 has_wild
= ms_has_wild(mask
);
3500 * No wildcards - just process the one file.
3502 BOOL is_short_name
= mangle_is_8_3(name
, True
);
3504 /* Add a terminating '/' to the directory name. */
3505 pstrcat(directory
,"/");
3506 pstrcat(directory
,mask
);
3508 /* Ensure newname contains a '/' also */
3509 if(strrchr_m(newname
,'/') == 0) {
3512 pstrcpy(tmpstr
, "./");
3513 pstrcat(tmpstr
, newname
);
3514 pstrcpy(newname
, tmpstr
);
3517 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3518 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3519 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3520 newname
, newname_last_component
, is_short_name
));
3523 * Check for special case with case preserving and not
3524 * case sensitive, if directory and newname are identical,
3525 * and the old last component differs from the original
3526 * last component only by case, then we should allow
3527 * the rename (user is trying to change the case of the
3530 if((case_sensitive
== False
) &&
3531 (((case_preserve
== True
) &&
3532 (is_short_name
== False
)) ||
3533 ((short_case_preserve
== True
) &&
3534 (is_short_name
== True
))) &&
3535 strcsequal(directory
, newname
)) {
3536 pstring newname_modified_last_component
;
3539 * Get the last component of the modified name.
3540 * Note that we guarantee that newname contains a '/'
3543 p
= strrchr_m(newname
,'/');
3544 pstrcpy(newname_modified_last_component
,p
+1);
3546 if(strcsequal(newname_modified_last_component
,
3547 newname_last_component
) == False
) {
3549 * Replace the modified last component with
3552 pstrcpy(p
+1, newname_last_component
);
3556 resolve_wildcards(directory
,newname
);
3559 * The source object must exist.
3562 if (!vfs_object_exist(conn
, directory
, &sbuf1
)) {
3563 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3564 directory
,newname
));
3566 if (errno
== ENOTDIR
|| errno
== EISDIR
|| errno
== ENOENT
) {
3568 * Must return different errors depending on whether the parent
3569 * directory existed or not.
3572 p
= strrchr_m(directory
, '/');
3574 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3576 if (vfs_object_exist(conn
, directory
, NULL
))
3577 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3578 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3580 error
= map_nt_error_from_unix(errno
);
3581 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3582 nt_errstr(error
), directory
,newname
));
3587 error
= can_rename(directory
,conn
,&sbuf1
);
3589 if (!NT_STATUS_IS_OK(error
)) {
3590 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3591 nt_errstr(error
), directory
,newname
));
3596 * If the src and dest names are identical - including case,
3597 * don't do the rename, just return success.
3600 if (strcsequal(directory
, newname
)) {
3601 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3602 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory
));
3603 return NT_STATUS_OK
;
3606 if(!replace_if_exists
&& vfs_object_exist(conn
,newname
,NULL
)) {
3607 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3608 directory
,newname
));
3609 return NT_STATUS_OBJECT_NAME_COLLISION
;
3612 if(SMB_VFS_RENAME(conn
,directory
, newname
) == 0) {
3613 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3614 directory
,newname
));
3615 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3616 return NT_STATUS_OK
;
3619 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3620 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3622 error
= map_nt_error_from_unix(errno
);
3624 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3625 nt_errstr(error
), directory
,newname
));
3630 * Wildcards - process each file that matches.
3632 void *dirptr
= NULL
;
3636 if (check_name(directory
,conn
))
3637 dirptr
= OpenDir(conn
, directory
, True
);
3640 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3642 if (strequal(mask
,"????????.???"))
3645 while ((dname
= ReadDirName(dirptr
))) {
3648 pstrcpy(fname
,dname
);
3650 if(!mask_match(fname
, mask
, case_sensitive
))
3653 error
= NT_STATUS_ACCESS_DENIED
;
3654 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3655 if (!vfs_object_exist(conn
, fname
, &sbuf1
)) {
3656 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3657 DEBUG(6,("rename %s failed. Error %s\n", fname
, nt_errstr(error
)));
3660 error
= can_rename(fname
,conn
,&sbuf1
);
3661 if (!NT_STATUS_IS_OK(error
)) {
3662 DEBUG(6,("rename %s refused\n", fname
));
3665 pstrcpy(destname
,newname
);
3667 if (!resolve_wildcards(fname
,destname
)) {
3668 DEBUG(6,("resolve_wildcards %s %s failed\n",
3673 if (!replace_if_exists
&&
3674 vfs_file_exist(conn
,destname
, NULL
)) {
3675 DEBUG(6,("file_exist %s\n", destname
));
3676 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3680 if (!SMB_VFS_RENAME(conn
,fname
,destname
)) {
3681 rename_open_files(conn
, sbuf1
.st_dev
, sbuf1
.st_ino
, newname
);
3684 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3690 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
3691 error
= map_nt_error_from_unix(errno
);
3697 /****************************************************************************
3699 ****************************************************************************/
3701 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
3710 START_PROFILE(SMBmv
);
3712 p
= smb_buf(inbuf
) + 1;
3713 p
+= srvstr_get_path(inbuf
, name
, p
, sizeof(name
), STR_TERMINATE
,&status
);
3714 if (!NT_STATUS_IS_OK(status
)) {
3716 return ERROR_NT(status
);
3719 p
+= srvstr_get_path(inbuf
, newname
, p
, sizeof(newname
), STR_TERMINATE
,&status
);
3720 if (!NT_STATUS_IS_OK(status
)) {
3722 return ERROR_NT(status
);
3725 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3726 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3728 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3730 status
= rename_internals(conn
, name
, newname
, False
);
3731 if (!NT_STATUS_IS_OK(status
)) {
3733 return ERROR_NT(status
);
3737 * Win2k needs a changenotify request response before it will
3738 * update after a rename..
3740 process_pending_change_notify_queue((time_t)0);
3741 outsize
= set_message(outbuf
,0,0,True
);
3747 /*******************************************************************
3748 Copy a file as part of a reply_copy.
3749 ******************************************************************/
3751 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3752 int count
,BOOL target_is_directory
, int *err_ret
)
3755 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
3757 files_struct
*fsp1
,*fsp2
;
3762 pstrcpy(dest
,dest1
);
3763 if (target_is_directory
) {
3764 char *p
= strrchr_m(src
,'/');
3773 if (!vfs_file_exist(conn
,src
,&src_sbuf
))
3776 fsp1
= open_file_shared(conn
,src
,&src_sbuf
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
3777 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
3782 if (!target_is_directory
&& count
)
3783 ofun
= FILE_EXISTS_OPEN
;
3785 if (SMB_VFS_STAT(conn
,dest
,&sbuf2
) == -1)
3786 ZERO_STRUCTP(&sbuf2
);
3788 fsp2
= open_file_shared(conn
,dest
,&sbuf2
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
3789 ofun
,src_sbuf
.st_mode
,0,&Access
,&action
);
3792 close_file(fsp1
,False
);
3796 if ((ofun
&3) == 1) {
3797 if(SMB_VFS_LSEEK(fsp2
,fsp2
->fd
,0,SEEK_END
) == -1) {
3798 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
3800 * Stop the copy from occurring.
3803 src_sbuf
.st_size
= 0;
3807 if (src_sbuf
.st_size
)
3808 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
3810 close_file(fsp1
,False
);
3812 /* Ensure the modtime is set correctly on the destination file. */
3813 fsp2
->pending_modtime
= src_sbuf
.st_mtime
;
3816 * As we are opening fsp1 read-only we only expect
3817 * an error on close on fsp2 if we are out of space.
3818 * Thus we don't look at the error return from the
3821 *err_ret
= close_file(fsp2
,False
);
3823 return(ret
== (SMB_OFF_T
)src_sbuf
.st_size
);
3826 /****************************************************************************
3827 Reply to a file copy.
3828 ****************************************************************************/
3830 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3835 pstring mask
,newname
;
3838 int error
= ERRnoaccess
;
3842 int tid2
= SVAL(inbuf
,smb_vwv0
);
3843 int ofun
= SVAL(inbuf
,smb_vwv1
);
3844 int flags
= SVAL(inbuf
,smb_vwv2
);
3845 BOOL target_is_directory
=False
;
3846 BOOL bad_path1
= False
;
3847 BOOL bad_path2
= False
;
3849 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3852 START_PROFILE(SMBcopy
);
3854 *directory
= *mask
= 0;
3857 p
+= srvstr_get_path(inbuf
, name
, p
, sizeof(name
), STR_TERMINATE
,&status
);
3858 if (!NT_STATUS_IS_OK(status
)) {
3859 END_PROFILE(SMBcopy
);
3860 return ERROR_NT(status
);
3862 p
+= srvstr_get_path(inbuf
, newname
, p
, sizeof(newname
), STR_TERMINATE
,&status
);
3863 if (!NT_STATUS_IS_OK(status
)) {
3864 END_PROFILE(SMBcopy
);
3865 return ERROR_NT(status
);
3868 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
3870 if (tid2
!= conn
->cnum
) {
3871 /* can't currently handle inter share copies XXXX */
3872 DEBUG(3,("Rejecting inter-share copy\n"));
3873 END_PROFILE(SMBcopy
);
3874 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
3877 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3878 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3880 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
3881 unix_convert(newname
,conn
,0,&bad_path2
,&sbuf2
);
3883 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
3885 if ((flags
&1) && target_is_directory
) {
3886 END_PROFILE(SMBcopy
);
3887 return ERROR_DOS(ERRDOS
,ERRbadfile
);
3890 if ((flags
&2) && !target_is_directory
) {
3891 END_PROFILE(SMBcopy
);
3892 return ERROR_DOS(ERRDOS
,ERRbadpath
);
3895 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
3896 /* wants a tree copy! XXXX */
3897 DEBUG(3,("Rejecting tree copy\n"));
3898 END_PROFILE(SMBcopy
);
3899 return ERROR_DOS(ERRSRV
,ERRerror
);
3902 p
= strrchr_m(name
,'/');
3904 pstrcpy(directory
,"./");
3908 pstrcpy(directory
,name
);
3913 * We should only check the mangled cache
3914 * here if unix_convert failed. This means
3915 * that the path in 'mask' doesn't exist
3916 * on the file system and so we need to look
3917 * for a possible mangle. This patch from
3918 * Tine Smukavec <valentin.smukavec@hermes.si>.
3921 if (!rc
&& mangle_is_mangled(mask
))
3922 mangle_check_cache( mask
);
3924 has_wild
= ms_has_wild(mask
);
3927 pstrcat(directory
,"/");
3928 pstrcat(directory
,mask
);
3929 if (resolve_wildcards(directory
,newname
) &&
3930 copy_file(directory
,newname
,conn
,ofun
, count
,target_is_directory
,&err
))
3934 END_PROFILE(SMBcopy
);
3935 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3938 exists
= vfs_file_exist(conn
,directory
,NULL
);
3941 void *dirptr
= NULL
;
3945 if (check_name(directory
,conn
))
3946 dirptr
= OpenDir(conn
, directory
, True
);
3951 if (strequal(mask
,"????????.???"))
3954 while ((dname
= ReadDirName(dirptr
))) {
3956 pstrcpy(fname
,dname
);
3958 if(!mask_match(fname
, mask
, case_sensitive
))
3961 error
= ERRnoaccess
;
3962 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
3963 pstrcpy(destname
,newname
);
3964 if (resolve_wildcards(fname
,destname
) &&
3965 copy_file(fname
,destname
,conn
,ofun
,
3966 count
,target_is_directory
,&err
))
3968 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
3976 /* Error on close... */
3978 END_PROFILE(SMBcopy
);
3979 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3983 END_PROFILE(SMBcopy
);
3984 return ERROR_DOS(ERRDOS
,error
);
3986 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
)) {
3987 unix_ERR_class
= ERRDOS
;
3988 unix_ERR_code
= ERRbadpath
;
3990 END_PROFILE(SMBcopy
);
3991 return(UNIXERROR(ERRDOS
,error
));
3995 outsize
= set_message(outbuf
,1,0,True
);
3996 SSVAL(outbuf
,smb_vwv0
,count
);
3998 END_PROFILE(SMBcopy
);
4002 /****************************************************************************
4004 ****************************************************************************/
4006 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4014 START_PROFILE(pathworks_setdir
);
4017 if (!CAN_SETDIR(snum
)) {
4018 END_PROFILE(pathworks_setdir
);
4019 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4022 srvstr_get_path(inbuf
, newdir
, smb_buf(inbuf
) + 1, sizeof(newdir
), STR_TERMINATE
,&status
);
4023 if (!NT_STATUS_IS_OK(status
)) {
4024 END_PROFILE(pathworks_setdir
);
4025 return ERROR_NT(status
);
4028 if (strlen(newdir
) == 0) {
4031 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
4033 string_set(&conn
->connectpath
,newdir
);
4037 END_PROFILE(pathworks_setdir
);
4038 return ERROR_DOS(ERRDOS
,ERRbadpath
);
4041 outsize
= set_message(outbuf
,0,0,True
);
4042 SCVAL(outbuf
,smb_reh
,CVAL(inbuf
,smb_reh
));
4044 DEBUG(3,("setdir %s\n", newdir
));
4046 END_PROFILE(pathworks_setdir
);
4050 /****************************************************************************
4051 Get a lock pid, dealing with large count requests.
4052 ****************************************************************************/
4054 uint16
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
4056 if(!large_file_format
)
4057 return SVAL(data
,SMB_LPID_OFFSET(data_offset
));
4059 return SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
4062 /****************************************************************************
4063 Get a lock count, dealing with large count requests.
4064 ****************************************************************************/
4066 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
4068 SMB_BIG_UINT count
= 0;
4070 if(!large_file_format
) {
4071 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
4074 #if defined(HAVE_LONGLONG)
4075 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
4076 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
4077 #else /* HAVE_LONGLONG */
4080 * NT4.x seems to be broken in that it sends large file (64 bit)
4081 * lockingX calls even if the CAP_LARGE_FILES was *not*
4082 * negotiated. For boxes without large unsigned ints truncate the
4083 * lock count by dropping the top 32 bits.
4086 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
4087 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4088 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
4089 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
4090 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
4093 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
4094 #endif /* HAVE_LONGLONG */
4100 #if !defined(HAVE_LONGLONG)
4101 /****************************************************************************
4102 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4103 ****************************************************************************/
4105 static uint32
map_lock_offset(uint32 high
, uint32 low
)
4109 uint32 highcopy
= high
;
4112 * Try and find out how many significant bits there are in high.
4115 for(i
= 0; highcopy
; i
++)
4119 * We use 31 bits not 32 here as POSIX
4120 * lock offsets may not be negative.
4123 mask
= (~0) << (31 - i
);
4126 return 0; /* Fail. */
4132 #endif /* !defined(HAVE_LONGLONG) */
4134 /****************************************************************************
4135 Get a lock offset, dealing with large offset requests.
4136 ****************************************************************************/
4138 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
4140 SMB_BIG_UINT offset
= 0;
4144 if(!large_file_format
) {
4145 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
4148 #if defined(HAVE_LONGLONG)
4149 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
4150 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
4151 #else /* HAVE_LONGLONG */
4154 * NT4.x seems to be broken in that it sends large file (64 bit)
4155 * lockingX calls even if the CAP_LARGE_FILES was *not*
4156 * negotiated. For boxes without large unsigned ints mangle the
4157 * lock offset by mapping the top 32 bits onto the lower 32.
4160 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
4161 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4162 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
4165 if((new_low
= map_lock_offset(high
, low
)) == 0) {
4167 return (SMB_BIG_UINT
)-1;
4170 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4171 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
4172 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
4173 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
4176 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
4177 #endif /* HAVE_LONGLONG */
4183 /****************************************************************************
4184 Reply to a lockingX request.
4185 ****************************************************************************/
4187 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4189 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
4190 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
4191 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
4192 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
4193 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
4194 SMB_BIG_UINT count
= 0, offset
= 0;
4196 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
4199 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
4201 BOOL my_lock_ctx
= False
;
4204 START_PROFILE(SMBlockingX
);
4206 CHECK_FSP(fsp
,conn
);
4208 data
= smb_buf(inbuf
);
4210 if (locktype
& (LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_CHANGE_LOCKTYPE
)) {
4211 /* we don't support these - and CANCEL_LOCK makes w2k
4212 and XP reboot so I don't really want to be
4213 compatible! (tridge) */
4214 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
4217 /* Check if this is an oplock break on a file
4218 we have granted an oplock on.
4220 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
4221 /* Client can insist on breaking to none. */
4222 BOOL break_to_none
= (oplocklevel
== 0);
4224 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4225 (unsigned int)oplocklevel
, fsp
->fnum
));
4228 * Make sure we have granted an exclusive or batch oplock on this file.
4231 if(!EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
4232 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4233 no oplock granted on this file (%s).\n", fsp
->fnum
, fsp
->fsp_name
));
4235 /* if this is a pure oplock break request then don't send a reply */
4236 if (num_locks
== 0 && num_ulocks
== 0) {
4237 END_PROFILE(SMBlockingX
);
4240 END_PROFILE(SMBlockingX
);
4241 return ERROR_DOS(ERRDOS
,ERRlock
);
4245 if (remove_oplock(fsp
, break_to_none
) == False
) {
4246 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4250 /* if this is a pure oplock break request then don't send a reply */
4251 if (num_locks
== 0 && num_ulocks
== 0) {
4252 /* Sanity check - ensure a pure oplock break is not a
4254 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
4255 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4256 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
4257 END_PROFILE(SMBlockingX
);
4263 * We do this check *after* we have checked this is not a oplock break
4264 * response message. JRA.
4267 release_level_2_oplocks_on_change(fsp
);
4269 /* Data now points at the beginning of the list
4270 of smb_unlkrng structs */
4271 for(i
= 0; i
< (int)num_ulocks
; i
++) {
4272 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4273 count
= get_lock_count( data
, i
, large_file_format
);
4274 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4277 * There is no error code marked "stupid client bug".... :-).
4280 END_PROFILE(SMBlockingX
);
4281 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4284 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4285 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
));
4287 status
= do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4288 if (NT_STATUS_V(status
)) {
4289 END_PROFILE(SMBlockingX
);
4290 return ERROR_NT(status
);
4294 /* Setup the timeout in seconds. */
4296 lock_timeout
= ((lock_timeout
== -1) ? -1 : (lock_timeout
+499)/500);
4298 /* Now do any requested locks */
4299 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
4301 /* Data now points at the beginning of the list
4302 of smb_lkrng structs */
4304 for(i
= 0; i
< (int)num_locks
; i
++) {
4305 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4306 count
= get_lock_count( data
, i
, large_file_format
);
4307 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4310 * There is no error code marked "stupid client bug".... :-).
4313 END_PROFILE(SMBlockingX
);
4314 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4317 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4318 (double)offset
, (double)count
, (unsigned int)lock_pid
,
4319 fsp
->fsp_name
, (int)lock_timeout
));
4321 status
= do_lock_spin(fsp
,conn
,lock_pid
, count
,offset
,
4322 ((locktype
& 1) ? READ_LOCK
: WRITE_LOCK
), &my_lock_ctx
);
4323 if (NT_STATUS_V(status
)) {
4324 if ((lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
)) && !my_lock_ctx
&& ERROR_WAS_LOCK_DENIED(status
)) {
4326 * A blocking lock was requested. Package up
4327 * this smb into a queued request and push it
4328 * onto the blocking lock queue.
4330 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
, lock_pid
, offset
, count
)) {
4331 END_PROFILE(SMBlockingX
);
4339 /* If any of the above locks failed, then we must unlock
4340 all of the previous locks (X/Open spec). */
4341 if (i
!= num_locks
&& num_locks
!= 0) {
4343 * Ensure we don't do a remove on the lock that just failed,
4344 * as under POSIX rules, if we have a lock already there, we
4345 * will delete it (and we shouldn't) .....
4347 for(i
--; i
>= 0; i
--) {
4348 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4349 count
= get_lock_count( data
, i
, large_file_format
);
4350 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4353 * There is no error code marked "stupid client bug".... :-).
4356 END_PROFILE(SMBlockingX
);
4357 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4360 do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4362 END_PROFILE(SMBlockingX
);
4363 return ERROR_NT(status
);
4366 set_message(outbuf
,2,0,True
);
4368 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4369 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
4371 END_PROFILE(SMBlockingX
);
4372 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
4375 /****************************************************************************
4376 Reply to a SMBreadbmpx (read block multiplex) request.
4377 ****************************************************************************/
4379 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4390 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4391 START_PROFILE(SMBreadBmpx
);
4393 /* this function doesn't seem to work - disable by default */
4394 if (!lp_readbmpx()) {
4395 END_PROFILE(SMBreadBmpx
);
4396 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
4399 outsize
= set_message(outbuf
,8,0,True
);
4401 CHECK_FSP(fsp
,conn
);
4404 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv1
);
4405 maxcount
= SVAL(inbuf
,smb_vwv3
);
4407 data
= smb_buf(outbuf
);
4408 pad
= ((long)data
)%4;
4413 max_per_packet
= bufsize
-(outsize
+pad
);
4417 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
4418 END_PROFILE(SMBreadBmpx
);
4419 return ERROR_DOS(ERRDOS
,ERRlock
);
4423 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
4425 nread
= read_file(fsp
,data
,startpos
,N
);
4430 if (nread
< (ssize_t
)N
)
4431 tcount
= total_read
+ nread
;
4433 set_message(outbuf
,8,nread
,False
);
4434 SIVAL(outbuf
,smb_vwv0
,startpos
);
4435 SSVAL(outbuf
,smb_vwv2
,tcount
);
4436 SSVAL(outbuf
,smb_vwv6
,nread
);
4437 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
4439 if (!send_smb(smbd_server_fd(),outbuf
))
4440 exit_server("reply_readbmpx: send_smb failed.");
4442 total_read
+= nread
;
4444 } while (total_read
< (ssize_t
)tcount
);
4446 END_PROFILE(SMBreadBmpx
);
4450 /****************************************************************************
4451 Reply to a SMBsetattrE.
4452 ****************************************************************************/
4454 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4456 struct utimbuf unix_times
;
4458 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4459 START_PROFILE(SMBsetattrE
);
4461 outsize
= set_message(outbuf
,0,0,True
);
4463 if(!fsp
|| (fsp
->conn
!= conn
)) {
4464 END_PROFILE(SMBgetattrE
);
4465 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4469 * Convert the DOS times into unix times. Ignore create
4470 * time as UNIX can't set this.
4473 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4474 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4477 * Patch from Ray Frush <frush@engr.colostate.edu>
4478 * Sometimes times are sent as zero - ignore them.
4481 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0)) {
4482 /* Ignore request */
4483 if( DEBUGLVL( 3 ) ) {
4484 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4485 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4487 END_PROFILE(SMBsetattrE
);
4489 } else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0)) {
4490 /* set modify time = to access time if modify time was 0 */
4491 unix_times
.modtime
= unix_times
.actime
;
4494 /* Set the date on this file */
4495 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
4496 END_PROFILE(SMBsetattrE
);
4497 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4500 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4501 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4503 END_PROFILE(SMBsetattrE
);
4508 /* Back from the dead for OS/2..... JRA. */
4510 /****************************************************************************
4511 Reply to a SMBwritebmpx (write block multiplex primary) request.
4512 ****************************************************************************/
4514 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4517 ssize_t nwritten
= -1;
4524 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4525 START_PROFILE(SMBwriteBmpx
);
4527 CHECK_FSP(fsp
,conn
);
4531 tcount
= SVAL(inbuf
,smb_vwv1
);
4532 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv3
);
4533 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
4534 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4535 smb_doff
= SVAL(inbuf
,smb_vwv11
);
4537 data
= smb_base(inbuf
) + smb_doff
;
4539 /* If this fails we need to send an SMBwriteC response,
4540 not an SMBwritebmpx - set this up now so we don't forget */
4541 SCVAL(outbuf
,smb_com
,SMBwritec
);
4543 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
,False
)) {
4544 END_PROFILE(SMBwriteBmpx
);
4545 return(ERROR_DOS(ERRDOS
,ERRlock
));
4548 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4550 if(lp_syncalways(SNUM(conn
)) || write_through
)
4551 sync_file(conn
,fsp
);
4553 if(nwritten
< (ssize_t
)numtowrite
) {
4554 END_PROFILE(SMBwriteBmpx
);
4555 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
4558 /* If the maximum to be written to this file
4559 is greater than what we just wrote then set
4560 up a secondary struct to be attached to this
4561 fd, we will use this to cache error messages etc. */
4563 if((ssize_t
)tcount
> nwritten
) {
4564 write_bmpx_struct
*wbms
;
4565 if(fsp
->wbmpx_ptr
!= NULL
)
4566 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
4568 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
4570 DEBUG(0,("Out of memory in reply_readmpx\n"));
4571 END_PROFILE(SMBwriteBmpx
);
4572 return(ERROR_DOS(ERRSRV
,ERRnoresource
));
4574 wbms
->wr_mode
= write_through
;
4575 wbms
->wr_discard
= False
; /* No errors yet */
4576 wbms
->wr_total_written
= nwritten
;
4577 wbms
->wr_errclass
= 0;
4579 fsp
->wbmpx_ptr
= wbms
;
4582 /* We are returning successfully, set the message type back to
4584 SCVAL(outbuf
,smb_com
,SMBwriteBmpx
);
4586 outsize
= set_message(outbuf
,1,0,True
);
4588 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
4590 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4591 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
4593 if (write_through
&& tcount
==nwritten
) {
4594 /* We need to send both a primary and a secondary response */
4595 smb_setlen(outbuf
,outsize
- 4);
4596 if (!send_smb(smbd_server_fd(),outbuf
))
4597 exit_server("reply_writebmpx: send_smb failed.");
4599 /* Now the secondary */
4600 outsize
= set_message(outbuf
,1,0,True
);
4601 SCVAL(outbuf
,smb_com
,SMBwritec
);
4602 SSVAL(outbuf
,smb_vwv0
,nwritten
);
4605 END_PROFILE(SMBwriteBmpx
);
4609 /****************************************************************************
4610 Reply to a SMBwritebs (write block multiplex secondary) request.
4611 ****************************************************************************/
4613 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4616 ssize_t nwritten
= -1;
4623 write_bmpx_struct
*wbms
;
4624 BOOL send_response
= False
;
4625 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4626 START_PROFILE(SMBwriteBs
);
4628 CHECK_FSP(fsp
,conn
);
4631 tcount
= SVAL(inbuf
,smb_vwv1
);
4632 startpos
= IVAL_TO_SMB_OFF_T(inbuf
,smb_vwv2
);
4633 numtowrite
= SVAL(inbuf
,smb_vwv6
);
4634 smb_doff
= SVAL(inbuf
,smb_vwv7
);
4636 data
= smb_base(inbuf
) + smb_doff
;
4638 /* We need to send an SMBwriteC response, not an SMBwritebs */
4639 SCVAL(outbuf
,smb_com
,SMBwritec
);
4641 /* This fd should have an auxiliary struct attached,
4642 check that it does */
4643 wbms
= fsp
->wbmpx_ptr
;
4645 END_PROFILE(SMBwriteBs
);
4649 /* If write through is set we can return errors, else we must cache them */
4650 write_through
= wbms
->wr_mode
;
4652 /* Check for an earlier error */
4653 if(wbms
->wr_discard
) {
4654 END_PROFILE(SMBwriteBs
);
4655 return -1; /* Just discard the packet */
4658 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4660 if(lp_syncalways(SNUM(conn
)) || write_through
)
4661 sync_file(conn
,fsp
);
4663 if (nwritten
< (ssize_t
)numtowrite
) {
4665 /* We are returning an error - we can delete the aux struct */
4668 fsp
->wbmpx_ptr
= NULL
;
4669 END_PROFILE(SMBwriteBs
);
4670 return(ERROR_DOS(ERRHRD
,ERRdiskfull
));
4672 END_PROFILE(SMBwriteBs
);
4673 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
4676 /* Increment the total written, if this matches tcount
4677 we can discard the auxiliary struct (hurrah !) and return a writeC */
4678 wbms
->wr_total_written
+= nwritten
;
4679 if(wbms
->wr_total_written
>= tcount
) {
4680 if (write_through
) {
4681 outsize
= set_message(outbuf
,1,0,True
);
4682 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
4683 send_response
= True
;
4687 fsp
->wbmpx_ptr
= NULL
;
4691 END_PROFILE(SMBwriteBs
);
4695 END_PROFILE(SMBwriteBs
);
4699 /****************************************************************************
4700 Reply to a SMBgetattrE.
4701 ****************************************************************************/
4703 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4705 SMB_STRUCT_STAT sbuf
;
4708 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4709 START_PROFILE(SMBgetattrE
);
4711 outsize
= set_message(outbuf
,11,0,True
);
4713 if(!fsp
|| (fsp
->conn
!= conn
)) {
4714 END_PROFILE(SMBgetattrE
);
4715 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4718 /* Do an fstat on this file */
4719 if(fsp_stat(fsp
, &sbuf
)) {
4720 END_PROFILE(SMBgetattrE
);
4721 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4724 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4727 * Convert the times into dos times. Set create
4728 * date to be last modify date as UNIX doesn't save
4732 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4733 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4734 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4737 SIVAL(outbuf
,smb_vwv6
,0);
4738 SIVAL(outbuf
,smb_vwv8
,0);
4740 uint32 allocation_size
= get_allocation_size(fsp
, &sbuf
);
4741 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
4742 SIVAL(outbuf
,smb_vwv8
,allocation_size
);
4744 SSVAL(outbuf
,smb_vwv10
, mode
);
4746 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
4748 END_PROFILE(SMBgetattrE
);