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 pstring global_myname
;
37 extern int global_oplock_break
;
38 unsigned int smb_echo_count
= 0;
40 extern BOOL global_encrypted_passwords_negotiated
;
42 /****************************************************************************
43 Reply to an special message.
44 ****************************************************************************/
46 int reply_special(char *inbuf
,char *outbuf
)
49 int msg_type
= CVAL(inbuf
,0);
50 int msg_flags
= CVAL(inbuf
,1);
56 static BOOL already_got_session
= False
;
60 memset(outbuf
,'\0',smb_size
);
65 case 0x81: /* session request */
67 if (already_got_session
) {
68 exit_server("multiple session request not permitted");
73 if (name_len(inbuf
+4) > 50 ||
74 name_len(inbuf
+4 + name_len(inbuf
+ 4)) > 50) {
75 DEBUG(0,("Invalid name length in session request\n"));
78 name_extract(inbuf
,4,name1
);
79 name_extract(inbuf
,4 + name_len(inbuf
+ 4),name2
);
80 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
87 name_type
= name2
[15];
91 set_local_machine_name(name1
);
92 set_remote_machine_name(name2
);
94 DEBUG(2,("netbios connect: local=%s remote=%s\n",
95 get_local_machine_name(), get_remote_machine_name() ));
97 if (name_type
== 'R') {
98 /* We are being asked for a pathworks session ---
100 SCVAL(outbuf
, 0,0x83);
104 /* only add the client's machine name to the list
105 of possibly valid usernames if we are operating
106 in share mode security */
107 if (lp_security() == SEC_SHARE
) {
108 add_session_user(get_remote_machine_name());
111 reload_services(True
);
114 claim_connection(NULL
,"",0,True
,FLAG_MSG_GENERAL
|FLAG_MSG_SMBD
);
116 already_got_session
= True
;
119 case 0x89: /* session keepalive request
120 (some old clients produce this?) */
121 SCVAL(outbuf
,0,SMBkeepalive
);
125 case 0x82: /* positive session response */
126 case 0x83: /* negative session response */
127 case 0x84: /* retarget session response */
128 DEBUG(0,("Unexpected session response\n"));
131 case SMBkeepalive
: /* session keepalive */
136 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
137 msg_type
, msg_flags
));
142 /****************************************************************************
144 ****************************************************************************/
146 int reply_tcon(connection_struct
*conn
,
147 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
154 uint16 vuid
= SVAL(inbuf
,smb_uid
);
158 DATA_BLOB password_blob
;
160 START_PROFILE(SMBtcon
);
162 *service_buf
= *password
= *dev
= 0;
164 p
= smb_buf(inbuf
)+1;
165 p
+= srvstr_pull_buf(inbuf
, service_buf
, p
, sizeof(service
), STR_TERMINATE
) + 1;
166 pwlen
= srvstr_pull_buf(inbuf
, password
, p
, sizeof(password
), STR_TERMINATE
) + 1;
168 p
+= srvstr_pull_buf(inbuf
, dev
, p
, sizeof(dev
), STR_TERMINATE
) + 1;
170 p
= strrchr_m(service_buf
,'\\');
174 service
= service_buf
;
177 password_blob
= data_blob(password
, pwlen
+1);
179 conn
= make_connection(service
,password_blob
,dev
,vuid
,&nt_status
);
181 data_blob_clear_free(&password_blob
);
184 END_PROFILE(SMBtcon
);
185 return ERROR_NT(nt_status
);
188 outsize
= set_message(outbuf
,2,0,True
);
189 SSVAL(outbuf
,smb_vwv0
,max_recv
);
190 SSVAL(outbuf
,smb_vwv1
,conn
->cnum
);
191 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
193 DEBUG(3,("tcon service=%s cnum=%d\n",
194 service
, conn
->cnum
));
196 END_PROFILE(SMBtcon
);
200 /****************************************************************************
201 Reply to a tcon and X.
202 ****************************************************************************/
204 int reply_tcon_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
210 uint16 vuid
= SVAL(inbuf
,smb_uid
);
211 int passlen
= SVAL(inbuf
,smb_vwv3
);
214 extern BOOL global_encrypted_passwords_negotiated
;
215 START_PROFILE(SMBtconX
);
217 *service
= *devicename
= 0;
219 /* we might have to close an old one */
220 if ((SVAL(inbuf
,smb_vwv2
) & 0x1) && conn
) {
221 close_cnum(conn
,vuid
);
224 if (passlen
> MAX_PASS_LEN
) {
225 return ERROR_DOS(ERRDOS
,ERRbuftoosmall
);
228 if (global_encrypted_passwords_negotiated
) {
229 password
= data_blob(smb_buf(inbuf
),passlen
);
231 password
= data_blob(smb_buf(inbuf
),passlen
+1);
232 /* Ensure correct termination */
233 password
.data
[passlen
]=0;
236 p
= smb_buf(inbuf
) + passlen
;
237 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
240 * the service name can be either: \\server\share
241 * or share directly like on the DELL PowerVault 705
244 q
= strchr_m(path
+2,'\\');
246 END_PROFILE(SMBtconX
);
247 return(ERROR_DOS(ERRDOS
,ERRnosuchshare
));
249 fstrcpy(service
,q
+1);
252 fstrcpy(service
,path
);
254 p
+= srvstr_pull(inbuf
, devicename
, p
, sizeof(devicename
), 6, STR_ASCII
);
256 DEBUG(4,("Got device type %s\n",devicename
));
258 conn
= make_connection(service
,password
,devicename
,vuid
,&nt_status
);
260 data_blob_clear_free(&password
);
263 END_PROFILE(SMBtconX
);
264 return ERROR_NT(nt_status
);
267 if (Protocol
< PROTOCOL_NT1
) {
268 set_message(outbuf
,2,0,True
);
270 p
+= srvstr_push(outbuf
, p
, devicename
, -1,
271 STR_TERMINATE
|STR_ASCII
);
272 set_message_end(outbuf
,p
);
274 /* NT sets the fstype of IPC$ to the null string */
275 char *fsname
= IS_IPC(conn
) ? "" : lp_fstype(SNUM(conn
));
277 set_message(outbuf
,3,0,True
);
280 p
+= srvstr_push(outbuf
, p
, devicename
, -1,
281 STR_TERMINATE
|STR_ASCII
);
282 p
+= srvstr_push(outbuf
, p
, fsname
, -1,
285 set_message_end(outbuf
,p
);
287 /* what does setting this bit do? It is set by NT4 and
288 may affect the ability to autorun mounted cdroms */
289 SSVAL(outbuf
, smb_vwv2
, SMB_SUPPORT_SEARCH_BITS
|
290 (lp_csc_policy(SNUM(conn
)) << 2));
292 init_dfsroot(conn
, inbuf
, outbuf
);
296 DEBUG(3,("tconX service=%s \n",
299 /* set the incoming and outgoing tid to the just created one */
300 SSVAL(inbuf
,smb_tid
,conn
->cnum
);
301 SSVAL(outbuf
,smb_tid
,conn
->cnum
);
303 END_PROFILE(SMBtconX
);
304 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
307 /****************************************************************************
308 Reply to an unknown type.
309 ****************************************************************************/
311 int reply_unknown(char *inbuf
,char *outbuf
)
314 type
= CVAL(inbuf
,smb_com
);
316 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
317 smb_fn_name(type
), type
, type
));
319 return(ERROR_DOS(ERRSRV
,ERRunknownsmb
));
322 /****************************************************************************
324 ****************************************************************************/
326 int reply_ioctl(connection_struct
*conn
,
327 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
329 uint16 device
= SVAL(inbuf
,smb_vwv1
);
330 uint16 function
= SVAL(inbuf
,smb_vwv2
);
331 uint32 ioctl_code
= (device
<< 16) + function
;
332 int replysize
, outsize
;
334 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
335 START_PROFILE(SMBioctl
);
337 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code
));
339 switch (ioctl_code
) {
340 case IOCTL_QUERY_JOB_INFO
:
344 END_PROFILE(SMBioctl
);
345 return(ERROR_DOS(ERRSRV
,ERRnosupport
));
348 outsize
= set_message(outbuf
,8,replysize
+1,True
);
349 SSVAL(outbuf
,smb_vwv1
,replysize
); /* Total data bytes returned */
350 SSVAL(outbuf
,smb_vwv5
,replysize
); /* Data bytes this buffer */
351 SSVAL(outbuf
,smb_vwv6
,52); /* Offset to data */
352 p
= smb_buf(outbuf
) + 1; /* Allow for alignment */
354 switch (ioctl_code
) {
355 case IOCTL_QUERY_JOB_INFO
:
357 uint16 rap_jobid
= pjobid_to_rap(SNUM(fsp
->conn
), fsp
->print_jobid
);
358 SSVAL(p
,0,rap_jobid
); /* Job number */
359 srvstr_push(outbuf
, p
+2, global_myname
, 15, STR_TERMINATE
|STR_ASCII
);
360 srvstr_push(outbuf
, p
+18, lp_servicename(SNUM(conn
)), 13, STR_TERMINATE
|STR_ASCII
);
365 END_PROFILE(SMBioctl
);
369 /****************************************************************************
371 ****************************************************************************/
373 int reply_chkpth(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
379 BOOL bad_path
= False
;
380 SMB_STRUCT_STAT sbuf
;
381 START_PROFILE(SMBchkpth
);
383 srvstr_pull_buf(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), STR_TERMINATE
);
385 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
387 unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
389 mode
= SVAL(inbuf
,smb_vwv0
);
391 if (check_name(name
,conn
)) {
392 if (VALID_STAT(sbuf
) || vfs_stat(conn
,name
,&sbuf
) == 0)
393 ok
= S_ISDIR(sbuf
.st_mode
);
397 /* We special case this - as when a Windows machine
398 is parsing a path is steps through the components
399 one at a time - if a component fails it expects
400 ERRbadpath, not ERRbadfile.
403 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND
);
405 return(UNIXERROR(ERRDOS
,ERRbadpath
));
408 outsize
= set_message(outbuf
,0,0,True
);
410 DEBUG(3,("chkpth %s mode=%d\n", name
, mode
));
412 END_PROFILE(SMBchkpth
);
416 /****************************************************************************
418 ****************************************************************************/
420 int reply_getatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
424 SMB_STRUCT_STAT sbuf
;
429 BOOL bad_path
= False
;
431 START_PROFILE(SMBgetatr
);
433 p
= smb_buf(inbuf
) + 1;
434 p
+= srvstr_pull_buf(inbuf
, fname
, p
, sizeof(fname
), STR_TERMINATE
);
436 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
438 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
439 under WfWg - weird! */
442 mode
= aHIDDEN
| aDIR
;
443 if (!CAN_WRITE(conn
)) mode
|= aRONLY
;
450 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
451 if (check_name(fname
,conn
))
453 if (VALID_STAT(sbuf
) || vfs_stat(conn
,fname
,&sbuf
) == 0)
455 mode
= dos_mode(conn
,fname
,&sbuf
);
457 mtime
= sbuf
.st_mtime
;
463 DEBUG(3,("stat of %s failed (%s)\n",fname
,strerror(errno
)));
469 set_bad_path_error(errno
, bad_path
);
470 END_PROFILE(SMBgetatr
);
471 return(UNIXERROR(ERRDOS
,ERRbadfile
));
474 outsize
= set_message(outbuf
,10,0,True
);
476 SSVAL(outbuf
,smb_vwv0
,mode
);
477 if(lp_dos_filetime_resolution(SNUM(conn
)) )
478 put_dos_date3(outbuf
,smb_vwv1
,mtime
& ~1);
480 put_dos_date3(outbuf
,smb_vwv1
,mtime
);
481 SIVAL(outbuf
,smb_vwv3
,(uint32
)size
);
483 if (Protocol
>= PROTOCOL_NT1
)
484 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
486 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname
, mode
, (uint32
)size
) );
488 END_PROFILE(SMBgetatr
);
492 /****************************************************************************
494 ****************************************************************************/
496 int reply_setatr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
503 SMB_STRUCT_STAT sbuf
;
504 BOOL bad_path
= False
;
507 START_PROFILE(SMBsetatr
);
509 p
= smb_buf(inbuf
) + 1;
510 p
+= srvstr_pull_buf(inbuf
, fname
, p
, sizeof(fname
), STR_TERMINATE
);
511 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
513 mode
= SVAL(inbuf
,smb_vwv0
);
514 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
516 if (VALID_STAT_OF_DIR(sbuf
))
521 if (check_name(fname
,conn
))
522 ok
= (file_chmod(conn
,fname
,mode
,NULL
) == 0);
524 ok
= set_filetime(conn
,fname
,mtime
);
528 set_bad_path_error(errno
, bad_path
);
529 END_PROFILE(SMBsetatr
);
530 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
533 outsize
= set_message(outbuf
,0,0,True
);
535 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname
, mode
) );
537 END_PROFILE(SMBsetatr
);
541 /****************************************************************************
543 ****************************************************************************/
545 int reply_dskattr(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
548 SMB_BIG_UINT dfree
,dsize
,bsize
;
549 START_PROFILE(SMBdskattr
);
551 conn
->vfs_ops
.disk_free(conn
,".",True
,&bsize
,&dfree
,&dsize
);
553 outsize
= set_message(outbuf
,5,0,True
);
555 if (Protocol
<= PROTOCOL_LANMAN2
) {
556 double total_space
, free_space
;
557 /* we need to scale this to a number that DOS6 can handle. We
558 use floating point so we can handle large drives on systems
559 that don't have 64 bit integers
561 we end up displaying a maximum of 2G to DOS systems
563 total_space
= dsize
* (double)bsize
;
564 free_space
= dfree
* (double)bsize
;
566 dsize
= (total_space
+63*512) / (64*512);
567 dfree
= (free_space
+63*512) / (64*512);
569 if (dsize
> 0xFFFF) dsize
= 0xFFFF;
570 if (dfree
> 0xFFFF) dfree
= 0xFFFF;
572 SSVAL(outbuf
,smb_vwv0
,dsize
);
573 SSVAL(outbuf
,smb_vwv1
,64); /* this must be 64 for dos systems */
574 SSVAL(outbuf
,smb_vwv2
,512); /* and this must be 512 */
575 SSVAL(outbuf
,smb_vwv3
,dfree
);
577 SSVAL(outbuf
,smb_vwv0
,dsize
);
578 SSVAL(outbuf
,smb_vwv1
,bsize
/512);
579 SSVAL(outbuf
,smb_vwv2
,512);
580 SSVAL(outbuf
,smb_vwv3
,dfree
);
583 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree
));
585 END_PROFILE(SMBdskattr
);
589 /****************************************************************************
591 Can be called from SMBsearch, SMBffirst or SMBfunique.
592 ****************************************************************************/
594 int reply_search(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
605 BOOL finished
= False
;
614 BOOL check_descend
= False
;
615 BOOL expect_close
= False
;
616 BOOL can_open
= True
;
617 BOOL bad_path
= False
;
618 START_PROFILE(SMBsearch
);
620 *mask
= *directory
= *fname
= 0;
622 /* If we were called as SMBffirst then we must expect close. */
623 if(CVAL(inbuf
,smb_com
) == SMBffirst
)
626 outsize
= set_message(outbuf
,1,3,True
);
627 maxentries
= SVAL(inbuf
,smb_vwv0
);
628 dirtype
= SVAL(inbuf
,smb_vwv1
);
629 p
= smb_buf(inbuf
) + 1;
630 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
632 status_len
= SVAL(p
, 0);
635 /* dirtype &= ~aDIR; */
639 SMB_STRUCT_STAT sbuf
;
642 pstrcpy(directory
,path
);
644 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
647 if (!check_name(directory
,conn
))
650 p
= strrchr_m(dir2
,'/');
662 p
= strrchr_m(directory
,'/');
668 if (strlen(directory
) == 0)
669 pstrcpy(directory
,"./");
670 memset((char *)status
,'\0',21);
671 SCVAL(status
,0,(dirtype
& 0x1F));
677 status_dirtype
= CVAL(status
,0) & 0x1F;
678 if (status_dirtype
!= (dirtype
& 0x1F))
679 dirtype
= status_dirtype
;
681 conn
->dirptr
= dptr_fetch(status
+12,&dptr_num
);
684 string_set(&conn
->dirpath
,dptr_path(dptr_num
));
685 fstrcpy(mask
, dptr_wcard(dptr_num
));
690 p
= smb_buf(outbuf
) + 3;
696 dptr_num
= dptr_create(conn
,directory
,True
,expect_close
,SVAL(inbuf
,smb_pid
));
701 set_bad_path_error(errno
, bad_path
);
702 END_PROFILE(SMBsearch
);
703 return (UNIXERROR(ERRDOS
,ERRnofids
));
705 END_PROFILE(SMBsearch
);
706 return ERROR_DOS(ERRDOS
,ERRnofids
);
708 dptr_set_wcard(dptr_num
, strdup(mask
));
711 DEBUG(4,("dptr_num is %d\n",dptr_num
));
715 if ((dirtype
&0x1F) == aVOLID
)
718 make_dir_struct(p
,"???????????",volume_label(SNUM(conn
)),0,aVOLID
,0);
719 dptr_fill(p
+12,dptr_num
);
720 if (dptr_zero(p
+12) && (status_len
==0))
724 p
+= DIR_STRUCT_SIZE
;
728 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
729 conn
->dirpath
,lp_dontdescend(SNUM(conn
))));
730 if (in_list(conn
->dirpath
, lp_dontdescend(SNUM(conn
)),True
))
731 check_descend
= True
;
733 for (i
=numentries
;(i
<maxentries
) && !finished
;i
++)
736 !get_dir_entry(conn
,mask
,dirtype
,fname
,&size
,&mode
,&date
,check_descend
);
740 make_dir_struct(p
,mask
,fname
,size
,mode
,date
);
741 dptr_fill(p
+12,dptr_num
);
744 p
+= DIR_STRUCT_SIZE
;
753 if (numentries
== 0 || !ok
)
755 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
756 SSVAL(outbuf
,smb_err
,ERRnofiles
);
757 dptr_close(&dptr_num
);
760 /* If we were called as SMBffirst with smb_search_id == NULL
761 and no entries were found then return error and close dirptr
764 if(ok
&& expect_close
&& numentries
== 0 && status_len
== 0)
766 SCVAL(outbuf
,smb_rcls
,ERRDOS
);
767 SSVAL(outbuf
,smb_err
,ERRnofiles
);
768 /* Also close the dptr - we know it's gone */
769 dptr_close(&dptr_num
);
772 /* If we were called as SMBfunique, then we can close the dirptr now ! */
773 if(dptr_num
>= 0 && CVAL(inbuf
,smb_com
) == SMBfunique
)
774 dptr_close(&dptr_num
);
776 SSVAL(outbuf
,smb_vwv0
,numentries
);
777 SSVAL(outbuf
,smb_vwv1
,3 + numentries
* DIR_STRUCT_SIZE
);
778 SCVAL(smb_buf(outbuf
),0,5);
779 SSVAL(smb_buf(outbuf
),1,numentries
*DIR_STRUCT_SIZE
);
781 if (Protocol
>= PROTOCOL_NT1
)
782 SSVAL(outbuf
,smb_flg2
,SVAL(outbuf
, smb_flg2
) | FLAGS2_IS_LONG_NAME
);
784 outsize
+= DIR_STRUCT_SIZE
*numentries
;
785 smb_setlen(outbuf
,outsize
- 4);
787 if ((! *directory
) && dptr_path(dptr_num
))
788 slprintf(directory
, sizeof(directory
)-1, "(%s)",dptr_path(dptr_num
));
790 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
791 smb_fn_name(CVAL(inbuf
,smb_com
)),
792 mask
, directory
, dirtype
, numentries
, maxentries
) );
794 END_PROFILE(SMBsearch
);
798 /****************************************************************************
799 Reply to a fclose (stop directory search).
800 ****************************************************************************/
802 int reply_fclose(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
811 START_PROFILE(SMBfclose
);
813 outsize
= set_message(outbuf
,1,0,True
);
814 p
= smb_buf(inbuf
) + 1;
815 p
+= srvstr_pull_buf(inbuf
, path
, p
, sizeof(path
), STR_TERMINATE
);
817 status_len
= SVAL(p
,0);
820 if (status_len
== 0) {
821 END_PROFILE(SMBfclose
);
822 return ERROR_DOS(ERRSRV
,ERRsrverror
);
827 if(dptr_fetch(status
+12,&dptr_num
)) {
828 /* Close the dptr - we know it's gone */
829 dptr_close(&dptr_num
);
832 SSVAL(outbuf
,smb_vwv0
,0);
834 DEBUG(3,("search close\n"));
836 END_PROFILE(SMBfclose
);
840 /****************************************************************************
842 ****************************************************************************/
844 int reply_open(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
854 SMB_STRUCT_STAT sbuf
;
855 BOOL bad_path
= False
;
857 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
858 START_PROFILE(SMBopen
);
860 share_mode
= SVAL(inbuf
,smb_vwv0
);
862 srvstr_pull_buf(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), STR_TERMINATE
);
864 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
866 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
868 unixmode
= unix_mode(conn
,aARCH
,fname
);
870 fsp
= open_file_shared(conn
,fname
,&sbuf
,share_mode
,(FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),
871 unixmode
, oplock_request
,&rmode
,NULL
);
875 set_bad_path_error(errno
, bad_path
);
876 END_PROFILE(SMBopen
);
877 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
881 fmode
= dos_mode(conn
,fname
,&sbuf
);
882 mtime
= sbuf
.st_mtime
;
885 DEBUG(3,("attempt to open a directory %s\n",fname
));
886 close_file(fsp
,False
);
887 END_PROFILE(SMBopen
);
888 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
891 outsize
= set_message(outbuf
,7,0,True
);
892 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
893 SSVAL(outbuf
,smb_vwv1
,fmode
);
894 if(lp_dos_filetime_resolution(SNUM(conn
)) )
895 put_dos_date3(outbuf
,smb_vwv2
,mtime
& ~1);
897 put_dos_date3(outbuf
,smb_vwv2
,mtime
);
898 SIVAL(outbuf
,smb_vwv4
,(uint32
)size
);
899 SSVAL(outbuf
,smb_vwv6
,rmode
);
901 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
902 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
905 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
906 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
907 END_PROFILE(SMBopen
);
911 /****************************************************************************
912 Reply to an open and X.
913 ****************************************************************************/
915 int reply_open_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
918 int smb_mode
= SVAL(inbuf
,smb_vwv3
);
919 int smb_attr
= SVAL(inbuf
,smb_vwv5
);
920 /* Breakout the oplock request bits so we can set the
921 reply bits separately. */
922 BOOL ex_oplock_request
= EXTENDED_OPLOCK_REQUEST(inbuf
);
923 BOOL core_oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
924 BOOL oplock_request
= ex_oplock_request
| core_oplock_request
;
926 int open_flags
= SVAL(inbuf
,smb_vwv2
);
927 int smb_sattr
= SVAL(inbuf
,smb_vwv4
);
928 uint32 smb_time
= make_unix_date3(inbuf
+smb_vwv6
);
930 int smb_ofun
= SVAL(inbuf
,smb_vwv8
);
933 int fmode
=0,mtime
=0,rmode
=0;
934 SMB_STRUCT_STAT sbuf
;
936 BOOL bad_path
= False
;
938 START_PROFILE(SMBopenX
);
940 /* If it's an IPC, pass off the pipe handler. */
942 if (lp_nt_pipe_support()) {
943 END_PROFILE(SMBopenX
);
944 return reply_open_pipe_and_X(conn
, inbuf
,outbuf
,length
,bufsize
);
946 END_PROFILE(SMBopenX
);
947 return ERROR_DOS(ERRSRV
,ERRaccess
);
951 /* XXXX we need to handle passed times, sattr and flags */
952 srvstr_pull_buf(inbuf
, fname
, smb_buf(inbuf
), sizeof(fname
), STR_TERMINATE
);
954 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
956 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
958 unixmode
= unix_mode(conn
,smb_attr
| aARCH
, fname
);
960 fsp
= open_file_shared(conn
,fname
,&sbuf
,smb_mode
,smb_ofun
,unixmode
,
961 oplock_request
, &rmode
,&smb_action
);
965 set_bad_path_error(errno
, bad_path
);
966 END_PROFILE(SMBopenX
);
967 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
971 fmode
= dos_mode(conn
,fname
,&sbuf
);
972 mtime
= sbuf
.st_mtime
;
974 close_file(fsp
,False
);
975 END_PROFILE(SMBopenX
);
976 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
979 /* If the caller set the extended oplock request bit
980 and we granted one (by whatever means) - set the
981 correct bit for extended oplock reply.
984 if (ex_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
985 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
988 if(ex_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
989 smb_action
|= EXTENDED_OPLOCK_GRANTED
;
992 /* If the caller set the core oplock request bit
993 and we granted one (by whatever means) - set the
994 correct bit for core oplock reply.
997 if (core_oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
998 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1001 if(core_oplock_request
&& EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
1002 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1005 set_message(outbuf
,15,0,True
);
1006 SSVAL(outbuf
,smb_vwv2
,fsp
->fnum
);
1007 SSVAL(outbuf
,smb_vwv3
,fmode
);
1008 if(lp_dos_filetime_resolution(SNUM(conn
)) )
1009 put_dos_date3(outbuf
,smb_vwv4
,mtime
& ~1);
1011 put_dos_date3(outbuf
,smb_vwv4
,mtime
);
1012 SIVAL(outbuf
,smb_vwv6
,(uint32
)size
);
1013 SSVAL(outbuf
,smb_vwv8
,rmode
);
1014 SSVAL(outbuf
,smb_vwv11
,smb_action
);
1016 END_PROFILE(SMBopenX
);
1017 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1020 /****************************************************************************
1021 Reply to a SMBulogoffX.
1022 ****************************************************************************/
1024 int reply_ulogoffX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1026 uint16 vuid
= SVAL(inbuf
,smb_uid
);
1027 user_struct
*vuser
= get_valid_user_struct(vuid
);
1028 START_PROFILE(SMBulogoffX
);
1031 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid
));
1034 /* in user level security we are supposed to close any files
1035 open by this user */
1036 if ((vuser
!= 0) && (lp_security() != SEC_SHARE
)) {
1037 file_close_user(vuid
);
1040 invalidate_vuid(vuid
);
1042 set_message(outbuf
,2,0,True
);
1044 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid
) );
1046 END_PROFILE(SMBulogoffX
);
1047 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
1050 /****************************************************************************
1051 Reply to a mknew or a create.
1052 ****************************************************************************/
1054 int reply_mknew(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1062 BOOL bad_path
= False
;
1064 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1065 SMB_STRUCT_STAT sbuf
;
1066 START_PROFILE(SMBcreate
);
1068 com
= SVAL(inbuf
,smb_com
);
1070 createmode
= SVAL(inbuf
,smb_vwv0
);
1071 srvstr_pull_buf(inbuf
, fname
, smb_buf(inbuf
) + 1, sizeof(fname
), STR_TERMINATE
);
1073 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1075 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1077 if (createmode
& aVOLID
) {
1078 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname
));
1081 unixmode
= unix_mode(conn
,createmode
,fname
);
1085 /* We should fail if file exists. */
1086 ofun
= FILE_CREATE_IF_NOT_EXIST
;
1090 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1091 ofun
= FILE_CREATE_IF_NOT_EXIST
|FILE_EXISTS_TRUNCATE
;
1094 /* Open file in dos compatibility share mode. */
1095 fsp
= open_file_shared(conn
,fname
,&sbuf
,SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1096 ofun
, unixmode
, oplock_request
, NULL
, NULL
);
1100 set_bad_path_error(errno
, bad_path
);
1101 END_PROFILE(SMBcreate
);
1102 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1105 outsize
= set_message(outbuf
,1,0,True
);
1106 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1108 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1109 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1112 if(EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1113 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1115 DEBUG( 2, ( "new file %s\n", fname
) );
1116 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1117 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1119 END_PROFILE(SMBcreate
);
1123 /****************************************************************************
1124 Reply to a create temporary file.
1125 ****************************************************************************/
1127 int reply_ctemp(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
1133 BOOL bad_path
= False
;
1135 int oplock_request
= CORE_OPLOCK_REQUEST(inbuf
);
1137 SMB_STRUCT_STAT sbuf
;
1140 START_PROFILE(SMBctemp
);
1142 createmode
= SVAL(inbuf
,smb_vwv0
);
1143 srvstr_pull_buf(inbuf
, fname
, smb_buf(inbuf
)+1, sizeof(fname
), STR_TERMINATE
);
1144 pstrcat(fname
,"\\TMXXXXXX");
1146 RESOLVE_DFSPATH(fname
, conn
, inbuf
, outbuf
);
1148 unix_convert(fname
,conn
,0,&bad_path
,&sbuf
);
1150 unixmode
= unix_mode(conn
,createmode
,fname
);
1152 tmpfd
= smb_mkstemp(fname
);
1154 END_PROFILE(SMBctemp
);
1155 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1158 vfs_stat(conn
,fname
,&sbuf
);
1160 /* Open file in dos compatibility share mode. */
1161 /* We should fail if file does not exist. */
1162 fsp
= open_file_shared(conn
,fname
,&sbuf
,
1163 SET_DENY_MODE(DENY_FCB
)|SET_OPEN_MODE(DOS_OPEN_FCB
),
1164 FILE_EXISTS_OPEN
|FILE_FAIL_IF_NOT_EXIST
,
1165 unixmode
, oplock_request
, NULL
, NULL
);
1167 /* close fd from smb_mkstemp() */
1171 set_bad_path_error(errno
, bad_path
);
1172 END_PROFILE(SMBctemp
);
1173 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1176 outsize
= set_message(outbuf
,1,0,True
);
1177 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
1179 /* the returned filename is relative to the directory */
1180 s
= strrchr_m(fname
, '/');
1187 p
= smb_buf(outbuf
);
1188 SSVALS(p
, 0, -1); /* what is this? not in spec */
1189 SSVAL(p
, 2, strlen(s
));
1191 p
+= srvstr_push(outbuf
, p
, s
, -1, STR_ASCII
);
1192 outsize
= set_message_end(outbuf
, p
);
1194 if (oplock_request
&& lp_fake_oplocks(SNUM(conn
))) {
1195 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1198 if (EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
))
1199 SCVAL(outbuf
,smb_flg
,CVAL(outbuf
,smb_flg
)|CORE_OPLOCK_GRANTED
);
1201 DEBUG( 2, ( "created temp file %s\n", fname
) );
1202 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1203 fname
, fsp
->fd
, createmode
, (int)unixmode
) );
1205 END_PROFILE(SMBctemp
);
1209 /*******************************************************************
1210 Check if a user is allowed to rename a file.
1211 ********************************************************************/
1213 static NTSTATUS
can_rename(char *fname
,connection_struct
*conn
, SMB_STRUCT_STAT
*pst
)
1219 if (!CAN_WRITE(conn
))
1220 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1222 if (S_ISDIR(pst
->st_mode
))
1223 return NT_STATUS_OK
;
1225 /* We need a better way to return NT status codes from open... */
1229 fsp
= open_file_shared1(conn
, fname
, pst
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1230 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1233 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1234 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1235 ret
= NT_STATUS_SHARING_VIOLATION
;
1240 close_file(fsp
,False
);
1241 return NT_STATUS_OK
;
1244 /*******************************************************************
1245 Check if a user is allowed to delete a file.
1246 ********************************************************************/
1248 static NTSTATUS
can_delete(char *fname
,connection_struct
*conn
, int dirtype
)
1250 SMB_STRUCT_STAT sbuf
;
1256 if (!CAN_WRITE(conn
))
1257 return NT_STATUS_MEDIA_WRITE_PROTECTED
;
1259 if (conn
->vfs_ops
.lstat(conn
,fname
,&sbuf
) != 0)
1260 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1262 fmode
= dos_mode(conn
,fname
,&sbuf
);
1264 return NT_STATUS_FILE_IS_A_DIRECTORY
;
1265 if (!lp_delete_readonly(SNUM(conn
))) {
1267 return NT_STATUS_CANNOT_DELETE
;
1269 if ((fmode
& ~dirtype
) & (aHIDDEN
| aSYSTEM
))
1270 return NT_STATUS_CANNOT_DELETE
;
1272 /* We need a better way to return NT status codes from open... */
1276 fsp
= open_file_shared1(conn
, fname
, &sbuf
, DELETE_ACCESS
, SET_DENY_MODE(DENY_ALL
),
1277 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
), 0, 0, &access_mode
, &smb_action
);
1280 NTSTATUS ret
= NT_STATUS_ACCESS_DENIED
;
1281 if (unix_ERR_class
== ERRDOS
&& unix_ERR_code
== ERRbadshare
)
1282 ret
= NT_STATUS_SHARING_VIOLATION
;
1287 close_file(fsp
,False
);
1288 return NT_STATUS_OK
;
1291 /****************************************************************************
1292 The guts of the unlink command, split out so it may be called by the NT SMB
1294 ****************************************************************************/
1296 NTSTATUS
unlink_internals(connection_struct
*conn
, int dirtype
, char *name
)
1302 NTSTATUS error
= NT_STATUS_OK
;
1304 BOOL bad_path
= False
;
1306 SMB_STRUCT_STAT sbuf
;
1308 *directory
= *mask
= 0;
1310 rc
= unix_convert(name
,conn
,0,&bad_path
,&sbuf
);
1312 p
= strrchr_m(name
,'/');
1314 pstrcpy(directory
,".");
1318 pstrcpy(directory
,name
);
1323 * We should only check the mangled cache
1324 * here if unix_convert failed. This means
1325 * that the path in 'mask' doesn't exist
1326 * on the file system and so we need to look
1327 * for a possible mangle. This patch from
1328 * Tine Smukavec <valentin.smukavec@hermes.si>.
1331 if (!rc
&& mangle_is_mangled(mask
))
1332 mangle_check_cache( mask
);
1334 has_wild
= ms_has_wild(mask
);
1337 pstrcat(directory
,"/");
1338 pstrcat(directory
,mask
);
1339 error
= can_delete(directory
,conn
,dirtype
);
1340 if (!NT_STATUS_IS_OK(error
)) return error
;
1342 if (vfs_unlink(conn
,directory
) == 0) {
1346 void *dirptr
= NULL
;
1349 if (check_name(directory
,conn
))
1350 dirptr
= OpenDir(conn
, directory
, True
);
1352 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1353 the pattern matches against the long name, otherwise the short name
1354 We don't implement this yet XXXX
1358 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
1360 if (strequal(mask
,"????????.???"))
1363 while ((dname
= ReadDirName(dirptr
))) {
1365 pstrcpy(fname
,dname
);
1367 if(!mask_match(fname
, mask
, case_sensitive
)) continue;
1369 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
1370 error
= can_delete(fname
,conn
,dirtype
);
1371 if (!NT_STATUS_IS_OK(error
)) continue;
1372 if (vfs_unlink(conn
,fname
) == 0) count
++;
1373 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname
));
1379 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
1380 error
= map_nt_error_from_unix(errno
);
1386 /****************************************************************************
1388 ****************************************************************************/
1390 int reply_unlink(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
1397 START_PROFILE(SMBunlink
);
1399 dirtype
= SVAL(inbuf
,smb_vwv0
);
1401 srvstr_pull_buf(inbuf
, name
, smb_buf(inbuf
) + 1, sizeof(name
), STR_TERMINATE
);
1403 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
1405 DEBUG(3,("reply_unlink : %s\n",name
));
1407 status
= unlink_internals(conn
, dirtype
, name
);
1408 if (!NT_STATUS_IS_OK(status
)) return ERROR_NT(status
);
1411 * Win2k needs a changenotify request response before it will
1412 * update after a rename..
1414 process_pending_change_notify_queue((time_t)0);
1416 outsize
= set_message(outbuf
,0,0,True
);
1418 END_PROFILE(SMBunlink
);
1422 /****************************************************************************
1424 ****************************************************************************/
1426 void fail_readraw(void)
1429 slprintf(errstr
, sizeof(errstr
)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1431 exit_server(errstr
);
1434 /****************************************************************************
1435 Use sendfile in readbraw.
1436 ****************************************************************************/
1438 void send_file_readbraw(connection_struct
*conn
, files_struct
*fsp
, SMB_OFF_T startpos
, size_t nread
,
1439 ssize_t mincount
, char *outbuf
)
1443 #if defined(WITH_SENDFILE)
1445 * We can only use sendfile on a non-chained packet and on a file
1446 * that is exclusively oplocked. reply_readbraw has already checked the length.
1449 if ((nread
> 0) && (lp_write_cache_size(SNUM(conn
)) == 0) &&
1450 EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) && lp_use_sendfile(SNUM(conn
)) ) {
1453 _smb_setlen(outbuf
,nread
);
1454 header
.data
= outbuf
;
1458 if ( conn
->vfs_ops
.sendfile( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, nread
) == -1) {
1460 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1461 * return ENOSYS then pretend we just got a normal read.
1463 if (errno
== ENOSYS
)
1466 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1467 fsp
->fsp_name
, strerror(errno
) ));
1468 exit_server("send_file_readbraw sendfile failed");
1477 ret
= read_file(fsp
,outbuf
+4,startpos
,nread
);
1482 _smb_setlen(outbuf
,ret
);
1483 if (write_data(smbd_server_fd(),outbuf
,4+ret
) != 4+ret
)
1487 /****************************************************************************
1488 Reply to a readbraw (core+ protocol).
1489 ****************************************************************************/
1491 int reply_readbraw(connection_struct
*conn
, char *inbuf
, char *outbuf
, int dum_size
, int dum_buffsize
)
1493 ssize_t maxcount
,mincount
;
1496 char *header
= outbuf
;
1498 START_PROFILE(SMBreadbraw
);
1501 * Special check if an oplock break has been issued
1502 * and the readraw request croses on the wire, we must
1503 * return a zero length response here.
1506 if(global_oplock_break
) {
1507 _smb_setlen(header
,0);
1508 if (write_data(smbd_server_fd(),header
,4) != 4)
1510 DEBUG(5,("readbraw - oplock break finished\n"));
1511 END_PROFILE(SMBreadbraw
);
1515 fsp
= file_fsp(inbuf
,smb_vwv0
);
1517 if (!FNUM_OK(fsp
,conn
) || !fsp
->can_read
) {
1519 * fsp could be NULL here so use the value from the packet. JRA.
1521 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf
,smb_vwv0
)));
1522 _smb_setlen(header
,0);
1523 if (write_data(smbd_server_fd(),header
,4) != 4)
1525 END_PROFILE(SMBreadbraw
);
1529 CHECK_FSP(fsp
,conn
);
1531 flush_write_cache(fsp
, READRAW_FLUSH
);
1533 startpos
= IVAL(inbuf
,smb_vwv1
);
1534 if(CVAL(inbuf
,smb_wct
) == 10) {
1536 * This is a large offset (64 bit) read.
1538 #ifdef LARGE_SMB_OFF_T
1540 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv8
)) << 32);
1542 #else /* !LARGE_SMB_OFF_T */
1545 * Ensure we haven't been sent a >32 bit offset.
1548 if(IVAL(inbuf
,smb_vwv8
) != 0) {
1549 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1550 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv8
) ));
1551 _smb_setlen(header
,0);
1552 if (write_data(smbd_server_fd(),header
,4) != 4)
1554 END_PROFILE(SMBreadbraw
);
1558 #endif /* LARGE_SMB_OFF_T */
1561 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos
));
1562 _smb_setlen(header
,0);
1563 if (write_data(smbd_server_fd(),header
,4) != 4)
1565 END_PROFILE(SMBreadbraw
);
1569 maxcount
= (SVAL(inbuf
,smb_vwv3
) & 0xFFFF);
1570 mincount
= (SVAL(inbuf
,smb_vwv4
) & 0xFFFF);
1572 /* ensure we don't overrun the packet size */
1573 maxcount
= MIN(65535,maxcount
);
1574 maxcount
= MAX(mincount
,maxcount
);
1576 if (!is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1577 SMB_OFF_T size
= fsp
->size
;
1578 SMB_OFF_T sizeneeded
= startpos
+ maxcount
;
1580 if (size
< sizeneeded
) {
1582 if (vfs_fstat(fsp
,fsp
->fd
,&st
) == 0)
1584 if (!fsp
->can_write
)
1588 if (startpos
>= size
)
1591 nread
= MIN(maxcount
,(size
- startpos
));
1594 if (nread
< mincount
)
1597 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp
->fnum
, (double)startpos
,
1598 (int)maxcount
, (int)mincount
, (int)nread
) );
1600 send_file_readbraw(conn
, fsp
, startpos
, nread
, mincount
, outbuf
);
1602 DEBUG(5,("readbraw finished\n"));
1603 END_PROFILE(SMBreadbraw
);
1607 /****************************************************************************
1608 Reply to a lockread (core+ protocol).
1609 ****************************************************************************/
1611 int reply_lockread(connection_struct
*conn
, char *inbuf
,char *outbuf
, int length
, int dum_buffsiz
)
1619 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1620 START_PROFILE(SMBlockread
);
1622 CHECK_FSP(fsp
,conn
);
1625 release_level_2_oplocks_on_change(fsp
);
1627 numtoread
= SVAL(inbuf
,smb_vwv1
);
1628 startpos
= IVAL(inbuf
,smb_vwv2
);
1630 outsize
= set_message(outbuf
,5,3,True
);
1631 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1632 data
= smb_buf(outbuf
) + 3;
1635 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1636 * protocol request that predates the read/write lock concept.
1637 * Thus instead of asking for a read lock here we need to ask
1638 * for a write lock. JRA.
1641 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
),
1642 (SMB_BIG_UINT
)numtoread
, (SMB_BIG_UINT
)startpos
, WRITE_LOCK
);
1644 if (NT_STATUS_V(status
)) {
1645 if (lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
1647 * A blocking lock was requested. Package up
1648 * this smb into a queued request and push it
1649 * onto the blocking lock queue.
1651 if(push_blocking_lock_request(inbuf
, length
, -1, 0)) {
1652 END_PROFILE(SMBlockread
);
1656 END_PROFILE(SMBlockread
);
1657 return ERROR_NT(status
);
1660 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1663 END_PROFILE(SMBlockread
);
1664 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1668 SSVAL(outbuf
,smb_vwv0
,nread
);
1669 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1670 SSVAL(smb_buf(outbuf
),1,nread
);
1672 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1673 fsp
->fnum
, (int)numtoread
, (int)nread
));
1675 END_PROFILE(SMBlockread
);
1679 /****************************************************************************
1681 ****************************************************************************/
1683 int reply_read(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
1690 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1691 START_PROFILE(SMBread
);
1693 CHECK_FSP(fsp
,conn
);
1696 numtoread
= SVAL(inbuf
,smb_vwv1
);
1697 startpos
= IVAL(inbuf
,smb_vwv2
);
1699 outsize
= set_message(outbuf
,5,3,True
);
1700 numtoread
= MIN(BUFFER_SIZE
-outsize
,numtoread
);
1701 data
= smb_buf(outbuf
) + 3;
1703 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtoread
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1704 END_PROFILE(SMBread
);
1705 return ERROR_DOS(ERRDOS
,ERRlock
);
1709 nread
= read_file(fsp
,data
,startpos
,numtoread
);
1712 END_PROFILE(SMBread
);
1713 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1717 SSVAL(outbuf
,smb_vwv0
,nread
);
1718 SSVAL(outbuf
,smb_vwv5
,nread
+3);
1719 SCVAL(smb_buf(outbuf
),0,1);
1720 SSVAL(smb_buf(outbuf
),1,nread
);
1722 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1723 fsp
->fnum
, (int)numtoread
, (int)nread
) );
1725 END_PROFILE(SMBread
);
1729 /****************************************************************************
1730 Reply to a read and X - possibly using sendfile.
1731 ****************************************************************************/
1733 int send_file_readX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,
1734 files_struct
*fsp
, SMB_OFF_T startpos
, size_t smb_maxcnt
)
1737 char *data
= smb_buf(outbuf
);
1739 #if defined(WITH_SENDFILE)
1741 * We can only use sendfile on a non-chained packet and on a file
1742 * that is exclusively oplocked.
1745 if ((CVAL(inbuf
,smb_vwv0
) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
) &&
1746 lp_use_sendfile(SNUM(conn
)) && (lp_write_cache_size(SNUM(conn
)) == 0) ) {
1747 SMB_STRUCT_STAT sbuf
;
1750 if(vfs_fstat(fsp
,fsp
->fd
, &sbuf
) == -1)
1751 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1753 if (startpos
> sbuf
.st_size
)
1756 if (smb_maxcnt
> (sbuf
.st_size
- startpos
))
1757 smb_maxcnt
= (sbuf
.st_size
- startpos
);
1759 if (smb_maxcnt
== 0)
1763 * Set up the packet header before send. We
1764 * assume here the sendfile will work (get the
1765 * correct amount of data).
1768 SSVAL(outbuf
,smb_vwv5
,smb_maxcnt
);
1769 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
1770 SSVAL(smb_buf(outbuf
),-2,smb_maxcnt
);
1771 SCVAL(outbuf
,smb_vwv0
,0xFF);
1772 set_message(outbuf
,12,smb_maxcnt
,False
);
1773 header
.data
= outbuf
;
1774 header
.length
= data
- outbuf
;
1777 if ( conn
->vfs_ops
.sendfile( smbd_server_fd(), fsp
, fsp
->fd
, &header
, startpos
, smb_maxcnt
) == -1) {
1779 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1780 * return ENOSYS then pretend we just got a normal read.
1782 if (errno
== ENOSYS
)
1785 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1786 fsp
->fsp_name
, strerror(errno
) ));
1787 exit_server("send_file_readX sendfile failed");
1790 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1791 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
1799 nread
= read_file(fsp
,data
,startpos
,smb_maxcnt
);
1802 END_PROFILE(SMBreadX
);
1803 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
1806 SSVAL(outbuf
,smb_vwv5
,nread
);
1807 SSVAL(outbuf
,smb_vwv6
,smb_offset(data
,outbuf
));
1808 SSVAL(smb_buf(outbuf
),-2,nread
);
1810 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1811 fsp
->fnum
, (int)smb_maxcnt
, (int)nread
) );
1816 /****************************************************************************
1817 Reply to a read and X.
1818 ****************************************************************************/
1820 int reply_read_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
1822 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
1823 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
1825 size_t smb_maxcnt
= SVAL(inbuf
,smb_vwv5
);
1827 size_t smb_mincnt
= SVAL(inbuf
,smb_vwv6
);
1830 START_PROFILE(SMBreadX
);
1832 /* If it's an IPC, pass off the pipe handler. */
1834 END_PROFILE(SMBreadX
);
1835 return reply_pipe_read_and_X(inbuf
,outbuf
,length
,bufsize
);
1838 CHECK_FSP(fsp
,conn
);
1841 set_message(outbuf
,12,0,True
);
1843 if(CVAL(inbuf
,smb_wct
) == 12) {
1844 #ifdef LARGE_SMB_OFF_T
1846 * This is a large offset (64 bit) read.
1848 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv10
)) << 32);
1850 #else /* !LARGE_SMB_OFF_T */
1853 * Ensure we haven't been sent a >32 bit offset.
1856 if(IVAL(inbuf
,smb_vwv10
) != 0) {
1857 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1858 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv10
) ));
1859 END_PROFILE(SMBreadX
);
1860 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
1863 #endif /* LARGE_SMB_OFF_T */
1867 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)smb_maxcnt
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
1868 END_PROFILE(SMBreadX
);
1869 return ERROR_DOS(ERRDOS
,ERRlock
);
1872 nread
= send_file_readX(conn
, inbuf
, outbuf
, length
, fsp
, startpos
, smb_maxcnt
);
1874 nread
= chain_reply(inbuf
,outbuf
,length
,bufsize
);
1876 END_PROFILE(SMBreadX
);
1880 /****************************************************************************
1881 Reply to a writebraw (core+ or LANMAN1.0 protocol).
1882 ****************************************************************************/
1884 int reply_writebraw(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
1887 ssize_t total_written
=0;
1888 size_t numtowrite
=0;
1893 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
1895 START_PROFILE(SMBwritebraw
);
1897 CHECK_FSP(fsp
,conn
);
1900 tcount
= IVAL(inbuf
,smb_vwv1
);
1901 startpos
= IVAL(inbuf
,smb_vwv3
);
1902 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
1904 /* We have to deal with slightly different formats depending
1905 on whether we are using the core+ or lanman1.0 protocol */
1907 if(Protocol
<= PROTOCOL_COREPLUS
) {
1908 numtowrite
= SVAL(smb_buf(inbuf
),-2);
1909 data
= smb_buf(inbuf
);
1911 numtowrite
= SVAL(inbuf
,smb_vwv10
);
1912 data
= smb_base(inbuf
) + SVAL(inbuf
, smb_vwv11
);
1915 /* force the error type */
1916 SCVAL(inbuf
,smb_com
,SMBwritec
);
1917 SCVAL(outbuf
,smb_com
,SMBwritec
);
1919 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
1920 END_PROFILE(SMBwritebraw
);
1921 return(ERROR_DOS(ERRDOS
,ERRlock
));
1925 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
1927 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1928 fsp
->fnum
, (double)startpos
, (int)numtowrite
, (int)nwritten
, (int)write_through
));
1930 if (nwritten
< numtowrite
) {
1931 END_PROFILE(SMBwritebraw
);
1932 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
1935 total_written
= nwritten
;
1937 /* Return a message to the redirector to tell it to send more bytes */
1938 SCVAL(outbuf
,smb_com
,SMBwritebraw
);
1939 SSVALS(outbuf
,smb_vwv0
,-1);
1940 outsize
= set_message(outbuf
,Protocol
>PROTOCOL_COREPLUS
?1:0,0,True
);
1941 if (!send_smb(smbd_server_fd(),outbuf
))
1942 exit_server("reply_writebraw: send_smb failed.");
1944 /* Now read the raw data into the buffer and write it */
1945 if (read_smb_length(smbd_server_fd(),inbuf
,SMB_SECONDARY_WAIT
) == -1) {
1946 exit_server("secondary writebraw failed");
1949 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1950 numtowrite
= smb_len(inbuf
);
1952 /* Set up outbuf to return the correct return */
1953 outsize
= set_message(outbuf
,1,0,True
);
1954 SCVAL(outbuf
,smb_com
,SMBwritec
);
1955 SSVAL(outbuf
,smb_vwv0
,total_written
);
1957 if (numtowrite
!= 0) {
1959 if (numtowrite
> BUFFER_SIZE
) {
1960 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1961 (unsigned int)numtowrite
));
1962 exit_server("secondary writebraw failed");
1965 if (tcount
> nwritten
+numtowrite
) {
1966 DEBUG(3,("Client overestimated the write %d %d %d\n",
1967 (int)tcount
,(int)nwritten
,(int)numtowrite
));
1970 if (read_data( smbd_server_fd(), inbuf
+4, numtowrite
) != numtowrite
) {
1971 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1973 exit_server("secondary writebraw failed");
1976 nwritten
= write_file(fsp
,inbuf
+4,startpos
+nwritten
,numtowrite
);
1978 if (nwritten
< (ssize_t
)numtowrite
) {
1979 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
1980 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
1984 total_written
+= nwritten
;
1987 if ((lp_syncalways(SNUM(conn
)) || write_through
) && lp_strict_sync(SNUM(conn
)))
1988 sync_file(conn
,fsp
);
1990 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1991 fsp
->fnum
, (double)startpos
, (int)numtowrite
,(int)total_written
));
1993 /* we won't return a status if write through is not selected - this follows what WfWg does */
1994 END_PROFILE(SMBwritebraw
);
1995 if (!write_through
&& total_written
==tcount
) {
1997 #if RABBIT_PELLET_FIX
1999 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2000 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2002 if (!send_keepalive(smbd_server_fd()))
2003 exit_server("reply_writebraw: send of keepalive failed");
2011 /****************************************************************************
2012 Reply to a writeunlock (core+).
2013 ****************************************************************************/
2015 int reply_writeunlock(connection_struct
*conn
, char *inbuf
,char *outbuf
,
2016 int size
, int dum_buffsize
)
2018 ssize_t nwritten
= -1;
2023 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2025 START_PROFILE(SMBwriteunlock
);
2027 CHECK_FSP(fsp
,conn
);
2030 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2031 startpos
= IVAL(inbuf
,smb_vwv2
);
2032 data
= smb_buf(inbuf
) + 3;
2034 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
,
2035 WRITE_LOCK
,False
)) {
2036 END_PROFILE(SMBwriteunlock
);
2037 return ERROR_DOS(ERRDOS
,ERRlock
);
2040 /* The special X/Open SMB protocol handling of
2041 zero length writes is *NOT* done for
2046 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2048 if (lp_syncalways(SNUM(conn
)))
2049 sync_file(conn
,fsp
);
2051 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2052 END_PROFILE(SMBwriteunlock
);
2053 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2056 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), (SMB_BIG_UINT
)numtowrite
,
2057 (SMB_BIG_UINT
)startpos
);
2058 if (NT_STATUS_V(status
)) {
2059 END_PROFILE(SMBwriteunlock
);
2060 return ERROR_NT(status
);
2063 outsize
= set_message(outbuf
,1,0,True
);
2065 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2067 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2068 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2070 END_PROFILE(SMBwriteunlock
);
2074 /****************************************************************************
2076 ****************************************************************************/
2078 int reply_write(connection_struct
*conn
, char *inbuf
,char *outbuf
,int size
,int dum_buffsize
)
2081 ssize_t nwritten
= -1;
2084 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2086 START_PROFILE(SMBwrite
);
2088 /* If it's an IPC, pass off the pipe handler. */
2090 END_PROFILE(SMBwrite
);
2091 return reply_pipe_write(inbuf
,outbuf
,size
,dum_buffsize
);
2094 CHECK_FSP(fsp
,conn
);
2097 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2098 startpos
= IVAL(inbuf
,smb_vwv2
);
2099 data
= smb_buf(inbuf
) + 3;
2101 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2102 END_PROFILE(SMBwrite
);
2103 return ERROR_DOS(ERRDOS
,ERRlock
);
2107 * X/Open SMB protocol says that if smb_vwv1 is
2108 * zero then the file size should be extended or
2109 * truncated to the size given in smb_vwv[2-3].
2112 if(numtowrite
== 0) {
2114 * This is actually an allocate call, and set EOF. JRA.
2116 nwritten
= vfs_allocate_file_space(fsp
, (SMB_OFF_T
)startpos
);
2118 END_PROFILE(SMBwrite
);
2119 return ERROR_NT(NT_STATUS_DISK_FULL
);
2121 nwritten
= vfs_set_filelen(fsp
, (SMB_OFF_T
)startpos
);
2123 END_PROFILE(SMBwrite
);
2124 return ERROR_NT(NT_STATUS_DISK_FULL
);
2127 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2129 if (lp_syncalways(SNUM(conn
)))
2130 sync_file(conn
,fsp
);
2132 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2133 END_PROFILE(SMBwrite
);
2134 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2137 outsize
= set_message(outbuf
,1,0,True
);
2139 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2141 if (nwritten
< (ssize_t
)numtowrite
) {
2142 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2143 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2146 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2148 END_PROFILE(SMBwrite
);
2152 /****************************************************************************
2153 Reply to a write and X.
2154 ****************************************************************************/
2156 int reply_write_and_X(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
2158 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
2159 SMB_OFF_T startpos
= IVAL(inbuf
,smb_vwv3
);
2160 size_t numtowrite
= SVAL(inbuf
,smb_vwv10
);
2161 BOOL write_through
= BITSETW(inbuf
+smb_vwv7
,0);
2162 ssize_t nwritten
= -1;
2163 unsigned int smb_doff
= SVAL(inbuf
,smb_vwv11
);
2164 unsigned int smblen
= smb_len(inbuf
);
2166 BOOL large_writeX
= ((CVAL(inbuf
,smb_wct
) == 14) && (smblen
> 0xFFFF));
2167 START_PROFILE(SMBwriteX
);
2169 /* If it's an IPC, pass off the pipe handler. */
2171 END_PROFILE(SMBwriteX
);
2172 return reply_pipe_write_and_X(inbuf
,outbuf
,length
,bufsize
);
2175 CHECK_FSP(fsp
,conn
);
2178 /* Deal with possible LARGE_WRITEX */
2180 numtowrite
|= ((((size_t)SVAL(inbuf
,smb_vwv9
)) & 1 )<<16);
2182 if(smb_doff
> smblen
|| (smb_doff
+ numtowrite
> smblen
)) {
2183 END_PROFILE(SMBwriteX
);
2184 return ERROR_DOS(ERRDOS
,ERRbadmem
);
2187 data
= smb_base(inbuf
) + smb_doff
;
2189 if(CVAL(inbuf
,smb_wct
) == 14) {
2190 #ifdef LARGE_SMB_OFF_T
2192 * This is a large offset (64 bit) write.
2194 startpos
|= (((SMB_OFF_T
)IVAL(inbuf
,smb_vwv12
)) << 32);
2196 #else /* !LARGE_SMB_OFF_T */
2199 * Ensure we haven't been sent a >32 bit offset.
2202 if(IVAL(inbuf
,smb_vwv12
) != 0) {
2203 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2204 64 bit offsets.\n", (unsigned int)IVAL(inbuf
,smb_vwv12
) ));
2205 END_PROFILE(SMBwriteX
);
2206 return ERROR_DOS(ERRDOS
,ERRbadaccess
);
2209 #endif /* LARGE_SMB_OFF_T */
2212 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2213 END_PROFILE(SMBwriteX
);
2214 return ERROR_DOS(ERRDOS
,ERRlock
);
2217 /* X/Open SMB protocol says that, unlike SMBwrite
2218 if the length is zero then NO truncation is
2219 done, just a write of zero. To truncate a file,
2224 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2226 if(((nwritten
== 0) && (numtowrite
!= 0))||(nwritten
< 0)) {
2227 END_PROFILE(SMBwriteX
);
2228 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2231 set_message(outbuf
,6,0,True
);
2233 SSVAL(outbuf
,smb_vwv2
,nwritten
);
2235 SSVAL(outbuf
,smb_vwv4
,(nwritten
>>16)&1);
2237 if (nwritten
< (ssize_t
)numtowrite
) {
2238 SCVAL(outbuf
,smb_rcls
,ERRHRD
);
2239 SSVAL(outbuf
,smb_err
,ERRdiskfull
);
2242 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2243 fsp
->fnum
, (int)numtowrite
, (int)nwritten
));
2245 if (lp_syncalways(SNUM(conn
)) || write_through
)
2246 sync_file(conn
,fsp
);
2248 END_PROFILE(SMBwriteX
);
2249 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
2252 /****************************************************************************
2254 ****************************************************************************/
2256 int reply_lseek(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2262 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2263 START_PROFILE(SMBlseek
);
2265 CHECK_FSP(fsp
,conn
);
2267 flush_write_cache(fsp
, SEEK_FLUSH
);
2269 mode
= SVAL(inbuf
,smb_vwv1
) & 3;
2270 startpos
= IVALS(inbuf
,smb_vwv2
);
2273 case 0: umode
= SEEK_SET
; break;
2274 case 1: umode
= SEEK_CUR
; break;
2275 case 2: umode
= SEEK_END
; break;
2277 umode
= SEEK_SET
; break;
2280 if((res
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,startpos
,umode
)) == -1) {
2282 * Check for the special case where a seek before the start
2283 * of the file sets the offset to zero. Added in the CIFS spec,
2287 if(errno
== EINVAL
) {
2288 SMB_OFF_T current_pos
= startpos
;
2290 if(umode
== SEEK_CUR
) {
2292 if((current_pos
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,0,SEEK_CUR
)) == -1) {
2293 END_PROFILE(SMBlseek
);
2294 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2297 current_pos
+= startpos
;
2299 } else if (umode
== SEEK_END
) {
2301 SMB_STRUCT_STAT sbuf
;
2303 if(vfs_fstat(fsp
,fsp
->fd
, &sbuf
) == -1) {
2304 END_PROFILE(SMBlseek
);
2305 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2308 current_pos
+= sbuf
.st_size
;
2312 res
= conn
->vfs_ops
.lseek(fsp
,fsp
->fd
,0,SEEK_SET
);
2316 END_PROFILE(SMBlseek
);
2317 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2323 outsize
= set_message(outbuf
,2,0,True
);
2324 SIVAL(outbuf
,smb_vwv0
,res
);
2326 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2327 fsp
->fnum
, (double)startpos
, (double)res
, mode
));
2329 END_PROFILE(SMBlseek
);
2333 /****************************************************************************
2335 ****************************************************************************/
2337 int reply_flush(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2339 int outsize
= set_message(outbuf
,0,0,True
);
2340 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2341 START_PROFILE(SMBflush
);
2343 CHECK_FSP(fsp
,conn
);
2346 file_sync_all(conn
);
2348 sync_file(conn
,fsp
);
2351 DEBUG(3,("flush\n"));
2352 END_PROFILE(SMBflush
);
2356 /****************************************************************************
2358 ****************************************************************************/
2360 int reply_exit(connection_struct
*conn
,
2361 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2364 START_PROFILE(SMBexit
);
2365 outsize
= set_message(outbuf
,0,0,True
);
2367 DEBUG(3,("exit\n"));
2369 END_PROFILE(SMBexit
);
2373 /****************************************************************************
2374 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2375 ****************************************************************************/
2377 int reply_close(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2382 int32 eclass
= 0, err
= 0;
2383 files_struct
*fsp
= NULL
;
2384 START_PROFILE(SMBclose
);
2386 outsize
= set_message(outbuf
,0,0,True
);
2388 /* If it's an IPC, pass off to the pipe handler. */
2390 END_PROFILE(SMBclose
);
2391 return reply_pipe_close(conn
, inbuf
,outbuf
);
2394 fsp
= file_fsp(inbuf
,smb_vwv0
);
2397 * We can only use CHECK_FSP if we know it's not a directory.
2400 if(!fsp
|| (fsp
->conn
!= conn
)) {
2401 END_PROFILE(SMBclose
);
2402 return ERROR_DOS(ERRDOS
,ERRbadfid
);
2405 if(fsp
->is_directory
) {
2407 * Special case - close NT SMB directory handle.
2409 DEBUG(3,("close %s fnum=%d\n", fsp
->is_directory
? "directory" : "stat file open", fsp
->fnum
));
2410 close_file(fsp
,True
);
2413 * Close ordinary file.
2418 /* Save the name for time set in close. */
2419 pstrcpy( file_name
, fsp
->fsp_name
);
2421 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2423 conn
->num_files_open
));
2426 * close_file() returns the unix errno if an error
2427 * was detected on close - normally this is due to
2428 * a disk full error. If not then it was probably an I/O error.
2431 if((close_err
= close_file(fsp
,True
)) != 0) {
2433 END_PROFILE(SMBclose
);
2434 return (UNIXERROR(ERRHRD
,ERRgeneral
));
2438 * Now take care of any time sent in the close.
2441 mtime
= make_unix_date3(inbuf
+smb_vwv1
);
2443 /* try and set the date */
2444 set_filetime(conn
, file_name
, mtime
);
2448 /* We have a cached error */
2450 END_PROFILE(SMBclose
);
2451 return ERROR_DOS(eclass
,err
);
2454 END_PROFILE(SMBclose
);
2458 /****************************************************************************
2459 Reply to a writeclose (Core+ protocol).
2460 ****************************************************************************/
2462 int reply_writeclose(connection_struct
*conn
,
2463 char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
2466 ssize_t nwritten
= -1;
2472 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2473 START_PROFILE(SMBwriteclose
);
2475 CHECK_FSP(fsp
,conn
);
2478 numtowrite
= SVAL(inbuf
,smb_vwv1
);
2479 startpos
= IVAL(inbuf
,smb_vwv2
);
2480 mtime
= make_unix_date3(inbuf
+smb_vwv4
);
2481 data
= smb_buf(inbuf
) + 1;
2483 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)numtowrite
,(SMB_BIG_UINT
)startpos
, WRITE_LOCK
,False
)) {
2484 END_PROFILE(SMBwriteclose
);
2485 return ERROR_DOS(ERRDOS
,ERRlock
);
2488 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
2490 set_filetime(conn
, fsp
->fsp_name
,mtime
);
2492 close_err
= close_file(fsp
,True
);
2494 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2495 fsp
->fnum
, (int)numtowrite
, (int)nwritten
,
2496 conn
->num_files_open
));
2498 if (nwritten
<= 0) {
2499 END_PROFILE(SMBwriteclose
);
2500 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2503 if(close_err
!= 0) {
2505 END_PROFILE(SMBwriteclose
);
2506 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2509 outsize
= set_message(outbuf
,1,0,True
);
2511 SSVAL(outbuf
,smb_vwv0
,nwritten
);
2512 END_PROFILE(SMBwriteclose
);
2516 /****************************************************************************
2518 ****************************************************************************/
2520 int reply_lock(connection_struct
*conn
,
2521 char *inbuf
,char *outbuf
, int length
, int dum_buffsize
)
2523 int outsize
= set_message(outbuf
,0,0,True
);
2524 SMB_BIG_UINT count
,offset
;
2526 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2527 START_PROFILE(SMBlock
);
2529 CHECK_FSP(fsp
,conn
);
2531 release_level_2_oplocks_on_change(fsp
);
2533 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2534 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2536 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2537 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
));
2539 status
= do_lock_spin(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
, WRITE_LOCK
);
2540 if (NT_STATUS_V(status
)) {
2541 if (lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
2543 * A blocking lock was requested. Package up
2544 * this smb into a queued request and push it
2545 * onto the blocking lock queue.
2547 if(push_blocking_lock_request(inbuf
, length
, -1, 0)) {
2548 END_PROFILE(SMBlock
);
2552 END_PROFILE(SMBlock
);
2553 return ERROR_NT(status
);
2556 END_PROFILE(SMBlock
);
2560 /****************************************************************************
2562 ****************************************************************************/
2564 int reply_unlock(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
,
2567 int outsize
= set_message(outbuf
,0,0,True
);
2568 SMB_BIG_UINT count
,offset
;
2570 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2571 START_PROFILE(SMBunlock
);
2573 CHECK_FSP(fsp
,conn
);
2575 count
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv1
);
2576 offset
= (SMB_BIG_UINT
)IVAL(inbuf
,smb_vwv3
);
2578 status
= do_unlock(fsp
, conn
, SVAL(inbuf
,smb_pid
), count
, offset
);
2579 if (NT_STATUS_V(status
)) {
2580 END_PROFILE(SMBunlock
);
2581 return ERROR_NT(status
);
2584 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2585 fsp
->fd
, fsp
->fnum
, (double)offset
, (double)count
) );
2587 END_PROFILE(SMBunlock
);
2591 /****************************************************************************
2593 ****************************************************************************/
2595 int reply_tdis(connection_struct
*conn
,
2596 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2598 int outsize
= set_message(outbuf
,0,0,True
);
2600 START_PROFILE(SMBtdis
);
2602 vuid
= SVAL(inbuf
,smb_uid
);
2605 DEBUG(4,("Invalid connection in tdis\n"));
2606 END_PROFILE(SMBtdis
);
2607 return ERROR_DOS(ERRSRV
,ERRinvnid
);
2612 close_cnum(conn
,vuid
);
2614 END_PROFILE(SMBtdis
);
2618 /****************************************************************************
2620 ****************************************************************************/
2622 int reply_echo(connection_struct
*conn
,
2623 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2625 int smb_reverb
= SVAL(inbuf
,smb_vwv0
);
2627 unsigned int data_len
= smb_buflen(inbuf
);
2628 int outsize
= set_message(outbuf
,1,data_len
,True
);
2629 START_PROFILE(SMBecho
);
2631 data_len
= MIN(data_len
, (sizeof(inbuf
)-(smb_buf(inbuf
)-inbuf
)));
2633 /* copy any incoming data back out */
2635 memcpy(smb_buf(outbuf
),smb_buf(inbuf
),data_len
);
2637 if (smb_reverb
> 100) {
2638 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb
));
2642 for (seq_num
=1 ; seq_num
<= smb_reverb
; seq_num
++) {
2643 SSVAL(outbuf
,smb_vwv0
,seq_num
);
2645 smb_setlen(outbuf
,outsize
- 4);
2647 if (!send_smb(smbd_server_fd(),outbuf
))
2648 exit_server("reply_echo: send_smb failed.");
2651 DEBUG(3,("echo %d times\n", smb_reverb
));
2655 END_PROFILE(SMBecho
);
2659 /****************************************************************************
2660 Reply to a printopen.
2661 ****************************************************************************/
2663 int reply_printopen(connection_struct
*conn
,
2664 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2668 START_PROFILE(SMBsplopen
);
2670 if (!CAN_PRINT(conn
)) {
2671 END_PROFILE(SMBsplopen
);
2672 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2675 /* Open for exclusive use, write only. */
2676 fsp
= print_fsp_open(conn
, NULL
);
2679 END_PROFILE(SMBsplopen
);
2680 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2683 outsize
= set_message(outbuf
,1,0,True
);
2684 SSVAL(outbuf
,smb_vwv0
,fsp
->fnum
);
2686 DEBUG(3,("openprint fd=%d fnum=%d\n",
2687 fsp
->fd
, fsp
->fnum
));
2689 END_PROFILE(SMBsplopen
);
2693 /****************************************************************************
2694 Reply to a printclose.
2695 ****************************************************************************/
2696 int reply_printclose(connection_struct
*conn
,
2697 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2699 int outsize
= set_message(outbuf
,0,0,True
);
2700 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2702 START_PROFILE(SMBsplclose
);
2704 CHECK_FSP(fsp
,conn
);
2706 if (!CAN_PRINT(conn
)) {
2707 END_PROFILE(SMBsplclose
);
2708 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2711 DEBUG(3,("printclose fd=%d fnum=%d\n",
2712 fsp
->fd
,fsp
->fnum
));
2714 close_err
= close_file(fsp
,True
);
2716 if(close_err
!= 0) {
2718 END_PROFILE(SMBsplclose
);
2719 return(UNIXERROR(ERRHRD
,ERRgeneral
));
2722 END_PROFILE(SMBsplclose
);
2726 /****************************************************************************
2727 Reply to a printqueue.
2728 ****************************************************************************/
2730 int reply_printqueue(connection_struct
*conn
,
2731 char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2733 int outsize
= set_message(outbuf
,2,3,True
);
2734 int max_count
= SVAL(inbuf
,smb_vwv0
);
2735 int start_index
= SVAL(inbuf
,smb_vwv1
);
2736 START_PROFILE(SMBsplretq
);
2738 /* we used to allow the client to get the cnum wrong, but that
2739 is really quite gross and only worked when there was only
2740 one printer - I think we should now only accept it if they
2741 get it right (tridge) */
2742 if (!CAN_PRINT(conn
)) {
2743 END_PROFILE(SMBsplretq
);
2744 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2747 SSVAL(outbuf
,smb_vwv0
,0);
2748 SSVAL(outbuf
,smb_vwv1
,0);
2749 SCVAL(smb_buf(outbuf
),0,1);
2750 SSVAL(smb_buf(outbuf
),1,0);
2752 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2753 start_index
, max_count
));
2756 print_queue_struct
*queue
= NULL
;
2757 print_status_struct status
;
2758 char *p
= smb_buf(outbuf
) + 3;
2759 int count
= print_queue_status(SNUM(conn
), &queue
, &status
);
2760 int num_to_get
= ABS(max_count
);
2761 int first
= (max_count
>0?start_index
:start_index
+max_count
+1);
2767 num_to_get
= MIN(num_to_get
,count
-first
);
2770 for (i
=first
;i
<first
+num_to_get
;i
++) {
2771 put_dos_date2(p
,0,queue
[i
].time
);
2772 SCVAL(p
,4,(queue
[i
].status
==LPQ_PRINTING
?2:3));
2773 SSVAL(p
,5, queue
[i
].job
);
2774 SIVAL(p
,7,queue
[i
].size
);
2776 srvstr_push(outbuf
, p
+12, queue
[i
].fs_user
, 16, STR_ASCII
);
2781 outsize
= set_message(outbuf
,2,28*count
+3,False
);
2782 SSVAL(outbuf
,smb_vwv0
,count
);
2783 SSVAL(outbuf
,smb_vwv1
,(max_count
>0?first
+count
:first
-1));
2784 SCVAL(smb_buf(outbuf
),0,1);
2785 SSVAL(smb_buf(outbuf
),1,28*count
);
2790 DEBUG(3,("%d entries returned in queue\n",count
));
2793 END_PROFILE(SMBsplretq
);
2797 /****************************************************************************
2798 Reply to a printwrite.
2799 ****************************************************************************/
2801 int reply_printwrite(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2804 int outsize
= set_message(outbuf
,0,0,True
);
2806 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
2807 START_PROFILE(SMBsplwr
);
2809 if (!CAN_PRINT(conn
)) {
2810 END_PROFILE(SMBsplwr
);
2811 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
2814 CHECK_FSP(fsp
,conn
);
2817 numtowrite
= SVAL(smb_buf(inbuf
),1);
2818 data
= smb_buf(inbuf
) + 3;
2820 if (write_file(fsp
,data
,-1,numtowrite
) != numtowrite
) {
2821 END_PROFILE(SMBsplwr
);
2822 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
2825 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp
->fnum
, numtowrite
) );
2827 END_PROFILE(SMBsplwr
);
2831 /****************************************************************************
2832 The guts of the mkdir command, split out so it may be called by the NT SMB
2834 ****************************************************************************/
2836 NTSTATUS
mkdir_internal(connection_struct
*conn
, pstring directory
)
2838 BOOL bad_path
= False
;
2839 SMB_STRUCT_STAT sbuf
;
2842 unix_convert(directory
,conn
,0,&bad_path
,&sbuf
);
2844 if (check_name(directory
, conn
))
2845 ret
= vfs_mkdir(conn
,directory
,unix_mode(conn
,aDIR
,directory
));
2848 NTSTATUS nterr
= set_bad_path_error(errno
, bad_path
);
2849 if (!NT_STATUS_IS_OK(nterr
))
2851 return map_nt_error_from_unix(errno
);
2854 return NT_STATUS_OK
;
2857 /****************************************************************************
2859 ****************************************************************************/
2861 int reply_mkdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
2866 START_PROFILE(SMBmkdir
);
2868 srvstr_pull_buf(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), STR_TERMINATE
);
2870 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
);
2872 status
= mkdir_internal(conn
, directory
);
2873 if (!NT_STATUS_IS_OK(status
))
2874 return ERROR_NT(status
);
2876 outsize
= set_message(outbuf
,0,0,True
);
2878 DEBUG( 3, ( "mkdir %s ret=%d\n", directory
, outsize
) );
2880 END_PROFILE(SMBmkdir
);
2884 /****************************************************************************
2885 Static function used by reply_rmdir to delete an entire directory
2886 tree recursively. Return False on ok, True on fail.
2887 ****************************************************************************/
2889 static BOOL
recursive_rmdir(connection_struct
*conn
, char *directory
)
2893 void *dirptr
= OpenDir(conn
, directory
, False
);
2898 while((dname
= ReadDirName(dirptr
))) {
2902 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2905 /* Construct the full name. */
2906 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
2912 pstrcpy(fullname
, directory
);
2913 pstrcat(fullname
, "/");
2914 pstrcat(fullname
, dname
);
2916 if(conn
->vfs_ops
.lstat(conn
,fullname
, &st
) != 0) {
2921 if(st
.st_mode
& S_IFDIR
) {
2922 if(recursive_rmdir(conn
, fullname
)!=0) {
2926 if(vfs_rmdir(conn
,fullname
) != 0) {
2930 } else if(vfs_unlink(conn
,fullname
) != 0) {
2939 /****************************************************************************
2940 The internals of the rmdir code - called elsewhere.
2941 ****************************************************************************/
2943 BOOL
rmdir_internals(connection_struct
*conn
, char *directory
)
2947 ok
= (vfs_rmdir(conn
,directory
) == 0);
2948 if(!ok
&& ((errno
== ENOTEMPTY
)||(errno
== EEXIST
)) && lp_veto_files(SNUM(conn
))) {
2950 * Check to see if the only thing in this directory are
2951 * vetoed files/directories. If so then delete them and
2952 * retry. If we fail to delete any of them (and we *don't*
2953 * do a recursive delete) then fail the rmdir.
2955 BOOL all_veto_files
= True
;
2957 void *dirptr
= OpenDir(conn
, directory
, False
);
2959 if(dirptr
!= NULL
) {
2960 int dirpos
= TellDir(dirptr
);
2961 while ((dname
= ReadDirName(dirptr
))) {
2962 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2964 if(!IS_VETO_PATH(conn
, dname
)) {
2965 all_veto_files
= False
;
2970 if(all_veto_files
) {
2971 SeekDir(dirptr
,dirpos
);
2972 while ((dname
= ReadDirName(dirptr
))) {
2976 if((strcmp(dname
, ".") == 0) || (strcmp(dname
, "..")==0))
2979 /* Construct the full name. */
2980 if(strlen(directory
) + strlen(dname
) + 1 >= sizeof(fullname
)) {
2985 pstrcpy(fullname
, directory
);
2986 pstrcat(fullname
, "/");
2987 pstrcat(fullname
, dname
);
2989 if(conn
->vfs_ops
.lstat(conn
,fullname
, &st
) != 0)
2991 if(st
.st_mode
& S_IFDIR
) {
2992 if(lp_recursive_veto_delete(SNUM(conn
))) {
2993 if(recursive_rmdir(conn
, fullname
) != 0)
2996 if(vfs_rmdir(conn
,fullname
) != 0)
2998 } else if(vfs_unlink(conn
,fullname
) != 0)
3002 /* Retry the rmdir */
3003 ok
= (vfs_rmdir(conn
,directory
) == 0);
3013 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory
,strerror(errno
)));
3018 /****************************************************************************
3020 ****************************************************************************/
3022 int reply_rmdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3027 BOOL bad_path
= False
;
3028 SMB_STRUCT_STAT sbuf
;
3029 START_PROFILE(SMBrmdir
);
3031 srvstr_pull_buf(inbuf
, directory
, smb_buf(inbuf
) + 1, sizeof(directory
), STR_TERMINATE
);
3033 RESOLVE_DFSPATH(directory
, conn
, inbuf
, outbuf
)
3035 unix_convert(directory
,conn
, NULL
,&bad_path
,&sbuf
);
3037 if (check_name(directory
,conn
))
3039 dptr_closepath(directory
,SVAL(inbuf
,smb_pid
));
3040 ok
= rmdir_internals(conn
, directory
);
3045 set_bad_path_error(errno
, bad_path
);
3046 END_PROFILE(SMBrmdir
);
3047 return(UNIXERROR(ERRDOS
,ERRbadpath
));
3050 outsize
= set_message(outbuf
,0,0,True
);
3052 DEBUG( 3, ( "rmdir %s\n", directory
) );
3054 END_PROFILE(SMBrmdir
);
3058 /*******************************************************************
3059 Resolve wildcards in a filename rename.
3060 ********************************************************************/
3062 static BOOL
resolve_wildcards(char *name1
,char *name2
)
3064 fstring root1
,root2
;
3068 name1
= strrchr_m(name1
,'/');
3069 name2
= strrchr_m(name2
,'/');
3071 if (!name1
|| !name2
) return(False
);
3073 fstrcpy(root1
,name1
);
3074 fstrcpy(root2
,name2
);
3075 p
= strrchr_m(root1
,'.');
3082 p
= strrchr_m(root2
,'.');
3114 pstrcpy(name2
,root2
);
3117 pstrcat(name2
,ext2
);
3123 /****************************************************************************
3124 The guts of the rename command, split out so it may be called by the NT SMB
3126 ****************************************************************************/
3128 NTSTATUS
rename_internals(connection_struct
*conn
, char *name
, char *newname
, BOOL replace_if_exists
)
3132 pstring newname_last_component
;
3135 BOOL bad_path1
= False
;
3136 BOOL bad_path2
= False
;
3138 NTSTATUS error
= NT_STATUS_OK
;
3140 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3142 *directory
= *mask
= 0;
3144 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
3145 unix_convert(newname
,conn
,newname_last_component
,&bad_path2
,&sbuf2
);
3148 * Split the old name into directory and last component
3149 * strings. Note that unix_convert may have stripped off a
3150 * leading ./ from both name and newname if the rename is
3151 * at the root of the share. We need to make sure either both
3152 * name and newname contain a / character or neither of them do
3153 * as this is checked in resolve_wildcards().
3156 p
= strrchr_m(name
,'/');
3158 pstrcpy(directory
,".");
3162 pstrcpy(directory
,name
);
3164 *p
= '/'; /* Replace needed for exceptional test below. */
3168 * We should only check the mangled cache
3169 * here if unix_convert failed. This means
3170 * that the path in 'mask' doesn't exist
3171 * on the file system and so we need to look
3172 * for a possible mangle. This patch from
3173 * Tine Smukavec <valentin.smukavec@hermes.si>.
3176 if (!rc
&& mangle_is_mangled(mask
))
3177 mangle_check_cache( mask
);
3179 has_wild
= ms_has_wild(mask
);
3183 * No wildcards - just process the one file.
3185 BOOL is_short_name
= mangle_is_8_3(name
, True
);
3187 /* Add a terminating '/' to the directory name. */
3188 pstrcat(directory
,"/");
3189 pstrcat(directory
,mask
);
3191 /* Ensure newname contains a '/' also */
3192 if(strrchr_m(newname
,'/') == 0) {
3195 pstrcpy(tmpstr
, "./");
3196 pstrcat(tmpstr
, newname
);
3197 pstrcpy(newname
, tmpstr
);
3200 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3201 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3202 case_sensitive
, case_preserve
, short_case_preserve
, directory
,
3203 newname
, newname_last_component
, is_short_name
));
3206 * Check for special case with case preserving and not
3207 * case sensitive, if directory and newname are identical,
3208 * and the old last component differs from the original
3209 * last component only by case, then we should allow
3210 * the rename (user is trying to change the case of the
3213 if((case_sensitive
== False
) &&
3214 (((case_preserve
== True
) &&
3215 (is_short_name
== False
)) ||
3216 ((short_case_preserve
== True
) &&
3217 (is_short_name
== True
))) &&
3218 strcsequal(directory
, newname
)) {
3219 pstring newname_modified_last_component
;
3222 * Get the last component of the modified name.
3223 * Note that we guarantee that newname contains a '/'
3226 p
= strrchr_m(newname
,'/');
3227 pstrcpy(newname_modified_last_component
,p
+1);
3229 if(strcsequal(newname_modified_last_component
,
3230 newname_last_component
) == False
) {
3232 * Replace the modified last component with
3235 pstrcpy(p
+1, newname_last_component
);
3239 resolve_wildcards(directory
,newname
);
3242 * The source object must exist.
3245 if (!vfs_object_exist(conn
, directory
, &sbuf1
)) {
3246 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3247 directory
,newname
));
3249 if (errno
== ENOTDIR
|| errno
== EISDIR
|| errno
== ENOENT
) {
3251 * Must return different errors depending on whether the parent
3252 * directory existed or not.
3255 p
= strrchr_m(directory
, '/');
3257 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3259 if (vfs_object_exist(conn
, directory
, NULL
))
3260 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3261 return NT_STATUS_OBJECT_PATH_NOT_FOUND
;
3263 error
= map_nt_error_from_unix(errno
);
3264 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3265 nt_errstr(error
), directory
,newname
));
3270 error
= can_rename(directory
,conn
,&sbuf1
);
3272 if (!NT_STATUS_IS_OK(error
)) {
3273 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3274 nt_errstr(error
), directory
,newname
));
3279 * If the src and dest names are identical - including case,
3280 * don't do the rename, just return success.
3283 if (strcsequal(directory
, newname
)) {
3284 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory
));
3285 return NT_STATUS_OK
;
3288 if(!replace_if_exists
&& vfs_object_exist(conn
,newname
,NULL
)) {
3289 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3290 directory
,newname
));
3291 return NT_STATUS_OBJECT_NAME_COLLISION
;
3294 if(conn
->vfs_ops
.rename(conn
,directory
, newname
) == 0) {
3295 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3296 directory
,newname
));
3297 return NT_STATUS_OK
;
3300 if (errno
== ENOTDIR
|| errno
== EISDIR
)
3301 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3303 error
= map_nt_error_from_unix(errno
);
3305 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3306 nt_errstr(error
), directory
,newname
));
3311 * Wildcards - process each file that matches.
3313 void *dirptr
= NULL
;
3317 if (check_name(directory
,conn
))
3318 dirptr
= OpenDir(conn
, directory
, True
);
3321 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3323 if (strequal(mask
,"????????.???"))
3326 while ((dname
= ReadDirName(dirptr
))) {
3329 pstrcpy(fname
,dname
);
3331 if(!mask_match(fname
, mask
, case_sensitive
))
3334 error
= NT_STATUS_ACCESS_DENIED
;
3335 slprintf(fname
,sizeof(fname
)-1,"%s/%s",directory
,dname
);
3336 if (!vfs_object_exist(conn
, fname
, &sbuf1
)) {
3337 error
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
3338 DEBUG(6,("rename %s failed. Error %s\n", fname
, nt_errstr(error
)));
3341 error
= can_rename(fname
,conn
,&sbuf1
);
3342 if (!NT_STATUS_IS_OK(error
)) {
3343 DEBUG(6,("rename %s refused\n", fname
));
3346 pstrcpy(destname
,newname
);
3348 if (!resolve_wildcards(fname
,destname
)) {
3349 DEBUG(6,("resolve_wildcards %s %s failed\n",
3354 if (!replace_if_exists
&&
3355 vfs_file_exist(conn
,destname
, NULL
)) {
3356 DEBUG(6,("file_exist %s\n", destname
));
3357 error
= NT_STATUS_OBJECT_NAME_COLLISION
;
3361 if (!conn
->vfs_ops
.rename(conn
,fname
,destname
))
3363 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname
,destname
));
3369 if (count
== 0 && NT_STATUS_IS_OK(error
)) {
3370 error
= map_nt_error_from_unix(errno
);
3376 /****************************************************************************
3378 ****************************************************************************/
3380 int reply_mv(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
,
3389 START_PROFILE(SMBmv
);
3391 p
= smb_buf(inbuf
) + 1;
3392 p
+= srvstr_pull_buf(inbuf
, name
, p
, sizeof(name
), STR_TERMINATE
);
3394 p
+= srvstr_pull_buf(inbuf
, newname
, p
, sizeof(newname
), STR_TERMINATE
);
3396 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3397 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3399 DEBUG(3,("reply_mv : %s -> %s\n",name
,newname
));
3401 status
= rename_internals(conn
, name
, newname
, False
);
3402 if (!NT_STATUS_IS_OK(status
)) {
3403 return ERROR_NT(status
);
3407 * Win2k needs a changenotify request response before it will
3408 * update after a rename..
3410 process_pending_change_notify_queue((time_t)0);
3411 outsize
= set_message(outbuf
,0,0,True
);
3417 /*******************************************************************
3418 Copy a file as part of a reply_copy.
3419 ******************************************************************/
3421 static BOOL
copy_file(char *src
,char *dest1
,connection_struct
*conn
, int ofun
,
3422 int count
,BOOL target_is_directory
, int *err_ret
)
3425 SMB_STRUCT_STAT src_sbuf
, sbuf2
;
3427 files_struct
*fsp1
,*fsp2
;
3432 pstrcpy(dest
,dest1
);
3433 if (target_is_directory
) {
3434 char *p
= strrchr_m(src
,'/');
3443 if (!vfs_file_exist(conn
,src
,&src_sbuf
))
3446 fsp1
= open_file_shared(conn
,src
,&src_sbuf
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_RDONLY
),
3447 (FILE_FAIL_IF_NOT_EXIST
|FILE_EXISTS_OPEN
),0,0,&Access
,&action
);
3452 if (!target_is_directory
&& count
)
3453 ofun
= FILE_EXISTS_OPEN
;
3455 if (vfs_stat(conn
,dest
,&sbuf2
) == -1)
3456 ZERO_STRUCTP(&sbuf2
);
3458 fsp2
= open_file_shared(conn
,dest
,&sbuf2
,SET_DENY_MODE(DENY_NONE
)|SET_OPEN_MODE(DOS_OPEN_WRONLY
),
3459 ofun
,src_sbuf
.st_mode
,0,&Access
,&action
);
3462 close_file(fsp1
,False
);
3466 if ((ofun
&3) == 1) {
3467 if(conn
->vfs_ops
.lseek(fsp2
,fsp2
->fd
,0,SEEK_END
) == -1) {
3468 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno
) ));
3470 * Stop the copy from occurring.
3473 src_sbuf
.st_size
= 0;
3477 if (src_sbuf
.st_size
)
3478 ret
= vfs_transfer_file(fsp1
, fsp2
, src_sbuf
.st_size
);
3480 close_file(fsp1
,False
);
3482 /* Ensure the modtime is set correctly on the destination file. */
3483 fsp2
->pending_modtime
= src_sbuf
.st_mtime
;
3486 * As we are opening fsp1 read-only we only expect
3487 * an error on close on fsp2 if we are out of space.
3488 * Thus we don't look at the error return from the
3491 *err_ret
= close_file(fsp2
,False
);
3493 return(ret
== (SMB_OFF_T
)src_sbuf
.st_size
);
3496 /****************************************************************************
3497 Reply to a file copy.
3498 ****************************************************************************/
3500 int reply_copy(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3505 pstring mask
,newname
;
3508 int error
= ERRnoaccess
;
3512 int tid2
= SVAL(inbuf
,smb_vwv0
);
3513 int ofun
= SVAL(inbuf
,smb_vwv1
);
3514 int flags
= SVAL(inbuf
,smb_vwv2
);
3515 BOOL target_is_directory
=False
;
3516 BOOL bad_path1
= False
;
3517 BOOL bad_path2
= False
;
3519 SMB_STRUCT_STAT sbuf1
, sbuf2
;
3520 START_PROFILE(SMBcopy
);
3522 *directory
= *mask
= 0;
3525 p
+= srvstr_pull_buf(inbuf
, name
, p
, sizeof(name
), STR_TERMINATE
);
3526 p
+= srvstr_pull_buf(inbuf
, newname
, p
, sizeof(newname
), STR_TERMINATE
);
3528 DEBUG(3,("reply_copy : %s -> %s\n",name
,newname
));
3530 if (tid2
!= conn
->cnum
) {
3531 /* can't currently handle inter share copies XXXX */
3532 DEBUG(3,("Rejecting inter-share copy\n"));
3533 END_PROFILE(SMBcopy
);
3534 return ERROR_DOS(ERRSRV
,ERRinvdevice
);
3537 RESOLVE_DFSPATH(name
, conn
, inbuf
, outbuf
);
3538 RESOLVE_DFSPATH(newname
, conn
, inbuf
, outbuf
);
3540 rc
= unix_convert(name
,conn
,0,&bad_path1
,&sbuf1
);
3541 unix_convert(newname
,conn
,0,&bad_path2
,&sbuf2
);
3543 target_is_directory
= VALID_STAT_OF_DIR(sbuf2
);
3545 if ((flags
&1) && target_is_directory
) {
3546 END_PROFILE(SMBcopy
);
3547 return ERROR_DOS(ERRDOS
,ERRbadfile
);
3550 if ((flags
&2) && !target_is_directory
) {
3551 END_PROFILE(SMBcopy
);
3552 return ERROR_DOS(ERRDOS
,ERRbadpath
);
3555 if ((flags
&(1<<5)) && VALID_STAT_OF_DIR(sbuf1
)) {
3556 /* wants a tree copy! XXXX */
3557 DEBUG(3,("Rejecting tree copy\n"));
3558 END_PROFILE(SMBcopy
);
3559 return ERROR_DOS(ERRSRV
,ERRerror
);
3562 p
= strrchr_m(name
,'/');
3564 pstrcpy(directory
,"./");
3568 pstrcpy(directory
,name
);
3573 * We should only check the mangled cache
3574 * here if unix_convert failed. This means
3575 * that the path in 'mask' doesn't exist
3576 * on the file system and so we need to look
3577 * for a possible mangle. This patch from
3578 * Tine Smukavec <valentin.smukavec@hermes.si>.
3581 if (!rc
&& mangle_is_mangled(mask
))
3582 mangle_check_cache( mask
);
3584 has_wild
= ms_has_wild(mask
);
3587 pstrcat(directory
,"/");
3588 pstrcat(directory
,mask
);
3589 if (resolve_wildcards(directory
,newname
) &&
3590 copy_file(directory
,newname
,conn
,ofun
,
3591 count
,target_is_directory
,&err
)) count
++;
3594 END_PROFILE(SMBcopy
);
3595 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3597 if (!count
) exists
= vfs_file_exist(conn
,directory
,NULL
);
3599 void *dirptr
= NULL
;
3603 if (check_name(directory
,conn
))
3604 dirptr
= OpenDir(conn
, directory
, True
);
3609 if (strequal(mask
,"????????.???"))
3612 while ((dname
= ReadDirName(dirptr
))) {
3614 pstrcpy(fname
,dname
);
3616 if(!mask_match(fname
, mask
, case_sensitive
))
3619 error
= ERRnoaccess
;
3620 slprintf(fname
,sizeof(fname
)-1, "%s/%s",directory
,dname
);
3621 pstrcpy(destname
,newname
);
3622 if (resolve_wildcards(fname
,destname
) &&
3623 copy_file(fname
,destname
,conn
,ofun
,
3624 count
,target_is_directory
,&err
)) count
++;
3625 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname
,destname
));
3633 /* Error on close... */
3635 END_PROFILE(SMBcopy
);
3636 return(UNIXERROR(ERRHRD
,ERRgeneral
));
3640 END_PROFILE(SMBcopy
);
3641 return ERROR_DOS(ERRDOS
,error
);
3644 if((errno
== ENOENT
) && (bad_path1
|| bad_path2
))
3646 unix_ERR_class
= ERRDOS
;
3647 unix_ERR_code
= ERRbadpath
;
3649 END_PROFILE(SMBcopy
);
3650 return(UNIXERROR(ERRDOS
,error
));
3654 outsize
= set_message(outbuf
,1,0,True
);
3655 SSVAL(outbuf
,smb_vwv0
,count
);
3657 END_PROFILE(SMBcopy
);
3661 /****************************************************************************
3663 ****************************************************************************/
3665 int reply_setdir(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
3671 START_PROFILE(pathworks_setdir
);
3674 if (!CAN_SETDIR(snum
)) {
3675 END_PROFILE(pathworks_setdir
);
3676 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3679 srvstr_pull_buf(inbuf
, newdir
, smb_buf(inbuf
) + 1, sizeof(newdir
), STR_TERMINATE
);
3681 if (strlen(newdir
) == 0) {
3684 ok
= vfs_directory_exist(conn
,newdir
,NULL
);
3686 string_set(&conn
->connectpath
,newdir
);
3691 END_PROFILE(pathworks_setdir
);
3692 return ERROR_DOS(ERRDOS
,ERRbadpath
);
3695 outsize
= set_message(outbuf
,0,0,True
);
3696 SCVAL(outbuf
,smb_reh
,CVAL(inbuf
,smb_reh
));
3698 DEBUG(3,("setdir %s\n", newdir
));
3700 END_PROFILE(pathworks_setdir
);
3704 /****************************************************************************
3705 Get a lock pid, dealing with large count requests.
3706 ****************************************************************************/
3708 uint16
get_lock_pid( char *data
, int data_offset
, BOOL large_file_format
)
3710 if(!large_file_format
)
3711 return SVAL(data
,SMB_LPID_OFFSET(data_offset
));
3713 return SVAL(data
,SMB_LARGE_LPID_OFFSET(data_offset
));
3716 /****************************************************************************
3717 Get a lock count, dealing with large count requests.
3718 ****************************************************************************/
3720 SMB_BIG_UINT
get_lock_count( char *data
, int data_offset
, BOOL large_file_format
)
3722 SMB_BIG_UINT count
= 0;
3724 if(!large_file_format
) {
3725 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKLEN_OFFSET(data_offset
));
3728 #if defined(HAVE_LONGLONG)
3729 count
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
))) << 32) |
3730 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)));
3731 #else /* HAVE_LONGLONG */
3734 * NT4.x seems to be broken in that it sends large file (64 bit)
3735 * lockingX calls even if the CAP_LARGE_FILES was *not*
3736 * negotiated. For boxes without large unsigned ints truncate the
3737 * lock count by dropping the top 32 bits.
3740 if(IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)) != 0) {
3741 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3742 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
)),
3743 (unsigned int)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
)) ));
3744 SIVAL(data
,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset
),0);
3747 count
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset
));
3748 #endif /* HAVE_LONGLONG */
3754 #if !defined(HAVE_LONGLONG)
3755 /****************************************************************************
3756 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3757 ****************************************************************************/
3759 static uint32
map_lock_offset(uint32 high
, uint32 low
)
3763 uint32 highcopy
= high
;
3766 * Try and find out how many significant bits there are in high.
3769 for(i
= 0; highcopy
; i
++)
3773 * We use 31 bits not 32 here as POSIX
3774 * lock offsets may not be negative.
3777 mask
= (~0) << (31 - i
);
3780 return 0; /* Fail. */
3786 #endif /* !defined(HAVE_LONGLONG) */
3788 /****************************************************************************
3789 Get a lock offset, dealing with large offset requests.
3790 ****************************************************************************/
3792 SMB_BIG_UINT
get_lock_offset( char *data
, int data_offset
, BOOL large_file_format
, BOOL
*err
)
3794 SMB_BIG_UINT offset
= 0;
3798 if(!large_file_format
) {
3799 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LKOFF_OFFSET(data_offset
));
3802 #if defined(HAVE_LONGLONG)
3803 offset
= (((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
))) << 32) |
3804 ((SMB_BIG_UINT
) IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
)));
3805 #else /* HAVE_LONGLONG */
3808 * NT4.x seems to be broken in that it sends large file (64 bit)
3809 * lockingX calls even if the CAP_LARGE_FILES was *not*
3810 * negotiated. For boxes without large unsigned ints mangle the
3811 * lock offset by mapping the top 32 bits onto the lower 32.
3814 if(IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
)) != 0) {
3815 uint32 low
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
3816 uint32 high
= IVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
));
3819 if((new_low
= map_lock_offset(high
, low
)) == 0) {
3821 return (SMB_BIG_UINT
)-1;
3824 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3825 (unsigned int)high
, (unsigned int)low
, (unsigned int)new_low
));
3826 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset
),0);
3827 SIVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
),new_low
);
3830 offset
= (SMB_BIG_UINT
)IVAL(data
,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset
));
3831 #endif /* HAVE_LONGLONG */
3837 /****************************************************************************
3838 Reply to a lockingX request.
3839 ****************************************************************************/
3841 int reply_lockingX(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
3843 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv2
);
3844 unsigned char locktype
= CVAL(inbuf
,smb_vwv3
);
3845 unsigned char oplocklevel
= CVAL(inbuf
,smb_vwv3
+1);
3846 uint16 num_ulocks
= SVAL(inbuf
,smb_vwv6
);
3847 uint16 num_locks
= SVAL(inbuf
,smb_vwv7
);
3848 SMB_BIG_UINT count
= 0, offset
= 0;
3850 int32 lock_timeout
= IVAL(inbuf
,smb_vwv4
);
3853 BOOL large_file_format
= (locktype
& LOCKING_ANDX_LARGE_FILES
)?True
:False
;
3857 START_PROFILE(SMBlockingX
);
3859 CHECK_FSP(fsp
,conn
);
3861 data
= smb_buf(inbuf
);
3863 if (locktype
& (LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_CHANGE_LOCKTYPE
)) {
3864 /* we don't support these - and CANCEL_LOCK makes w2k
3865 and XP reboot so I don't really want to be
3866 compatible! (tridge) */
3867 return ERROR_NT(NT_STATUS_NOT_SUPPORTED
);
3870 /* Check if this is an oplock break on a file
3871 we have granted an oplock on.
3873 if ((locktype
& LOCKING_ANDX_OPLOCK_RELEASE
)) {
3874 /* Client can insist on breaking to none. */
3875 BOOL break_to_none
= (oplocklevel
== 0);
3877 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3878 (unsigned int)oplocklevel
, fsp
->fnum
));
3881 * Make sure we have granted an exclusive or batch oplock on this file.
3884 if(!EXCLUSIVE_OPLOCK_TYPE(fsp
->oplock_type
)) {
3885 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3886 no oplock granted on this file (%s).\n", fsp
->fnum
, fsp
->fsp_name
));
3888 /* if this is a pure oplock break request then don't send a reply */
3889 if (num_locks
== 0 && num_ulocks
== 0) {
3890 END_PROFILE(SMBlockingX
);
3893 END_PROFILE(SMBlockingX
);
3894 return ERROR_DOS(ERRDOS
,ERRlock
);
3898 if (remove_oplock(fsp
, break_to_none
) == False
) {
3899 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3903 /* if this is a pure oplock break request then don't send a reply */
3904 if (num_locks
== 0 && num_ulocks
== 0) {
3905 /* Sanity check - ensure a pure oplock break is not a
3907 if(CVAL(inbuf
,smb_vwv0
) != 0xff)
3908 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3909 (unsigned int)CVAL(inbuf
,smb_vwv0
) ));
3910 END_PROFILE(SMBlockingX
);
3916 * We do this check *after* we have checked this is not a oplock break
3917 * response message. JRA.
3920 release_level_2_oplocks_on_change(fsp
);
3922 /* Data now points at the beginning of the list
3923 of smb_unlkrng structs */
3924 for(i
= 0; i
< (int)num_ulocks
; i
++) {
3925 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
3926 count
= get_lock_count( data
, i
, large_file_format
);
3927 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
3930 * There is no error code marked "stupid client bug".... :-).
3933 END_PROFILE(SMBlockingX
);
3934 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3937 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3938 (double)offset
, (double)count
, (unsigned int)lock_pid
, fsp
->fsp_name
));
3940 status
= do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
3941 if (NT_STATUS_V(status
)) {
3942 END_PROFILE(SMBlockingX
);
3943 return ERROR_NT(status
);
3947 /* Setup the timeout in seconds. */
3949 lock_timeout
= ((lock_timeout
== -1) ? -1 : (lock_timeout
+999)/1000);
3951 /* Now do any requested locks */
3952 data
+= ((large_file_format
? 20 : 10)*num_ulocks
);
3954 /* Data now points at the beginning of the list
3955 of smb_lkrng structs */
3957 for(i
= 0; i
< (int)num_locks
; i
++) {
3958 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
3959 count
= get_lock_count( data
, i
, large_file_format
);
3960 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
3963 * There is no error code marked "stupid client bug".... :-).
3966 END_PROFILE(SMBlockingX
);
3967 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
3970 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3971 (double)offset
, (double)count
, (unsigned int)lock_pid
,
3972 fsp
->fsp_name
, (int)lock_timeout
));
3974 status
= do_lock_spin(fsp
,conn
,lock_pid
, count
,offset
,
3975 ((locktype
& 1) ? READ_LOCK
: WRITE_LOCK
));
3976 if (NT_STATUS_V(status
)) {
3977 if ((lock_timeout
!= 0) && lp_blocking_locks(SNUM(conn
)) && ERROR_WAS_LOCK_DENIED(status
)) {
3979 * A blocking lock was requested. Package up
3980 * this smb into a queued request and push it
3981 * onto the blocking lock queue.
3983 if(push_blocking_lock_request(inbuf
, length
, lock_timeout
, i
)) {
3984 END_PROFILE(SMBlockingX
);
3992 /* If any of the above locks failed, then we must unlock
3993 all of the previous locks (X/Open spec). */
3994 if (i
!= num_locks
&& num_locks
!= 0) {
3996 * Ensure we don't do a remove on the lock that just failed,
3997 * as under POSIX rules, if we have a lock already there, we
3998 * will delete it (and we shouldn't) .....
4000 for(i
--; i
>= 0; i
--) {
4001 lock_pid
= get_lock_pid( data
, i
, large_file_format
);
4002 count
= get_lock_count( data
, i
, large_file_format
);
4003 offset
= get_lock_offset( data
, i
, large_file_format
, &err
);
4006 * There is no error code marked "stupid client bug".... :-).
4009 END_PROFILE(SMBlockingX
);
4010 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4013 do_unlock(fsp
,conn
,lock_pid
,count
,offset
);
4015 END_PROFILE(SMBlockingX
);
4016 return ERROR_NT(status
);
4019 set_message(outbuf
,2,0,True
);
4021 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4022 fsp
->fnum
, (unsigned int)locktype
, num_locks
, num_ulocks
) );
4024 END_PROFILE(SMBlockingX
);
4025 return chain_reply(inbuf
,outbuf
,length
,bufsize
);
4028 /****************************************************************************
4029 Reply to a SMBreadbmpx (read block multiplex) request.
4030 ****************************************************************************/
4032 int reply_readbmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
,int length
,int bufsize
)
4043 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4044 START_PROFILE(SMBreadBmpx
);
4046 /* this function doesn't seem to work - disable by default */
4047 if (!lp_readbmpx()) {
4048 END_PROFILE(SMBreadBmpx
);
4049 return ERROR_DOS(ERRSRV
,ERRuseSTD
);
4052 outsize
= set_message(outbuf
,8,0,True
);
4054 CHECK_FSP(fsp
,conn
);
4057 startpos
= IVAL(inbuf
,smb_vwv1
);
4058 maxcount
= SVAL(inbuf
,smb_vwv3
);
4060 data
= smb_buf(outbuf
);
4061 pad
= ((long)data
)%4;
4066 max_per_packet
= bufsize
-(outsize
+pad
);
4070 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)maxcount
,(SMB_BIG_UINT
)startpos
, READ_LOCK
,False
)) {
4071 END_PROFILE(SMBreadBmpx
);
4072 return ERROR_DOS(ERRDOS
,ERRlock
);
4076 size_t N
= MIN(max_per_packet
,tcount
-total_read
);
4078 nread
= read_file(fsp
,data
,startpos
,N
);
4083 if (nread
< (ssize_t
)N
)
4084 tcount
= total_read
+ nread
;
4086 set_message(outbuf
,8,nread
,False
);
4087 SIVAL(outbuf
,smb_vwv0
,startpos
);
4088 SSVAL(outbuf
,smb_vwv2
,tcount
);
4089 SSVAL(outbuf
,smb_vwv6
,nread
);
4090 SSVAL(outbuf
,smb_vwv7
,smb_offset(data
,outbuf
));
4092 if (!send_smb(smbd_server_fd(),outbuf
))
4093 exit_server("reply_readbmpx: send_smb failed.");
4095 total_read
+= nread
;
4097 } while (total_read
< (ssize_t
)tcount
);
4099 END_PROFILE(SMBreadBmpx
);
4103 /****************************************************************************
4104 Reply to a SMBsetattrE.
4105 ****************************************************************************/
4107 int reply_setattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4109 struct utimbuf unix_times
;
4111 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4112 START_PROFILE(SMBsetattrE
);
4114 outsize
= set_message(outbuf
,0,0,True
);
4116 if(!fsp
|| (fsp
->conn
!= conn
)) {
4117 END_PROFILE(SMBgetattrE
);
4118 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4122 * Convert the DOS times into unix times. Ignore create
4123 * time as UNIX can't set this.
4126 unix_times
.actime
= make_unix_date2(inbuf
+smb_vwv3
);
4127 unix_times
.modtime
= make_unix_date2(inbuf
+smb_vwv5
);
4130 * Patch from Ray Frush <frush@engr.colostate.edu>
4131 * Sometimes times are sent as zero - ignore them.
4134 if ((unix_times
.actime
== 0) && (unix_times
.modtime
== 0)) {
4135 /* Ignore request */
4136 if( DEBUGLVL( 3 ) ) {
4137 dbgtext( "reply_setattrE fnum=%d ", fsp
->fnum
);
4138 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4140 END_PROFILE(SMBsetattrE
);
4142 } else if ((unix_times
.actime
!= 0) && (unix_times
.modtime
== 0)) {
4143 /* set modify time = to access time if modify time was 0 */
4144 unix_times
.modtime
= unix_times
.actime
;
4147 /* Set the date on this file */
4148 if(file_utime(conn
, fsp
->fsp_name
, &unix_times
)) {
4149 END_PROFILE(SMBsetattrE
);
4150 return ERROR_DOS(ERRDOS
,ERRnoaccess
);
4153 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4154 fsp
->fnum
, (int)unix_times
.actime
, (int)unix_times
.modtime
) );
4156 END_PROFILE(SMBsetattrE
);
4161 /* Back from the dead for OS/2..... JRA. */
4163 /****************************************************************************
4164 Reply to a SMBwritebmpx (write block multiplex primary) request.
4165 ****************************************************************************/
4167 int reply_writebmpx(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4170 ssize_t nwritten
= -1;
4177 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4178 START_PROFILE(SMBwriteBmpx
);
4180 CHECK_FSP(fsp
,conn
);
4184 tcount
= SVAL(inbuf
,smb_vwv1
);
4185 startpos
= IVAL(inbuf
,smb_vwv3
);
4186 write_through
= BITSETW(inbuf
+smb_vwv7
,0);
4187 numtowrite
= SVAL(inbuf
,smb_vwv10
);
4188 smb_doff
= SVAL(inbuf
,smb_vwv11
);
4190 data
= smb_base(inbuf
) + smb_doff
;
4192 /* If this fails we need to send an SMBwriteC response,
4193 not an SMBwritebmpx - set this up now so we don't forget */
4194 SCVAL(outbuf
,smb_com
,SMBwritec
);
4196 if (is_locked(fsp
,conn
,(SMB_BIG_UINT
)tcount
,(SMB_BIG_UINT
)startpos
,WRITE_LOCK
,False
)) {
4197 END_PROFILE(SMBwriteBmpx
);
4198 return(ERROR_DOS(ERRDOS
,ERRlock
));
4201 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4203 if(lp_syncalways(SNUM(conn
)) || write_through
)
4204 sync_file(conn
,fsp
);
4206 if(nwritten
< (ssize_t
)numtowrite
) {
4207 END_PROFILE(SMBwriteBmpx
);
4208 return(UNIXERROR(ERRHRD
,ERRdiskfull
));
4211 /* If the maximum to be written to this file
4212 is greater than what we just wrote then set
4213 up a secondary struct to be attached to this
4214 fd, we will use this to cache error messages etc. */
4216 if((ssize_t
)tcount
> nwritten
) {
4217 write_bmpx_struct
*wbms
;
4218 if(fsp
->wbmpx_ptr
!= NULL
)
4219 wbms
= fsp
->wbmpx_ptr
; /* Use an existing struct */
4221 wbms
= (write_bmpx_struct
*)malloc(sizeof(write_bmpx_struct
));
4223 DEBUG(0,("Out of memory in reply_readmpx\n"));
4224 END_PROFILE(SMBwriteBmpx
);
4225 return(ERROR_DOS(ERRSRV
,ERRnoresource
));
4227 wbms
->wr_mode
= write_through
;
4228 wbms
->wr_discard
= False
; /* No errors yet */
4229 wbms
->wr_total_written
= nwritten
;
4230 wbms
->wr_errclass
= 0;
4232 fsp
->wbmpx_ptr
= wbms
;
4235 /* We are returning successfully, set the message type back to
4237 SCVAL(outbuf
,smb_com
,SMBwriteBmpx
);
4239 outsize
= set_message(outbuf
,1,0,True
);
4241 SSVALS(outbuf
,smb_vwv0
,-1); /* We don't support smb_remaining */
4243 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4244 fsp
->fnum
, (int)numtowrite
, (int)nwritten
) );
4246 if (write_through
&& tcount
==nwritten
) {
4247 /* We need to send both a primary and a secondary response */
4248 smb_setlen(outbuf
,outsize
- 4);
4249 if (!send_smb(smbd_server_fd(),outbuf
))
4250 exit_server("reply_writebmpx: send_smb failed.");
4252 /* Now the secondary */
4253 outsize
= set_message(outbuf
,1,0,True
);
4254 SCVAL(outbuf
,smb_com
,SMBwritec
);
4255 SSVAL(outbuf
,smb_vwv0
,nwritten
);
4258 END_PROFILE(SMBwriteBmpx
);
4262 /****************************************************************************
4263 Reply to a SMBwritebs (write block multiplex secondary) request.
4264 ****************************************************************************/
4266 int reply_writebs(connection_struct
*conn
, char *inbuf
,char *outbuf
, int dum_size
, int dum_buffsize
)
4269 ssize_t nwritten
= -1;
4276 write_bmpx_struct
*wbms
;
4277 BOOL send_response
= False
;
4278 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4279 START_PROFILE(SMBwriteBs
);
4281 CHECK_FSP(fsp
,conn
);
4284 tcount
= SVAL(inbuf
,smb_vwv1
);
4285 startpos
= IVAL(inbuf
,smb_vwv2
);
4286 numtowrite
= SVAL(inbuf
,smb_vwv6
);
4287 smb_doff
= SVAL(inbuf
,smb_vwv7
);
4289 data
= smb_base(inbuf
) + smb_doff
;
4291 /* We need to send an SMBwriteC response, not an SMBwritebs */
4292 SCVAL(outbuf
,smb_com
,SMBwritec
);
4294 /* This fd should have an auxiliary struct attached,
4295 check that it does */
4296 wbms
= fsp
->wbmpx_ptr
;
4298 END_PROFILE(SMBwriteBs
);
4302 /* If write through is set we can return errors, else we must cache them */
4303 write_through
= wbms
->wr_mode
;
4305 /* Check for an earlier error */
4306 if(wbms
->wr_discard
) {
4307 END_PROFILE(SMBwriteBs
);
4308 return -1; /* Just discard the packet */
4311 nwritten
= write_file(fsp
,data
,startpos
,numtowrite
);
4313 if(lp_syncalways(SNUM(conn
)) || write_through
)
4314 sync_file(conn
,fsp
);
4316 if (nwritten
< (ssize_t
)numtowrite
) {
4318 /* We are returning an error - we can delete the aux struct */
4321 fsp
->wbmpx_ptr
= NULL
;
4322 END_PROFILE(SMBwriteBs
);
4323 return(ERROR_DOS(ERRHRD
,ERRdiskfull
));
4325 END_PROFILE(SMBwriteBs
);
4326 return(CACHE_ERROR(wbms
,ERRHRD
,ERRdiskfull
));
4329 /* Increment the total written, if this matches tcount
4330 we can discard the auxiliary struct (hurrah !) and return a writeC */
4331 wbms
->wr_total_written
+= nwritten
;
4332 if(wbms
->wr_total_written
>= tcount
) {
4333 if (write_through
) {
4334 outsize
= set_message(outbuf
,1,0,True
);
4335 SSVAL(outbuf
,smb_vwv0
,wbms
->wr_total_written
);
4336 send_response
= True
;
4340 fsp
->wbmpx_ptr
= NULL
;
4344 END_PROFILE(SMBwriteBs
);
4348 END_PROFILE(SMBwriteBs
);
4352 /****************************************************************************
4353 Reply to a SMBgetattrE.
4354 ****************************************************************************/
4356 int reply_getattrE(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int dum_buffsize
)
4358 SMB_STRUCT_STAT sbuf
;
4361 files_struct
*fsp
= file_fsp(inbuf
,smb_vwv0
);
4362 START_PROFILE(SMBgetattrE
);
4364 outsize
= set_message(outbuf
,11,0,True
);
4366 if(!fsp
|| (fsp
->conn
!= conn
)) {
4367 END_PROFILE(SMBgetattrE
);
4368 return ERROR_DOS(ERRDOS
,ERRbadfid
);
4371 /* Do an fstat on this file */
4372 if(fsp_stat(fsp
, &sbuf
)) {
4373 END_PROFILE(SMBgetattrE
);
4374 return(UNIXERROR(ERRDOS
,ERRnoaccess
));
4377 mode
= dos_mode(conn
,fsp
->fsp_name
,&sbuf
);
4380 * Convert the times into dos times. Set create
4381 * date to be last modify date as UNIX doesn't save
4385 put_dos_date2(outbuf
,smb_vwv0
,get_create_time(&sbuf
,lp_fake_dir_create_times(SNUM(conn
))));
4386 put_dos_date2(outbuf
,smb_vwv2
,sbuf
.st_atime
);
4387 put_dos_date2(outbuf
,smb_vwv4
,sbuf
.st_mtime
);
4390 SIVAL(outbuf
,smb_vwv6
,0);
4391 SIVAL(outbuf
,smb_vwv8
,0);
4393 SIVAL(outbuf
,smb_vwv6
,(uint32
)sbuf
.st_size
);
4394 SIVAL(outbuf
,smb_vwv8
,SMB_ROUNDUP(sbuf
.st_size
,1024));
4396 SSVAL(outbuf
,smb_vwv10
, mode
);
4398 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp
->fnum
));
4400 END_PROFILE(SMBgetattrE
);