2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
28 /* look in server.c for some explanation of these variables */
32 extern char magic_char;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
36 extern int global_oplock_break;
37 unsigned int smb_echo_count = 0;
39 extern BOOL global_encrypted_passwords_negotiated;
41 /****************************************************************************
42 Ensure we check the path in *exactly* the same way as W2K.
43 ****************************************************************************/
45 NTSTATUS check_path_syntax(const char *name)
47 while (*name == '\\' || *name == '/')
49 if (name[0] == '.' && name[1] == '\0')
50 return NT_STATUS_OBJECT_NAME_INVALID;
51 else if (name[0] == '.' && name[1] == '.' &&
52 (name[2] == '\\' || name [2] == '/' || name[2] == '\0'))
53 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
57 /****************************************************************************
58 Pull a string and check the path - provide for error return.
59 ****************************************************************************/
61 size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, int flags, NTSTATUS *err)
63 size_t ret = srvstr_pull_buf( inbuf, dest, src, dest_len, flags);
64 *err = check_path_syntax(dest);
68 /****************************************************************************
69 Reply to a special message.
70 ****************************************************************************/
72 int reply_special(char *inbuf,char *outbuf)
75 int msg_type = CVAL(inbuf,0);
76 int msg_flags = CVAL(inbuf,1);
80 static BOOL already_got_session = False;
84 memset(outbuf,'\0',smb_size);
89 case 0x81: /* session request */
91 if (already_got_session) {
92 exit_server("multiple session request not permitted");
97 if (name_len(inbuf+4) > 50 ||
98 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
99 DEBUG(0,("Invalid name length in session request\n"));
102 name_extract(inbuf,4,name1);
103 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
104 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
107 set_local_machine_name(name1, True);
108 set_remote_machine_name(name2, True);
110 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
111 get_local_machine_name(), get_remote_machine_name(),
114 if (name_type == 'R') {
115 /* We are being asked for a pathworks session ---
117 SCVAL(outbuf, 0,0x83);
121 /* only add the client's machine name to the list
122 of possibly valid usernames if we are operating
123 in share mode security */
124 if (lp_security() == SEC_SHARE) {
125 add_session_user(get_remote_machine_name());
128 reload_services(True);
131 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
133 already_got_session = True;
136 case 0x89: /* session keepalive request
137 (some old clients produce this?) */
138 SCVAL(outbuf,0,SMBkeepalive);
142 case 0x82: /* positive session response */
143 case 0x83: /* negative session response */
144 case 0x84: /* retarget session response */
145 DEBUG(0,("Unexpected session response\n"));
148 case SMBkeepalive: /* session keepalive */
153 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
154 msg_type, msg_flags));
159 /****************************************************************************
161 ****************************************************************************/
163 int reply_tcon(connection_struct *conn,
164 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
171 uint16 vuid = SVAL(inbuf,smb_uid);
175 DATA_BLOB password_blob;
177 START_PROFILE(SMBtcon);
179 *service_buf = *password = *dev = 0;
181 p = smb_buf(inbuf)+1;
182 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
183 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
185 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
187 p = strrchr_m(service_buf,'\\');
191 service = service_buf;
194 password_blob = data_blob(password, pwlen+1);
196 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
198 data_blob_clear_free(&password_blob);
201 END_PROFILE(SMBtcon);
202 return ERROR_NT(nt_status);
205 outsize = set_message(outbuf,2,0,True);
206 SSVAL(outbuf,smb_vwv0,max_recv);
207 SSVAL(outbuf,smb_vwv1,conn->cnum);
208 SSVAL(outbuf,smb_tid,conn->cnum);
210 DEBUG(3,("tcon service=%s cnum=%d\n",
211 service, conn->cnum));
213 END_PROFILE(SMBtcon);
217 /****************************************************************************
218 Reply to a tcon and X.
219 ****************************************************************************/
221 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
226 /* what the cleint thinks the device is */
227 fstring client_devicetype;
228 /* what the server tells the client the share represents */
229 const char *server_devicetype;
231 uint16 vuid = SVAL(inbuf,smb_uid);
232 int passlen = SVAL(inbuf,smb_vwv3);
235 extern BOOL global_encrypted_passwords_negotiated;
237 START_PROFILE(SMBtconX);
239 *service = *client_devicetype = 0;
241 /* we might have to close an old one */
242 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
243 close_cnum(conn,vuid);
246 if (passlen > MAX_PASS_LEN) {
247 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
250 if (global_encrypted_passwords_negotiated) {
251 password = data_blob(smb_buf(inbuf),passlen);
253 password = data_blob(smb_buf(inbuf),passlen+1);
254 /* Ensure correct termination */
255 password.data[passlen]=0;
258 p = smb_buf(inbuf) + passlen;
259 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
262 * the service name can be either: \\server\share
263 * or share directly like on the DELL PowerVault 705
266 q = strchr_m(path+2,'\\');
268 END_PROFILE(SMBtconX);
269 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
271 fstrcpy(service,q+1);
274 fstrcpy(service,path);
276 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
278 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
280 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
282 data_blob_clear_free(&password);
285 END_PROFILE(SMBtconX);
286 return ERROR_NT(nt_status);
290 server_devicetype = "IPC";
291 else if ( IS_PRINT(conn) )
292 server_devicetype = "LPT1:";
294 server_devicetype = "A:";
296 if (Protocol < PROTOCOL_NT1) {
297 set_message(outbuf,2,0,True);
299 p += srvstr_push(outbuf, p, server_devicetype, -1,
300 STR_TERMINATE|STR_ASCII);
301 set_message_end(outbuf,p);
303 /* NT sets the fstype of IPC$ to the null string */
304 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
306 set_message(outbuf,3,0,True);
309 p += srvstr_push(outbuf, p, server_devicetype, -1,
310 STR_TERMINATE|STR_ASCII);
311 p += srvstr_push(outbuf, p, fstype, -1,
314 set_message_end(outbuf,p);
316 /* what does setting this bit do? It is set by NT4 and
317 may affect the ability to autorun mounted cdroms */
318 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
319 (lp_csc_policy(SNUM(conn)) << 2));
321 init_dfsroot(conn, inbuf, outbuf);
325 DEBUG(3,("tconX service=%s \n",
328 /* set the incoming and outgoing tid to the just created one */
329 SSVAL(inbuf,smb_tid,conn->cnum);
330 SSVAL(outbuf,smb_tid,conn->cnum);
332 END_PROFILE(SMBtconX);
333 return chain_reply(inbuf,outbuf,length,bufsize);
336 /****************************************************************************
337 Reply to an unknown type.
338 ****************************************************************************/
340 int reply_unknown(char *inbuf,char *outbuf)
343 type = CVAL(inbuf,smb_com);
345 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
346 smb_fn_name(type), type, type));
348 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
351 /****************************************************************************
353 ****************************************************************************/
355 int reply_ioctl(connection_struct *conn,
356 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
358 uint16 device = SVAL(inbuf,smb_vwv1);
359 uint16 function = SVAL(inbuf,smb_vwv2);
360 uint32 ioctl_code = (device << 16) + function;
361 int replysize, outsize;
363 START_PROFILE(SMBioctl);
365 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
367 switch (ioctl_code) {
368 case IOCTL_QUERY_JOB_INFO:
372 END_PROFILE(SMBioctl);
373 return(ERROR_DOS(ERRSRV,ERRnosupport));
376 outsize = set_message(outbuf,8,replysize+1,True);
377 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
378 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
379 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
380 p = smb_buf(outbuf) + 1; /* Allow for alignment */
382 switch (ioctl_code) {
383 case IOCTL_QUERY_JOB_INFO:
385 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
387 END_PROFILE(SMBioctl);
388 return(UNIXERROR(ERRDOS,ERRbadfid));
390 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
391 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
392 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
397 END_PROFILE(SMBioctl);
401 /****************************************************************************
403 ****************************************************************************/
405 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
411 BOOL bad_path = False;
412 SMB_STRUCT_STAT sbuf;
415 START_PROFILE(SMBchkpth);
417 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE, &status);
418 if (!NT_STATUS_IS_OK(status)) {
419 END_PROFILE(SMBchkpth);
420 return ERROR_NT(status);
423 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
425 unix_convert(name,conn,0,&bad_path,&sbuf);
427 mode = SVAL(inbuf,smb_vwv0);
429 if (check_name(name,conn)) {
430 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
431 if (!(ok = S_ISDIR(sbuf.st_mode))) {
432 END_PROFILE(SMBchkpth);
433 return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
438 /* We special case this - as when a Windows machine
439 is parsing a path is steps through the components
440 one at a time - if a component fails it expects
441 ERRbadpath, not ERRbadfile.
443 if(errno == ENOENT) {
445 * Windows returns different error codes if
446 * the parent directory is valid but not the
447 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
448 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
449 * if the path is invalid.
452 END_PROFILE(SMBchkpth);
453 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
455 END_PROFILE(SMBchkpth);
456 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
458 } else if (errno == ENOTDIR) {
459 END_PROFILE(SMBchkpth);
460 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
463 END_PROFILE(SMBchkpth);
464 return(UNIXERROR(ERRDOS,ERRbadpath));
467 outsize = set_message(outbuf,0,0,True);
469 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
471 END_PROFILE(SMBchkpth);
475 /****************************************************************************
477 ****************************************************************************/
479 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
483 SMB_STRUCT_STAT sbuf;
488 BOOL bad_path = False;
492 START_PROFILE(SMBgetatr);
494 p = smb_buf(inbuf) + 1;
495 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status);
496 if (!NT_STATUS_IS_OK(status)) {
497 END_PROFILE(SMBgetatr);
498 return ERROR_NT(status);
501 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
503 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
504 under WfWg - weird! */
506 mode = aHIDDEN | aDIR;
507 if (!CAN_WRITE(conn))
513 unix_convert(fname,conn,0,&bad_path,&sbuf);
514 if (check_name(fname,conn)) {
515 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
516 mode = dos_mode(conn,fname,&sbuf);
518 mtime = sbuf.st_mtime;
523 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
529 END_PROFILE(SMBgetatr);
530 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
533 outsize = set_message(outbuf,10,0,True);
535 SSVAL(outbuf,smb_vwv0,mode);
536 if(lp_dos_filetime_resolution(SNUM(conn)) )
537 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
539 put_dos_date3(outbuf,smb_vwv1,mtime);
540 SIVAL(outbuf,smb_vwv3,(uint32)size);
542 if (Protocol >= PROTOCOL_NT1)
543 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
545 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
547 END_PROFILE(SMBgetatr);
551 /****************************************************************************
553 ****************************************************************************/
555 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
562 SMB_STRUCT_STAT sbuf;
563 BOOL bad_path = False;
567 START_PROFILE(SMBsetatr);
569 p = smb_buf(inbuf) + 1;
570 p += srvstr_get_path(inbuf, fname, p, sizeof(fname), STR_TERMINATE,&status);
571 if (!NT_STATUS_IS_OK(status)) {
572 END_PROFILE(SMBsetatr);
573 return ERROR_NT(status);
576 unix_convert(fname,conn,0,&bad_path,&sbuf);
578 mode = SVAL(inbuf,smb_vwv0);
579 mtime = make_unix_date3(inbuf+smb_vwv1);
581 if (mode != FILE_ATTRIBUTE_NORMAL) {
582 if (VALID_STAT_OF_DIR(sbuf))
587 if (check_name(fname,conn))
588 ok = (file_chmod(conn,fname,mode,NULL) == 0);
594 ok = set_filetime(conn,fname,mtime);
597 END_PROFILE(SMBsetatr);
598 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
601 outsize = set_message(outbuf,0,0,True);
603 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
605 END_PROFILE(SMBsetatr);
609 /****************************************************************************
611 ****************************************************************************/
613 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
616 SMB_BIG_UINT dfree,dsize,bsize;
617 START_PROFILE(SMBdskattr);
619 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
621 outsize = set_message(outbuf,5,0,True);
623 if (Protocol <= PROTOCOL_LANMAN2) {
624 double total_space, free_space;
625 /* we need to scale this to a number that DOS6 can handle. We
626 use floating point so we can handle large drives on systems
627 that don't have 64 bit integers
629 we end up displaying a maximum of 2G to DOS systems
631 total_space = dsize * (double)bsize;
632 free_space = dfree * (double)bsize;
634 dsize = (total_space+63*512) / (64*512);
635 dfree = (free_space+63*512) / (64*512);
637 if (dsize > 0xFFFF) dsize = 0xFFFF;
638 if (dfree > 0xFFFF) dfree = 0xFFFF;
640 SSVAL(outbuf,smb_vwv0,dsize);
641 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
642 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
643 SSVAL(outbuf,smb_vwv3,dfree);
645 SSVAL(outbuf,smb_vwv0,dsize);
646 SSVAL(outbuf,smb_vwv1,bsize/512);
647 SSVAL(outbuf,smb_vwv2,512);
648 SSVAL(outbuf,smb_vwv3,dfree);
651 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
653 END_PROFILE(SMBdskattr);
657 /****************************************************************************
659 Can be called from SMBsearch, SMBffirst or SMBfunique.
660 ****************************************************************************/
662 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
673 BOOL finished = False;
682 BOOL check_descend = False;
683 BOOL expect_close = False;
684 BOOL can_open = True;
685 BOOL bad_path = False;
687 START_PROFILE(SMBsearch);
689 *mask = *directory = *fname = 0;
691 /* If we were called as SMBffirst then we must expect close. */
692 if(CVAL(inbuf,smb_com) == SMBffirst)
695 outsize = set_message(outbuf,1,3,True);
696 maxentries = SVAL(inbuf,smb_vwv0);
697 dirtype = SVAL(inbuf,smb_vwv1);
698 p = smb_buf(inbuf) + 1;
699 p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&nt_status);
700 if (!NT_STATUS_IS_OK(nt_status)) {
701 END_PROFILE(SMBsearch);
702 return ERROR_NT(nt_status);
705 status_len = SVAL(p, 0);
708 /* dirtype &= ~aDIR; */
710 if (status_len == 0) {
711 SMB_STRUCT_STAT sbuf;
714 pstrcpy(directory,path);
716 unix_convert(directory,conn,0,&bad_path,&sbuf);
719 if (!check_name(directory,conn))
722 p = strrchr_m(dir2,'/');
731 p = strrchr_m(directory,'/');
737 if (strlen(directory) == 0)
738 pstrcpy(directory,".");
739 memset((char *)status,'\0',21);
740 SCVAL(status,0,(dirtype & 0x1F));
745 status_dirtype = CVAL(status,0) & 0x1F;
746 if (status_dirtype != (dirtype & 0x1F))
747 dirtype = status_dirtype;
749 conn->dirptr = dptr_fetch(status+12,&dptr_num);
752 string_set(&conn->dirpath,dptr_path(dptr_num));
753 pstrcpy(mask, dptr_wcard(dptr_num));
757 p = smb_buf(outbuf) + 3;
760 if (status_len == 0) {
761 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
764 END_PROFILE(SMBsearch);
765 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
767 END_PROFILE(SMBsearch);
768 return ERROR_DOS(ERRDOS,ERRnofids);
770 dptr_set_wcard(dptr_num, strdup(mask));
771 dptr_set_attr(dptr_num, dirtype);
773 dirtype = dptr_attr(dptr_num);
776 DEBUG(4,("dptr_num is %d\n",dptr_num));
779 if ((dirtype&0x1F) == aVOLID) {
781 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
782 dptr_fill(p+12,dptr_num);
783 if (dptr_zero(p+12) && (status_len==0))
787 p += DIR_STRUCT_SIZE;
789 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
790 conn->dirpath,lp_dontdescend(SNUM(conn))));
791 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
792 check_descend = True;
794 for (i=numentries;(i<maxentries) && !finished;i++) {
795 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
798 make_dir_struct(p,mask,fname,size,mode,date);
799 dptr_fill(p+12,dptr_num);
802 p += DIR_STRUCT_SIZE;
811 /* If we were called as SMBffirst with smb_search_id == NULL
812 and no entries were found then return error and close dirptr
815 if(ok && expect_close && numentries == 0 && status_len == 0) {
816 if (Protocol < PROTOCOL_NT1) {
817 SCVAL(outbuf,smb_rcls,ERRDOS);
818 SSVAL(outbuf,smb_err,ERRnofiles);
820 /* Also close the dptr - we know it's gone */
821 dptr_close(&dptr_num);
822 } else if (numentries == 0 || !ok) {
823 if (Protocol < PROTOCOL_NT1) {
824 SCVAL(outbuf,smb_rcls,ERRDOS);
825 SSVAL(outbuf,smb_err,ERRnofiles);
827 dptr_close(&dptr_num);
830 /* If we were called as SMBfunique, then we can close the dirptr now ! */
831 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
832 dptr_close(&dptr_num);
834 SSVAL(outbuf,smb_vwv0,numentries);
835 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
836 SCVAL(smb_buf(outbuf),0,5);
837 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
839 if (Protocol >= PROTOCOL_NT1)
840 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
842 outsize += DIR_STRUCT_SIZE*numentries;
843 smb_setlen(outbuf,outsize - 4);
845 if ((! *directory) && dptr_path(dptr_num))
846 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
848 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
849 smb_fn_name(CVAL(inbuf,smb_com)),
850 mask, directory, dirtype, numentries, maxentries ) );
852 END_PROFILE(SMBsearch);
856 /****************************************************************************
857 Reply to a fclose (stop directory search).
858 ****************************************************************************/
860 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
870 START_PROFILE(SMBfclose);
872 outsize = set_message(outbuf,1,0,True);
873 p = smb_buf(inbuf) + 1;
874 p += srvstr_get_path(inbuf, path, p, sizeof(path), STR_TERMINATE,&err);
875 if (!NT_STATUS_IS_OK(err)) {
876 END_PROFILE(SMBfclose);
877 return ERROR_NT(err);
880 status_len = SVAL(p,0);
883 if (status_len == 0) {
884 END_PROFILE(SMBfclose);
885 return ERROR_DOS(ERRSRV,ERRsrverror);
890 if(dptr_fetch(status+12,&dptr_num)) {
891 /* Close the dptr - we know it's gone */
892 dptr_close(&dptr_num);
895 SSVAL(outbuf,smb_vwv0,0);
897 DEBUG(3,("search close\n"));
899 END_PROFILE(SMBfclose);
903 /****************************************************************************
905 ****************************************************************************/
907 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
917 SMB_STRUCT_STAT sbuf;
918 BOOL bad_path = False;
920 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
922 START_PROFILE(SMBopen);
924 share_mode = SVAL(inbuf,smb_vwv0);
926 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status);
927 if (!NT_STATUS_IS_OK(status)) {
928 END_PROFILE(SMBopen);
929 return ERROR_NT(status);
932 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
934 unix_convert(fname,conn,0,&bad_path,&sbuf);
936 unixmode = unix_mode(conn,aARCH,fname);
938 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
939 unixmode, oplock_request,&rmode,NULL);
942 END_PROFILE(SMBopen);
943 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
947 fmode = dos_mode(conn,fname,&sbuf);
948 mtime = sbuf.st_mtime;
951 DEBUG(3,("attempt to open a directory %s\n",fname));
952 close_file(fsp,False);
953 END_PROFILE(SMBopen);
954 return ERROR_DOS(ERRDOS,ERRnoaccess);
957 outsize = set_message(outbuf,7,0,True);
958 SSVAL(outbuf,smb_vwv0,fsp->fnum);
959 SSVAL(outbuf,smb_vwv1,fmode);
960 if(lp_dos_filetime_resolution(SNUM(conn)) )
961 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
963 put_dos_date3(outbuf,smb_vwv2,mtime);
964 SIVAL(outbuf,smb_vwv4,(uint32)size);
965 SSVAL(outbuf,smb_vwv6,rmode);
967 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
968 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
970 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
971 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
972 END_PROFILE(SMBopen);
976 /****************************************************************************
977 Reply to an open and X.
978 ****************************************************************************/
980 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
983 int smb_mode = SVAL(inbuf,smb_vwv3);
984 int smb_attr = SVAL(inbuf,smb_vwv5);
985 /* Breakout the oplock request bits so we can set the
986 reply bits separately. */
987 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
988 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
989 BOOL oplock_request = ex_oplock_request | core_oplock_request;
991 int open_flags = SVAL(inbuf,smb_vwv2);
992 int smb_sattr = SVAL(inbuf,smb_vwv4);
993 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
995 int smb_ofun = SVAL(inbuf,smb_vwv8);
998 int fmode=0,mtime=0,rmode=0;
999 SMB_STRUCT_STAT sbuf;
1001 BOOL bad_path = False;
1004 START_PROFILE(SMBopenX);
1006 /* If it's an IPC, pass off the pipe handler. */
1008 if (lp_nt_pipe_support()) {
1009 END_PROFILE(SMBopenX);
1010 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
1012 END_PROFILE(SMBopenX);
1013 return ERROR_DOS(ERRSRV,ERRaccess);
1017 /* XXXX we need to handle passed times, sattr and flags */
1018 srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE,&status);
1019 if (!NT_STATUS_IS_OK(status)) {
1020 END_PROFILE(SMBopenX);
1021 return ERROR_NT(status);
1024 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1026 unix_convert(fname,conn,0,&bad_path,&sbuf);
1028 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
1030 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
1031 oplock_request, &rmode,&smb_action);
1034 END_PROFILE(SMBopenX);
1035 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1038 size = sbuf.st_size;
1039 fmode = dos_mode(conn,fname,&sbuf);
1040 mtime = sbuf.st_mtime;
1042 close_file(fsp,False);
1043 END_PROFILE(SMBopenX);
1044 return ERROR_DOS(ERRDOS,ERRnoaccess);
1047 /* If the caller set the extended oplock request bit
1048 and we granted one (by whatever means) - set the
1049 correct bit for extended oplock reply.
1052 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1053 smb_action |= EXTENDED_OPLOCK_GRANTED;
1055 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1056 smb_action |= EXTENDED_OPLOCK_GRANTED;
1058 /* If the caller set the core oplock request bit
1059 and we granted one (by whatever means) - set the
1060 correct bit for core oplock reply.
1063 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1064 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1066 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1067 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1069 set_message(outbuf,15,0,True);
1070 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1071 SSVAL(outbuf,smb_vwv3,fmode);
1072 if(lp_dos_filetime_resolution(SNUM(conn)) )
1073 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1075 put_dos_date3(outbuf,smb_vwv4,mtime);
1076 SIVAL(outbuf,smb_vwv6,(uint32)size);
1077 SSVAL(outbuf,smb_vwv8,rmode);
1078 SSVAL(outbuf,smb_vwv11,smb_action);
1080 END_PROFILE(SMBopenX);
1081 return chain_reply(inbuf,outbuf,length,bufsize);
1084 /****************************************************************************
1085 Reply to a SMBulogoffX.
1086 ****************************************************************************/
1088 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1090 uint16 vuid = SVAL(inbuf,smb_uid);
1091 user_struct *vuser = get_valid_user_struct(vuid);
1092 START_PROFILE(SMBulogoffX);
1095 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1097 /* in user level security we are supposed to close any files
1098 open by this user */
1099 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1100 file_close_user(vuid);
1102 invalidate_vuid(vuid);
1104 set_message(outbuf,2,0,True);
1106 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1108 END_PROFILE(SMBulogoffX);
1109 return chain_reply(inbuf,outbuf,length,bufsize);
1112 /****************************************************************************
1113 Reply to a mknew or a create.
1114 ****************************************************************************/
1116 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1124 BOOL bad_path = False;
1126 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1127 SMB_STRUCT_STAT sbuf;
1129 START_PROFILE(SMBcreate);
1131 com = SVAL(inbuf,smb_com);
1133 createmode = SVAL(inbuf,smb_vwv0);
1134 srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE,&status);
1135 if (!NT_STATUS_IS_OK(status)) {
1136 END_PROFILE(SMBcreate);
1137 return ERROR_NT(status);
1140 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1142 unix_convert(fname,conn,0,&bad_path,&sbuf);
1144 if (createmode & aVOLID)
1145 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1147 unixmode = unix_mode(conn,createmode,fname);
1149 if(com == SMBmknew) {
1150 /* We should fail if file exists. */
1151 ofun = FILE_CREATE_IF_NOT_EXIST;
1153 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1154 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1157 /* Open file in dos compatibility share mode. */
1158 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1159 ofun, unixmode, oplock_request, NULL, NULL);
1162 END_PROFILE(SMBcreate);
1163 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1166 outsize = set_message(outbuf,1,0,True);
1167 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1169 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1170 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1172 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1173 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1175 DEBUG( 2, ( "new file %s\n", fname ) );
1176 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1178 END_PROFILE(SMBcreate);
1182 /****************************************************************************
1183 Reply to a create temporary file.
1184 ****************************************************************************/
1186 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1192 BOOL bad_path = False;
1194 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1196 SMB_STRUCT_STAT sbuf;
1200 START_PROFILE(SMBctemp);
1202 createmode = SVAL(inbuf,smb_vwv0);
1203 srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE,&status);
1204 if (!NT_STATUS_IS_OK(status)) {
1205 END_PROFILE(SMBctemp);
1206 return ERROR_NT(status);
1208 pstrcat(fname,"\\TMXXXXXX");
1210 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1212 unix_convert(fname,conn,0,&bad_path,&sbuf);
1214 unixmode = unix_mode(conn,createmode,fname);
1216 tmpfd = smb_mkstemp(fname);
1218 END_PROFILE(SMBctemp);
1219 return(UNIXERROR(ERRDOS,ERRnoaccess));
1222 SMB_VFS_STAT(conn,fname,&sbuf);
1224 /* Open file in dos compatibility share mode. */
1225 /* We should fail if file does not exist. */
1226 fsp = open_file_shared(conn,fname,&sbuf,
1227 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1228 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1229 unixmode, oplock_request, NULL, NULL);
1231 /* close fd from smb_mkstemp() */
1235 END_PROFILE(SMBctemp);
1236 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1239 outsize = set_message(outbuf,1,0,True);
1240 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1242 /* the returned filename is relative to the directory */
1243 s = strrchr_m(fname, '/');
1249 p = smb_buf(outbuf);
1250 SSVALS(p, 0, -1); /* what is this? not in spec */
1251 SSVAL(p, 2, strlen(s));
1253 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1254 outsize = set_message_end(outbuf, p);
1256 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1257 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1259 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1260 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1262 DEBUG( 2, ( "created temp file %s\n", fname ) );
1263 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1264 fname, fsp->fd, createmode, (int)unixmode ) );
1266 END_PROFILE(SMBctemp);
1270 /*******************************************************************
1271 Check if a user is allowed to rename a file.
1272 ********************************************************************/
1274 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1280 if (!CAN_WRITE(conn))
1281 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1283 if (S_ISDIR(pst->st_mode))
1284 return NT_STATUS_OK;
1286 /* We need a better way to return NT status codes from open... */
1290 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1291 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1294 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1295 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1296 ret = NT_STATUS_SHARING_VIOLATION;
1299 unix_ERR_ntstatus = NT_STATUS_OK;
1302 close_file(fsp,False);
1303 return NT_STATUS_OK;
1306 /*******************************************************************
1307 Check if a user is allowed to delete a file.
1308 ********************************************************************/
1310 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1312 SMB_STRUCT_STAT sbuf;
1318 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1321 if (!CAN_WRITE(conn))
1322 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1324 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0)
1325 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1327 fmode = dos_mode(conn,fname,&sbuf);
1329 /* Can't delete a directory. */
1331 return NT_STATUS_FILE_IS_A_DIRECTORY;
1333 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1334 return NT_STATUS_OBJECT_NAME_INVALID;
1335 #endif /* JRATEST */
1337 if (!lp_delete_readonly(SNUM(conn))) {
1339 return NT_STATUS_CANNOT_DELETE;
1341 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1342 return NT_STATUS_NO_SUCH_FILE;
1344 /* We need a better way to return NT status codes from open... */
1348 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1349 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1352 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1353 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1354 ret = unix_ERR_ntstatus;
1355 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1356 ret = NT_STATUS_SHARING_VIOLATION;
1359 unix_ERR_ntstatus = NT_STATUS_OK;
1362 close_file(fsp,False);
1363 return NT_STATUS_OK;
1366 /****************************************************************************
1367 The guts of the unlink command, split out so it may be called by the NT SMB
1369 ****************************************************************************/
1371 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1377 NTSTATUS error = NT_STATUS_OK;
1379 BOOL bad_path = False;
1381 SMB_STRUCT_STAT sbuf;
1383 *directory = *mask = 0;
1385 /* We must check for wildcards in the name given
1386 * directly by the client - before any unmangling.
1387 * This prevents an unmangling of a UNIX name containing
1388 * a DOS wildcard like '*' or '?' from unmangling into
1389 * a wildcard delete which was not intended.
1390 * FIX for #226. JRA.
1393 has_wild = ms_has_wild(name);
1395 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1397 p = strrchr_m(name,'/');
1399 pstrcpy(directory,".");
1403 pstrcpy(directory,name);
1408 * We should only check the mangled cache
1409 * here if unix_convert failed. This means
1410 * that the path in 'mask' doesn't exist
1411 * on the file system and so we need to look
1412 * for a possible mangle. This patch from
1413 * Tine Smukavec <valentin.smukavec@hermes.si>.
1416 if (!rc && mangle_is_mangled(mask))
1417 mangle_check_cache( mask );
1420 pstrcat(directory,"/");
1421 pstrcat(directory,mask);
1422 error = can_delete(directory,conn,dirtype);
1423 if (!NT_STATUS_IS_OK(error))
1426 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1430 void *dirptr = NULL;
1433 if (check_name(directory,conn))
1434 dirptr = OpenDir(conn, directory, True);
1436 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1437 the pattern matches against the long name, otherwise the short name
1438 We don't implement this yet XXXX
1442 error = NT_STATUS_NO_SUCH_FILE;
1444 if (strequal(mask,"????????.???"))
1447 while ((dname = ReadDirName(dirptr))) {
1449 pstrcpy(fname,dname);
1451 if(!mask_match(fname, mask, case_sensitive))
1454 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1455 error = can_delete(fname,conn,dirtype);
1456 if (!NT_STATUS_IS_OK(error))
1458 if (SMB_VFS_UNLINK(conn,fname) == 0)
1460 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1466 if (count == 0 && NT_STATUS_IS_OK(error)) {
1467 error = map_nt_error_from_unix(errno);
1473 /****************************************************************************
1475 ****************************************************************************/
1477 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1484 START_PROFILE(SMBunlink);
1486 dirtype = SVAL(inbuf,smb_vwv0);
1488 srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE,&status);
1489 if (!NT_STATUS_IS_OK(status)) {
1490 END_PROFILE(SMBunlink);
1491 return ERROR_NT(status);
1494 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1496 DEBUG(3,("reply_unlink : %s\n",name));
1498 status = unlink_internals(conn, dirtype, name);
1499 if (!NT_STATUS_IS_OK(status))
1500 return ERROR_NT(status);
1503 * Win2k needs a changenotify request response before it will
1504 * update after a rename..
1506 process_pending_change_notify_queue((time_t)0);
1508 outsize = set_message(outbuf,0,0,True);
1510 END_PROFILE(SMBunlink);
1514 /****************************************************************************
1516 ****************************************************************************/
1518 void fail_readraw(void)
1521 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1523 exit_server(errstr);
1526 /****************************************************************************
1527 Use sendfile in readbraw.
1528 ****************************************************************************/
1530 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1531 ssize_t mincount, char *outbuf)
1535 #if defined(WITH_SENDFILE)
1537 * We can only use sendfile on a non-chained packet and on a file
1538 * that is exclusively oplocked. reply_readbraw has already checked the length.
1541 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1542 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1545 _smb_setlen(outbuf,nread);
1546 header.data = outbuf;
1550 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1552 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1553 * return ENOSYS then pretend we just got a normal read.
1555 if (errno == ENOSYS)
1558 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1559 fsp->fsp_name, strerror(errno) ));
1560 exit_server("send_file_readbraw sendfile failed");
1569 ret = read_file(fsp,outbuf+4,startpos,nread);
1570 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1579 _smb_setlen(outbuf,ret);
1580 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1584 /****************************************************************************
1585 Reply to a readbraw (core+ protocol).
1586 ****************************************************************************/
1588 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1590 extern struct current_user current_user;
1591 ssize_t maxcount,mincount;
1594 char *header = outbuf;
1596 START_PROFILE(SMBreadbraw);
1598 if (srv_is_signing_active()) {
1599 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1603 * Special check if an oplock break has been issued
1604 * and the readraw request croses on the wire, we must
1605 * return a zero length response here.
1608 if(global_oplock_break) {
1609 _smb_setlen(header,0);
1610 if (write_data(smbd_server_fd(),header,4) != 4)
1612 DEBUG(5,("readbraw - oplock break finished\n"));
1613 END_PROFILE(SMBreadbraw);
1617 fsp = file_fsp(inbuf,smb_vwv0);
1619 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1621 * fsp could be NULL here so use the value from the packet. JRA.
1623 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1624 _smb_setlen(header,0);
1625 if (write_data(smbd_server_fd(),header,4) != 4)
1627 END_PROFILE(SMBreadbraw);
1631 CHECK_FSP(fsp,conn);
1633 flush_write_cache(fsp, READRAW_FLUSH);
1635 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1636 if(CVAL(inbuf,smb_wct) == 10) {
1638 * This is a large offset (64 bit) read.
1640 #ifdef LARGE_SMB_OFF_T
1642 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1644 #else /* !LARGE_SMB_OFF_T */
1647 * Ensure we haven't been sent a >32 bit offset.
1650 if(IVAL(inbuf,smb_vwv8) != 0) {
1651 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1652 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1653 _smb_setlen(header,0);
1654 if (write_data(smbd_server_fd(),header,4) != 4)
1656 END_PROFILE(SMBreadbraw);
1660 #endif /* LARGE_SMB_OFF_T */
1663 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1664 _smb_setlen(header,0);
1665 if (write_data(smbd_server_fd(),header,4) != 4)
1667 END_PROFILE(SMBreadbraw);
1671 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1672 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1674 /* ensure we don't overrun the packet size */
1675 maxcount = MIN(65535,maxcount);
1677 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1678 SMB_OFF_T size = fsp->size;
1679 SMB_OFF_T sizeneeded = startpos + maxcount;
1681 if (size < sizeneeded) {
1683 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1685 if (!fsp->can_write)
1689 if (startpos >= size)
1692 nread = MIN(maxcount,(size - startpos));
1695 #if 0 /* mincount appears to be ignored in a W2K server. JRA. */
1696 if (nread < mincount)
1700 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1701 (int)maxcount, (int)mincount, (int)nread ) );
1703 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1705 DEBUG(5,("readbraw finished\n"));
1706 END_PROFILE(SMBreadbraw);
1710 /****************************************************************************
1711 Reply to a lockread (core+ protocol).
1712 ****************************************************************************/
1714 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1722 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1723 BOOL my_lock_ctx = False;
1724 START_PROFILE(SMBlockread);
1726 CHECK_FSP(fsp,conn);
1729 release_level_2_oplocks_on_change(fsp);
1731 numtoread = SVAL(inbuf,smb_vwv1);
1732 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1734 outsize = set_message(outbuf,5,3,True);
1735 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1736 data = smb_buf(outbuf) + 3;
1739 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1740 * protocol request that predates the read/write lock concept.
1741 * Thus instead of asking for a read lock here we need to ask
1742 * for a write lock. JRA.
1743 * Note that the requested lock size is unaffected by max_recv.
1746 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1747 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK, &my_lock_ctx);
1749 if (NT_STATUS_V(status)) {
1752 * We used to make lockread a blocking lock. It turns out
1753 * that this isn't on W2k. Found by the Samba 4 RAW-READ torture
1757 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
1759 * A blocking lock was requested. Package up
1760 * this smb into a queued request and push it
1761 * onto the blocking lock queue.
1763 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1764 (SMB_BIG_UINT)numtoread)) {
1765 END_PROFILE(SMBlockread);
1770 END_PROFILE(SMBlockread);
1771 return ERROR_NT(status);
1775 * However the requested READ size IS affected by max_recv. Insanity.... JRA.
1778 if (numtoread > max_recv) {
1779 DEBUG(0,("reply_lockread: requested read size (%u) is greater than maximum allowed (%u). \
1780 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1781 (unsigned int)numtoread, (unsigned int)max_recv ));
1782 numtoread = MIN(numtoread,max_recv);
1784 nread = read_file(fsp,data,startpos,numtoread);
1787 END_PROFILE(SMBlockread);
1788 return(UNIXERROR(ERRDOS,ERRnoaccess));
1792 SSVAL(outbuf,smb_vwv0,nread);
1793 SSVAL(outbuf,smb_vwv5,nread+3);
1794 SSVAL(smb_buf(outbuf),1,nread);
1796 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1797 fsp->fnum, (int)numtoread, (int)nread));
1799 END_PROFILE(SMBlockread);
1803 /****************************************************************************
1805 ****************************************************************************/
1807 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1814 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1815 START_PROFILE(SMBread);
1817 CHECK_FSP(fsp,conn);
1820 numtoread = SVAL(inbuf,smb_vwv1);
1821 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1823 outsize = set_message(outbuf,5,3,True);
1824 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1826 * The requested read size cannot be greater than max_recv. JRA.
1828 if (numtoread > max_recv) {
1829 DEBUG(0,("reply_read: requested read size (%u) is greater than maximum allowed (%u). \
1830 Returning short read of maximum allowed for compatibility with Windows 2000.\n",
1831 (unsigned int)numtoread, (unsigned int)max_recv ));
1832 numtoread = MIN(numtoread,max_recv);
1835 data = smb_buf(outbuf) + 3;
1837 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1838 END_PROFILE(SMBread);
1839 return ERROR_DOS(ERRDOS,ERRlock);
1843 nread = read_file(fsp,data,startpos,numtoread);
1846 END_PROFILE(SMBread);
1847 return(UNIXERROR(ERRDOS,ERRnoaccess));
1851 SSVAL(outbuf,smb_vwv0,nread);
1852 SSVAL(outbuf,smb_vwv5,nread+3);
1853 SCVAL(smb_buf(outbuf),0,1);
1854 SSVAL(smb_buf(outbuf),1,nread);
1856 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1857 fsp->fnum, (int)numtoread, (int)nread ) );
1859 END_PROFILE(SMBread);
1863 /****************************************************************************
1864 Reply to a read and X - possibly using sendfile.
1865 ****************************************************************************/
1867 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1868 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1871 char *data = smb_buf(outbuf);
1873 #if defined(WITH_SENDFILE)
1875 * We can only use sendfile on a non-chained packet and on a file
1876 * that is exclusively oplocked.
1879 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1880 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1881 SMB_STRUCT_STAT sbuf;
1884 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
1885 return(UNIXERROR(ERRDOS,ERRnoaccess));
1887 if (startpos > sbuf.st_size)
1890 if (smb_maxcnt > (sbuf.st_size - startpos))
1891 smb_maxcnt = (sbuf.st_size - startpos);
1893 if (smb_maxcnt == 0)
1897 * Set up the packet header before send. We
1898 * assume here the sendfile will work (get the
1899 * correct amount of data).
1902 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
1903 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1904 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1905 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1906 SCVAL(outbuf,smb_vwv0,0xFF);
1907 set_message(outbuf,12,smb_maxcnt,False);
1908 header.data = outbuf;
1909 header.length = data - outbuf;
1912 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1914 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1915 * return ENOSYS then pretend we just got a normal read.
1917 if (errno == ENOSYS)
1920 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1921 fsp->fsp_name, strerror(errno) ));
1922 exit_server("send_file_readX sendfile failed");
1925 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1926 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1934 nread = read_file(fsp,data,startpos,smb_maxcnt);
1937 END_PROFILE(SMBreadX);
1938 return(UNIXERROR(ERRDOS,ERRnoaccess));
1941 SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
1942 SSVAL(outbuf,smb_vwv5,nread);
1943 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1944 SSVAL(smb_buf(outbuf),-2,nread);
1946 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1947 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1952 /****************************************************************************
1953 Reply to a read and X.
1954 ****************************************************************************/
1956 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1958 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1959 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1961 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1963 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1966 START_PROFILE(SMBreadX);
1968 /* If it's an IPC, pass off the pipe handler. */
1970 END_PROFILE(SMBreadX);
1971 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1974 CHECK_FSP(fsp,conn);
1977 set_message(outbuf,12,0,True);
1979 if(CVAL(inbuf,smb_wct) == 12) {
1980 #ifdef LARGE_SMB_OFF_T
1982 * This is a large offset (64 bit) read.
1984 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1986 #else /* !LARGE_SMB_OFF_T */
1989 * Ensure we haven't been sent a >32 bit offset.
1992 if(IVAL(inbuf,smb_vwv10) != 0) {
1993 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1994 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1995 END_PROFILE(SMBreadX);
1996 return ERROR_DOS(ERRDOS,ERRbadaccess);
1999 #endif /* LARGE_SMB_OFF_T */
2003 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
2004 END_PROFILE(SMBreadX);
2005 return ERROR_DOS(ERRDOS,ERRlock);
2008 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
2010 nread = chain_reply(inbuf,outbuf,length,bufsize);
2012 END_PROFILE(SMBreadX);
2016 /****************************************************************************
2017 Reply to a writebraw (core+ or LANMAN1.0 protocol).
2018 ****************************************************************************/
2020 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2023 ssize_t total_written=0;
2024 size_t numtowrite=0;
2029 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2031 START_PROFILE(SMBwritebraw);
2033 if (srv_is_signing_active()) {
2034 exit_server("reply_writebraw: SMB signing is active - raw reads/writes are disallowed.");
2037 CHECK_FSP(fsp,conn);
2040 tcount = IVAL(inbuf,smb_vwv1);
2041 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2042 write_through = BITSETW(inbuf+smb_vwv7,0);
2044 /* We have to deal with slightly different formats depending
2045 on whether we are using the core+ or lanman1.0 protocol */
2047 if(Protocol <= PROTOCOL_COREPLUS) {
2048 numtowrite = SVAL(smb_buf(inbuf),-2);
2049 data = smb_buf(inbuf);
2051 numtowrite = SVAL(inbuf,smb_vwv10);
2052 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
2055 /* force the error type */
2056 SCVAL(inbuf,smb_com,SMBwritec);
2057 SCVAL(outbuf,smb_com,SMBwritec);
2059 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2060 END_PROFILE(SMBwritebraw);
2061 return(ERROR_DOS(ERRDOS,ERRlock));
2065 nwritten = write_file(fsp,data,startpos,numtowrite);
2067 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
2068 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
2070 if (nwritten < (ssize_t)numtowrite) {
2071 END_PROFILE(SMBwritebraw);
2072 return(UNIXERROR(ERRHRD,ERRdiskfull));
2075 total_written = nwritten;
2077 /* Return a message to the redirector to tell it to send more bytes */
2078 SCVAL(outbuf,smb_com,SMBwritebraw);
2079 SSVALS(outbuf,smb_vwv0,-1);
2080 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
2081 if (!send_smb(smbd_server_fd(),outbuf))
2082 exit_server("reply_writebraw: send_smb failed.");
2084 /* Now read the raw data into the buffer and write it */
2085 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
2086 exit_server("secondary writebraw failed");
2089 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
2090 numtowrite = smb_len(inbuf);
2092 /* Set up outbuf to return the correct return */
2093 outsize = set_message(outbuf,1,0,True);
2094 SCVAL(outbuf,smb_com,SMBwritec);
2095 SSVAL(outbuf,smb_vwv0,total_written);
2097 if (numtowrite != 0) {
2099 if (numtowrite > BUFFER_SIZE) {
2100 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2101 (unsigned int)numtowrite ));
2102 exit_server("secondary writebraw failed");
2105 if (tcount > nwritten+numtowrite) {
2106 DEBUG(3,("Client overestimated the write %d %d %d\n",
2107 (int)tcount,(int)nwritten,(int)numtowrite));
2110 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2111 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2113 exit_server("secondary writebraw failed");
2116 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2118 if (nwritten < (ssize_t)numtowrite) {
2119 SCVAL(outbuf,smb_rcls,ERRHRD);
2120 SSVAL(outbuf,smb_err,ERRdiskfull);
2124 total_written += nwritten;
2127 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2128 sync_file(conn,fsp);
2130 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2131 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2133 /* we won't return a status if write through is not selected - this follows what WfWg does */
2134 END_PROFILE(SMBwritebraw);
2135 if (!write_through && total_written==tcount) {
2137 #if RABBIT_PELLET_FIX
2139 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2140 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2142 if (!send_keepalive(smbd_server_fd()))
2143 exit_server("reply_writebraw: send of keepalive failed");
2151 /****************************************************************************
2152 Reply to a writeunlock (core+).
2153 ****************************************************************************/
2155 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2156 int size, int dum_buffsize)
2158 ssize_t nwritten = -1;
2163 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2165 START_PROFILE(SMBwriteunlock);
2167 CHECK_FSP(fsp,conn);
2170 numtowrite = SVAL(inbuf,smb_vwv1);
2171 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2172 data = smb_buf(inbuf) + 3;
2174 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2175 WRITE_LOCK,False)) {
2176 END_PROFILE(SMBwriteunlock);
2177 return ERROR_DOS(ERRDOS,ERRlock);
2180 /* The special X/Open SMB protocol handling of
2181 zero length writes is *NOT* done for
2186 nwritten = write_file(fsp,data,startpos,numtowrite);
2188 if (lp_syncalways(SNUM(conn)))
2189 sync_file(conn,fsp);
2191 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2192 END_PROFILE(SMBwriteunlock);
2193 return(UNIXERROR(ERRHRD,ERRdiskfull));
2196 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2197 (SMB_BIG_UINT)startpos);
2198 if (NT_STATUS_V(status)) {
2199 END_PROFILE(SMBwriteunlock);
2200 return ERROR_NT(status);
2203 outsize = set_message(outbuf,1,0,True);
2205 SSVAL(outbuf,smb_vwv0,nwritten);
2207 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2208 fsp->fnum, (int)numtowrite, (int)nwritten));
2210 END_PROFILE(SMBwriteunlock);
2214 /****************************************************************************
2216 ****************************************************************************/
2218 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2221 ssize_t nwritten = -1;
2224 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2226 START_PROFILE(SMBwrite);
2228 /* If it's an IPC, pass off the pipe handler. */
2230 END_PROFILE(SMBwrite);
2231 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2234 CHECK_FSP(fsp,conn);
2237 numtowrite = SVAL(inbuf,smb_vwv1);
2238 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2239 data = smb_buf(inbuf) + 3;
2241 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2242 END_PROFILE(SMBwrite);
2243 return ERROR_DOS(ERRDOS,ERRlock);
2247 * X/Open SMB protocol says that if smb_vwv1 is
2248 * zero then the file size should be extended or
2249 * truncated to the size given in smb_vwv[2-3].
2252 if(numtowrite == 0) {
2254 * This is actually an allocate call, and set EOF. JRA.
2256 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2258 END_PROFILE(SMBwrite);
2259 return ERROR_NT(NT_STATUS_DISK_FULL);
2261 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2263 END_PROFILE(SMBwrite);
2264 return ERROR_NT(NT_STATUS_DISK_FULL);
2267 nwritten = write_file(fsp,data,startpos,numtowrite);
2269 if (lp_syncalways(SNUM(conn)))
2270 sync_file(conn,fsp);
2272 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2273 END_PROFILE(SMBwrite);
2274 return(UNIXERROR(ERRHRD,ERRdiskfull));
2277 outsize = set_message(outbuf,1,0,True);
2279 SSVAL(outbuf,smb_vwv0,nwritten);
2281 if (nwritten < (ssize_t)numtowrite) {
2282 SCVAL(outbuf,smb_rcls,ERRHRD);
2283 SSVAL(outbuf,smb_err,ERRdiskfull);
2286 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2288 END_PROFILE(SMBwrite);
2292 /****************************************************************************
2293 Reply to a write and X.
2294 ****************************************************************************/
2296 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2298 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2299 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2300 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2301 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2302 ssize_t nwritten = -1;
2303 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2304 unsigned int smblen = smb_len(inbuf);
2306 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2307 START_PROFILE(SMBwriteX);
2309 /* If it's an IPC, pass off the pipe handler. */
2311 END_PROFILE(SMBwriteX);
2312 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2315 CHECK_FSP(fsp,conn);
2318 /* Deal with possible LARGE_WRITEX */
2320 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2322 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2323 END_PROFILE(SMBwriteX);
2324 return ERROR_DOS(ERRDOS,ERRbadmem);
2327 data = smb_base(inbuf) + smb_doff;
2329 if(CVAL(inbuf,smb_wct) == 14) {
2330 #ifdef LARGE_SMB_OFF_T
2332 * This is a large offset (64 bit) write.
2334 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2336 #else /* !LARGE_SMB_OFF_T */
2339 * Ensure we haven't been sent a >32 bit offset.
2342 if(IVAL(inbuf,smb_vwv12) != 0) {
2343 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2344 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2345 END_PROFILE(SMBwriteX);
2346 return ERROR_DOS(ERRDOS,ERRbadaccess);
2349 #endif /* LARGE_SMB_OFF_T */
2352 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2353 END_PROFILE(SMBwriteX);
2354 return ERROR_DOS(ERRDOS,ERRlock);
2357 /* X/Open SMB protocol says that, unlike SMBwrite
2358 if the length is zero then NO truncation is
2359 done, just a write of zero. To truncate a file,
2365 nwritten = write_file(fsp,data,startpos,numtowrite);
2367 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2368 END_PROFILE(SMBwriteX);
2369 return(UNIXERROR(ERRHRD,ERRdiskfull));
2372 set_message(outbuf,6,0,True);
2374 SSVAL(outbuf,smb_vwv2,nwritten);
2376 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2378 if (nwritten < (ssize_t)numtowrite) {
2379 SCVAL(outbuf,smb_rcls,ERRHRD);
2380 SSVAL(outbuf,smb_err,ERRdiskfull);
2383 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2384 fsp->fnum, (int)numtowrite, (int)nwritten));
2386 if (lp_syncalways(SNUM(conn)) || write_through)
2387 sync_file(conn,fsp);
2389 END_PROFILE(SMBwriteX);
2390 return chain_reply(inbuf,outbuf,length,bufsize);
2393 /****************************************************************************
2395 ****************************************************************************/
2397 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2403 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2404 START_PROFILE(SMBlseek);
2406 CHECK_FSP(fsp,conn);
2408 flush_write_cache(fsp, SEEK_FLUSH);
2410 mode = SVAL(inbuf,smb_vwv1) & 3;
2411 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2412 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2421 res = fsp->pos + startpos;
2432 if (umode == SEEK_END) {
2433 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2434 if(errno == EINVAL) {
2435 SMB_OFF_T current_pos = startpos;
2436 SMB_STRUCT_STAT sbuf;
2438 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2439 END_PROFILE(SMBlseek);
2440 return(UNIXERROR(ERRDOS,ERRnoaccess));
2443 current_pos += sbuf.st_size;
2445 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2450 END_PROFILE(SMBlseek);
2451 return(UNIXERROR(ERRDOS,ERRnoaccess));
2457 outsize = set_message(outbuf,2,0,True);
2458 SIVAL(outbuf,smb_vwv0,res);
2460 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2461 fsp->fnum, (double)startpos, (double)res, mode));
2463 END_PROFILE(SMBlseek);
2467 /****************************************************************************
2469 ****************************************************************************/
2471 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2473 int outsize = set_message(outbuf,0,0,True);
2474 uint16 fnum = SVAL(inbuf,smb_vwv0);
2475 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2476 START_PROFILE(SMBflush);
2479 CHECK_FSP(fsp,conn);
2482 file_sync_all(conn);
2484 sync_file(conn,fsp);
2487 DEBUG(3,("flush\n"));
2488 END_PROFILE(SMBflush);
2492 /****************************************************************************
2494 ****************************************************************************/
2496 int reply_exit(connection_struct *conn,
2497 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2500 START_PROFILE(SMBexit);
2502 file_close_pid(SVAL(inbuf,smb_pid));
2504 outsize = set_message(outbuf,0,0,True);
2506 DEBUG(3,("exit\n"));
2508 END_PROFILE(SMBexit);
2512 /****************************************************************************
2513 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2514 ****************************************************************************/
2516 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2519 extern struct current_user current_user;
2522 int32 eclass = 0, err = 0;
2523 files_struct *fsp = NULL;
2524 START_PROFILE(SMBclose);
2526 outsize = set_message(outbuf,0,0,True);
2528 /* If it's an IPC, pass off to the pipe handler. */
2530 END_PROFILE(SMBclose);
2531 return reply_pipe_close(conn, inbuf,outbuf);
2534 fsp = file_fsp(inbuf,smb_vwv0);
2537 * We can only use CHECK_FSP if we know it's not a directory.
2540 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2541 END_PROFILE(SMBclose);
2542 return ERROR_DOS(ERRDOS,ERRbadfid);
2545 if(fsp->is_directory) {
2547 * Special case - close NT SMB directory handle.
2549 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2550 close_file(fsp,True);
2553 * Close ordinary file.
2558 /* Save the name for time set in close. */
2559 pstrcpy( file_name, fsp->fsp_name);
2561 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2563 conn->num_files_open));
2566 * close_file() returns the unix errno if an error
2567 * was detected on close - normally this is due to
2568 * a disk full error. If not then it was probably an I/O error.
2571 if((close_err = close_file(fsp,True)) != 0) {
2573 END_PROFILE(SMBclose);
2574 return (UNIXERROR(ERRHRD,ERRgeneral));
2578 * Now take care of any time sent in the close.
2581 mtime = make_unix_date3(inbuf+smb_vwv1);
2583 /* try and set the date */
2584 set_filetime(conn, file_name, mtime);
2588 /* We have a cached error */
2590 END_PROFILE(SMBclose);
2591 return ERROR_DOS(eclass,err);
2594 END_PROFILE(SMBclose);
2598 /****************************************************************************
2599 Reply to a writeclose (Core+ protocol).
2600 ****************************************************************************/
2602 int reply_writeclose(connection_struct *conn,
2603 char *inbuf,char *outbuf, int size, int dum_buffsize)
2606 ssize_t nwritten = -1;
2612 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2613 START_PROFILE(SMBwriteclose);
2615 CHECK_FSP(fsp,conn);
2618 numtowrite = SVAL(inbuf,smb_vwv1);
2619 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2620 mtime = make_unix_date3(inbuf+smb_vwv4);
2621 data = smb_buf(inbuf) + 1;
2623 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2624 END_PROFILE(SMBwriteclose);
2625 return ERROR_DOS(ERRDOS,ERRlock);
2628 nwritten = write_file(fsp,data,startpos,numtowrite);
2630 set_filetime(conn, fsp->fsp_name,mtime);
2632 close_err = close_file(fsp,True);
2634 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2635 fsp->fnum, (int)numtowrite, (int)nwritten,
2636 conn->num_files_open));
2638 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2639 END_PROFILE(SMBwriteclose);
2640 return(UNIXERROR(ERRHRD,ERRdiskfull));
2643 if(close_err != 0) {
2645 END_PROFILE(SMBwriteclose);
2646 return(UNIXERROR(ERRHRD,ERRgeneral));
2649 outsize = set_message(outbuf,1,0,True);
2651 SSVAL(outbuf,smb_vwv0,nwritten);
2652 END_PROFILE(SMBwriteclose);
2656 /****************************************************************************
2658 ****************************************************************************/
2660 int reply_lock(connection_struct *conn,
2661 char *inbuf,char *outbuf, int length, int dum_buffsize)
2663 int outsize = set_message(outbuf,0,0,True);
2664 SMB_BIG_UINT count,offset;
2666 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2667 BOOL my_lock_ctx = False;
2669 START_PROFILE(SMBlock);
2671 CHECK_FSP(fsp,conn);
2673 release_level_2_oplocks_on_change(fsp);
2675 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2676 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2678 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2679 fsp->fd, fsp->fnum, (double)offset, (double)count));
2681 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK, &my_lock_ctx);
2682 if (NT_STATUS_V(status)) {
2683 if (lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
2685 * A blocking lock was requested. Package up
2686 * this smb into a queued request and push it
2687 * onto the blocking lock queue.
2689 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2690 END_PROFILE(SMBlock);
2694 END_PROFILE(SMBlock);
2695 return ERROR_NT(status);
2698 END_PROFILE(SMBlock);
2702 /****************************************************************************
2704 ****************************************************************************/
2706 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2709 int outsize = set_message(outbuf,0,0,True);
2710 SMB_BIG_UINT count,offset;
2712 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2713 START_PROFILE(SMBunlock);
2715 CHECK_FSP(fsp,conn);
2717 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2718 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2720 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2721 if (NT_STATUS_V(status)) {
2722 END_PROFILE(SMBunlock);
2723 return ERROR_NT(status);
2726 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2727 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2729 END_PROFILE(SMBunlock);
2733 /****************************************************************************
2735 ****************************************************************************/
2737 int reply_tdis(connection_struct *conn,
2738 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2740 int outsize = set_message(outbuf,0,0,True);
2742 START_PROFILE(SMBtdis);
2744 vuid = SVAL(inbuf,smb_uid);
2747 DEBUG(4,("Invalid connection in tdis\n"));
2748 END_PROFILE(SMBtdis);
2749 return ERROR_DOS(ERRSRV,ERRinvnid);
2754 close_cnum(conn,vuid);
2756 END_PROFILE(SMBtdis);
2760 /****************************************************************************
2762 ****************************************************************************/
2764 int reply_echo(connection_struct *conn,
2765 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2767 int smb_reverb = SVAL(inbuf,smb_vwv0);
2769 unsigned int data_len = smb_buflen(inbuf);
2770 int outsize = set_message(outbuf,1,data_len,True);
2771 START_PROFILE(SMBecho);
2773 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2775 /* copy any incoming data back out */
2777 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2779 if (smb_reverb > 100) {
2780 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2784 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2785 SSVAL(outbuf,smb_vwv0,seq_num);
2787 smb_setlen(outbuf,outsize - 4);
2789 if (!send_smb(smbd_server_fd(),outbuf))
2790 exit_server("reply_echo: send_smb failed.");
2793 DEBUG(3,("echo %d times\n", smb_reverb));
2797 END_PROFILE(SMBecho);
2801 /****************************************************************************
2802 Reply to a printopen.
2803 ****************************************************************************/
2805 int reply_printopen(connection_struct *conn,
2806 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2810 START_PROFILE(SMBsplopen);
2812 if (!CAN_PRINT(conn)) {
2813 END_PROFILE(SMBsplopen);
2814 return ERROR_DOS(ERRDOS,ERRnoaccess);
2817 /* Open for exclusive use, write only. */
2818 fsp = print_fsp_open(conn, NULL);
2821 END_PROFILE(SMBsplopen);
2822 return(UNIXERROR(ERRDOS,ERRnoaccess));
2825 outsize = set_message(outbuf,1,0,True);
2826 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2828 DEBUG(3,("openprint fd=%d fnum=%d\n",
2829 fsp->fd, fsp->fnum));
2831 END_PROFILE(SMBsplopen);
2835 /****************************************************************************
2836 Reply to a printclose.
2837 ****************************************************************************/
2839 int reply_printclose(connection_struct *conn,
2840 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2842 int outsize = set_message(outbuf,0,0,True);
2843 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2845 START_PROFILE(SMBsplclose);
2847 CHECK_FSP(fsp,conn);
2849 if (!CAN_PRINT(conn)) {
2850 END_PROFILE(SMBsplclose);
2851 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2854 DEBUG(3,("printclose fd=%d fnum=%d\n",
2855 fsp->fd,fsp->fnum));
2857 close_err = close_file(fsp,True);
2859 if(close_err != 0) {
2861 END_PROFILE(SMBsplclose);
2862 return(UNIXERROR(ERRHRD,ERRgeneral));
2865 END_PROFILE(SMBsplclose);
2869 /****************************************************************************
2870 Reply to a printqueue.
2871 ****************************************************************************/
2873 int reply_printqueue(connection_struct *conn,
2874 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2876 int outsize = set_message(outbuf,2,3,True);
2877 int max_count = SVAL(inbuf,smb_vwv0);
2878 int start_index = SVAL(inbuf,smb_vwv1);
2879 START_PROFILE(SMBsplretq);
2881 /* we used to allow the client to get the cnum wrong, but that
2882 is really quite gross and only worked when there was only
2883 one printer - I think we should now only accept it if they
2884 get it right (tridge) */
2885 if (!CAN_PRINT(conn)) {
2886 END_PROFILE(SMBsplretq);
2887 return ERROR_DOS(ERRDOS,ERRnoaccess);
2890 SSVAL(outbuf,smb_vwv0,0);
2891 SSVAL(outbuf,smb_vwv1,0);
2892 SCVAL(smb_buf(outbuf),0,1);
2893 SSVAL(smb_buf(outbuf),1,0);
2895 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2896 start_index, max_count));
2899 print_queue_struct *queue = NULL;
2900 print_status_struct status;
2901 char *p = smb_buf(outbuf) + 3;
2902 int count = print_queue_status(SNUM(conn), &queue, &status);
2903 int num_to_get = ABS(max_count);
2904 int first = (max_count>0?start_index:start_index+max_count+1);
2910 num_to_get = MIN(num_to_get,count-first);
2913 for (i=first;i<first+num_to_get;i++) {
2914 put_dos_date2(p,0,queue[i].time);
2915 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2916 SSVAL(p,5, queue[i].job);
2917 SIVAL(p,7,queue[i].size);
2919 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2924 outsize = set_message(outbuf,2,28*count+3,False);
2925 SSVAL(outbuf,smb_vwv0,count);
2926 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2927 SCVAL(smb_buf(outbuf),0,1);
2928 SSVAL(smb_buf(outbuf),1,28*count);
2933 DEBUG(3,("%d entries returned in queue\n",count));
2936 END_PROFILE(SMBsplretq);
2940 /****************************************************************************
2941 Reply to a printwrite.
2942 ****************************************************************************/
2944 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2947 int outsize = set_message(outbuf,0,0,True);
2949 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2951 START_PROFILE(SMBsplwr);
2953 if (!CAN_PRINT(conn)) {
2954 END_PROFILE(SMBsplwr);
2955 return ERROR_DOS(ERRDOS,ERRnoaccess);
2958 CHECK_FSP(fsp,conn);
2961 numtowrite = SVAL(smb_buf(inbuf),1);
2962 data = smb_buf(inbuf) + 3;
2964 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2965 END_PROFILE(SMBsplwr);
2966 return(UNIXERROR(ERRHRD,ERRdiskfull));
2969 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2971 END_PROFILE(SMBsplwr);
2975 /****************************************************************************
2976 The guts of the mkdir command, split out so it may be called by the NT SMB
2978 ****************************************************************************/
2980 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2982 BOOL bad_path = False;
2983 SMB_STRUCT_STAT sbuf;
2986 unix_convert(directory,conn,0,&bad_path,&sbuf);
2988 if (ms_has_wild(directory)) {
2989 return NT_STATUS_OBJECT_NAME_INVALID;
2992 if (check_name(directory, conn))
2993 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
2996 NTSTATUS nterr = NT_STATUS_OK;
2997 if(errno == ENOENT) {
2998 unix_ERR_class = ERRDOS;
3000 unix_ERR_code = ERRbadpath;
3001 nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND;
3003 unix_ERR_code = ERRbadfile;
3004 nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3007 if (!NT_STATUS_IS_OK(nterr))
3009 return map_nt_error_from_unix(errno);
3012 return NT_STATUS_OK;
3015 /****************************************************************************
3017 ****************************************************************************/
3019 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3024 START_PROFILE(SMBmkdir);
3026 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3027 if (!NT_STATUS_IS_OK(status)) {
3028 END_PROFILE(SMBmkdir);
3029 return ERROR_NT(status);
3032 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
3034 status = mkdir_internal(conn, directory);
3035 if (!NT_STATUS_IS_OK(status)) {
3036 END_PROFILE(SMBmkdir);
3037 return ERROR_NT(status);
3040 outsize = set_message(outbuf,0,0,True);
3042 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
3044 END_PROFILE(SMBmkdir);
3048 /****************************************************************************
3049 Static function used by reply_rmdir to delete an entire directory
3050 tree recursively. Return False on ok, True on fail.
3051 ****************************************************************************/
3053 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
3055 const char *dname = NULL;
3057 void *dirptr = OpenDir(conn, directory, False);
3062 while((dname = ReadDirName(dirptr))) {
3066 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3069 /* Construct the full name. */
3070 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3076 pstrcpy(fullname, directory);
3077 pstrcat(fullname, "/");
3078 pstrcat(fullname, dname);
3080 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
3085 if(st.st_mode & S_IFDIR) {
3086 if(recursive_rmdir(conn, fullname)!=0) {
3090 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
3094 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
3103 /****************************************************************************
3104 The internals of the rmdir code - called elsewhere.
3105 ****************************************************************************/
3107 BOOL rmdir_internals(connection_struct *conn, char *directory)
3111 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3112 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3114 * Check to see if the only thing in this directory are
3115 * vetoed files/directories. If so then delete them and
3116 * retry. If we fail to delete any of them (and we *don't*
3117 * do a recursive delete) then fail the rmdir.
3119 BOOL all_veto_files = True;
3121 void *dirptr = OpenDir(conn, directory, False);
3123 if(dirptr != NULL) {
3124 int dirpos = TellDir(dirptr);
3125 while ((dname = ReadDirName(dirptr))) {
3126 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3128 if(!IS_VETO_PATH(conn, dname)) {
3129 all_veto_files = False;
3134 if(all_veto_files) {
3135 SeekDir(dirptr,dirpos);
3136 while ((dname = ReadDirName(dirptr))) {
3140 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3143 /* Construct the full name. */
3144 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3149 pstrcpy(fullname, directory);
3150 pstrcat(fullname, "/");
3151 pstrcat(fullname, dname);
3153 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3155 if(st.st_mode & S_IFDIR) {
3156 if(lp_recursive_veto_delete(SNUM(conn))) {
3157 if(recursive_rmdir(conn, fullname) != 0)
3160 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3162 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3166 /* Retry the rmdir */
3167 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3177 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3182 /****************************************************************************
3184 ****************************************************************************/
3186 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3191 BOOL bad_path = False;
3192 SMB_STRUCT_STAT sbuf;
3194 START_PROFILE(SMBrmdir);
3196 srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE,&status);
3197 if (!NT_STATUS_IS_OK(status)) {
3198 END_PROFILE(SMBrmdir);
3199 return ERROR_NT(status);
3202 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3204 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3206 if (check_name(directory,conn)) {
3207 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3208 ok = rmdir_internals(conn, directory);
3212 END_PROFILE(SMBrmdir);
3213 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3216 outsize = set_message(outbuf,0,0,True);
3218 DEBUG( 3, ( "rmdir %s\n", directory ) );
3220 END_PROFILE(SMBrmdir);
3224 /*******************************************************************
3225 Resolve wildcards in a filename rename.
3226 ********************************************************************/
3228 static BOOL resolve_wildcards(const char *name1, char *name2)
3230 fstring root1,root2;
3232 char *p,*p2, *pname1, *pname2;
3233 int available_space;
3236 pname1 = strrchr_m(name1,'/');
3237 pname2 = strrchr_m(name2,'/');
3239 if (!pname1 || !pname2)
3242 fstrcpy(root1,pname1);
3243 fstrcpy(root2,pname2);
3244 p = strrchr_m(root1,'.');
3251 p = strrchr_m(root2,'.');
3285 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3288 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3290 pstrcpy_base(pname2, root2, name2);
3296 /****************************************************************************
3297 Ensure open files have their names updates.
3298 ****************************************************************************/
3300 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3303 BOOL did_rename = False;
3305 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3306 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3307 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3308 fsp->fsp_name, newname ));
3309 string_set(&fsp->fsp_name, newname);
3314 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3315 (unsigned int)dev, (double)inode, newname ));
3318 /****************************************************************************
3319 Rename an open file - given an fsp.
3320 ****************************************************************************/
3322 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3324 SMB_STRUCT_STAT sbuf;
3325 BOOL bad_path = False;
3326 pstring newname_last_component;
3327 NTSTATUS error = NT_STATUS_OK;
3331 unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3333 /* Ensure newname contains a '/' */
3334 if(strrchr_m(newname,'/') == 0) {
3337 pstrcpy(tmpstr, "./");
3338 pstrcat(tmpstr, newname);
3339 pstrcpy(newname, tmpstr);
3343 * Check for special case with case preserving and not
3344 * case sensitive. If the old last component differs from the original
3345 * last component only by case, then we should allow
3346 * the rename (user is trying to change the case of the
3350 if((case_sensitive == False) && (case_preserve == True) &&
3351 strequal(newname, fsp->fsp_name)) {
3353 pstring newname_modified_last_component;
3356 * Get the last component of the modified name.
3357 * Note that we guarantee that newname contains a '/'
3360 p = strrchr_m(newname,'/');
3361 pstrcpy(newname_modified_last_component,p+1);
3363 if(strcsequal(newname_modified_last_component,
3364 newname_last_component) == False) {
3366 * Replace the modified last component with
3369 pstrcpy(p+1, newname_last_component);
3374 * If the src and dest names are identical - including case,
3375 * don't do the rename, just return success.
3378 if (strcsequal(fsp->fsp_name, newname)) {
3379 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3381 return NT_STATUS_OK;
3384 dest_exists = vfs_object_exist(conn,newname,NULL);
3386 if(!replace_if_exists && dest_exists) {
3387 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3388 fsp->fsp_name,newname));
3389 return NT_STATUS_OBJECT_NAME_COLLISION;
3392 error = can_rename(newname,conn,&sbuf);
3394 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3395 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3396 nt_errstr(error), fsp->fsp_name,newname));
3397 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3398 error = NT_STATUS_ACCESS_DENIED;
3402 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3403 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3404 fsp->fsp_name,newname));
3405 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3406 return NT_STATUS_OK;
3409 if (errno == ENOTDIR || errno == EISDIR)
3410 error = NT_STATUS_OBJECT_NAME_COLLISION;
3412 error = map_nt_error_from_unix(errno);
3414 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3415 nt_errstr(error), fsp->fsp_name,newname));
3420 /****************************************************************************
3421 The guts of the rename command, split out so it may be called by the NT SMB
3423 ****************************************************************************/
3425 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3429 pstring newname_last_component;
3432 BOOL bad_path1 = False;
3433 BOOL bad_path2 = False;
3435 NTSTATUS error = NT_STATUS_OK;
3437 SMB_STRUCT_STAT sbuf1, sbuf2;
3439 *directory = *mask = 0;
3443 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3444 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3447 * Split the old name into directory and last component
3448 * strings. Note that unix_convert may have stripped off a
3449 * leading ./ from both name and newname if the rename is
3450 * at the root of the share. We need to make sure either both
3451 * name and newname contain a / character or neither of them do
3452 * as this is checked in resolve_wildcards().
3455 p = strrchr_m(name,'/');
3457 pstrcpy(directory,".");
3461 pstrcpy(directory,name);
3463 *p = '/'; /* Replace needed for exceptional test below. */
3467 * We should only check the mangled cache
3468 * here if unix_convert failed. This means
3469 * that the path in 'mask' doesn't exist
3470 * on the file system and so we need to look
3471 * for a possible mangle. This patch from
3472 * Tine Smukavec <valentin.smukavec@hermes.si>.
3475 if (!rc && mangle_is_mangled(mask))
3476 mangle_check_cache( mask );
3478 has_wild = ms_has_wild(mask);
3482 * No wildcards - just process the one file.
3484 BOOL is_short_name = mangle_is_8_3(name, True);
3486 /* Add a terminating '/' to the directory name. */
3487 pstrcat(directory,"/");
3488 pstrcat(directory,mask);
3490 /* Ensure newname contains a '/' also */
3491 if(strrchr_m(newname,'/') == 0) {
3494 pstrcpy(tmpstr, "./");
3495 pstrcat(tmpstr, newname);
3496 pstrcpy(newname, tmpstr);
3499 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3500 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3501 case_sensitive, case_preserve, short_case_preserve, directory,
3502 newname, newname_last_component, is_short_name));
3505 * Check for special case with case preserving and not
3506 * case sensitive, if directory and newname are identical,
3507 * and the old last component differs from the original
3508 * last component only by case, then we should allow
3509 * the rename (user is trying to change the case of the
3512 if((case_sensitive == False) &&
3513 (((case_preserve == True) &&
3514 (is_short_name == False)) ||
3515 ((short_case_preserve == True) &&
3516 (is_short_name == True))) &&
3517 strcsequal(directory, newname)) {
3518 pstring newname_modified_last_component;
3521 * Get the last component of the modified name.
3522 * Note that we guarantee that newname contains a '/'
3525 p = strrchr_m(newname,'/');
3526 pstrcpy(newname_modified_last_component,p+1);
3528 if(strcsequal(newname_modified_last_component,
3529 newname_last_component) == False) {
3531 * Replace the modified last component with
3534 pstrcpy(p+1, newname_last_component);
3538 resolve_wildcards(directory,newname);
3541 * The source object must exist.
3544 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3545 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3546 directory,newname));
3548 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3550 * Must return different errors depending on whether the parent
3551 * directory existed or not.
3554 p = strrchr_m(directory, '/');
3556 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3558 if (vfs_object_exist(conn, directory, NULL))
3559 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3560 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3562 error = map_nt_error_from_unix(errno);
3563 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3564 nt_errstr(error), directory,newname));
3569 error = can_rename(directory,conn,&sbuf1);
3571 if (!NT_STATUS_IS_OK(error)) {
3572 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3573 nt_errstr(error), directory,newname));
3578 * If the src and dest names are identical - including case,
3579 * don't do the rename, just return success.
3582 if (strcsequal(directory, newname)) {
3583 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3584 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3585 return NT_STATUS_OK;
3588 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3589 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3590 directory,newname));
3591 return NT_STATUS_OBJECT_NAME_COLLISION;
3594 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3595 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3596 directory,newname));
3597 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3598 return NT_STATUS_OK;
3601 if (errno == ENOTDIR || errno == EISDIR)
3602 error = NT_STATUS_OBJECT_NAME_COLLISION;
3604 error = map_nt_error_from_unix(errno);
3606 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3607 nt_errstr(error), directory,newname));
3612 * Wildcards - process each file that matches.
3614 void *dirptr = NULL;
3618 if (check_name(directory,conn))
3619 dirptr = OpenDir(conn, directory, True);
3622 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3624 if (strequal(mask,"????????.???"))
3627 while ((dname = ReadDirName(dirptr))) {
3630 pstrcpy(fname,dname);
3632 if(!mask_match(fname, mask, case_sensitive))
3635 error = NT_STATUS_ACCESS_DENIED;
3636 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3637 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3638 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3639 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3642 error = can_rename(fname,conn,&sbuf1);
3643 if (!NT_STATUS_IS_OK(error)) {
3644 DEBUG(6,("rename %s refused\n", fname));
3647 pstrcpy(destname,newname);
3649 if (!resolve_wildcards(fname,destname)) {
3650 DEBUG(6,("resolve_wildcards %s %s failed\n",
3655 if (!replace_if_exists &&
3656 vfs_file_exist(conn,destname, NULL)) {
3657 DEBUG(6,("file_exist %s\n", destname));
3658 error = NT_STATUS_OBJECT_NAME_COLLISION;
3662 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3663 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3666 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3672 if (count == 0 && NT_STATUS_IS_OK(error)) {
3673 error = map_nt_error_from_unix(errno);
3679 /****************************************************************************
3681 ****************************************************************************/
3683 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3692 START_PROFILE(SMBmv);
3694 p = smb_buf(inbuf) + 1;
3695 p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3696 if (!NT_STATUS_IS_OK(status)) {
3698 return ERROR_NT(status);
3701 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3702 if (!NT_STATUS_IS_OK(status)) {
3704 return ERROR_NT(status);
3707 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3708 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3710 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3712 status = rename_internals(conn, name, newname, False);
3713 if (!NT_STATUS_IS_OK(status)) {
3715 return ERROR_NT(status);
3719 * Win2k needs a changenotify request response before it will
3720 * update after a rename..
3722 process_pending_change_notify_queue((time_t)0);
3723 outsize = set_message(outbuf,0,0,True);
3729 /*******************************************************************
3730 Copy a file as part of a reply_copy.
3731 ******************************************************************/
3733 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3734 int count,BOOL target_is_directory, int *err_ret)
3737 SMB_STRUCT_STAT src_sbuf, sbuf2;
3739 files_struct *fsp1,*fsp2;
3744 pstrcpy(dest,dest1);
3745 if (target_is_directory) {
3746 char *p = strrchr_m(src,'/');
3755 if (!vfs_file_exist(conn,src,&src_sbuf))
3758 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3759 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3764 if (!target_is_directory && count)
3765 ofun = FILE_EXISTS_OPEN;
3767 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3768 ZERO_STRUCTP(&sbuf2);
3770 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3771 ofun,src_sbuf.st_mode,0,&Access,&action);
3774 close_file(fsp1,False);
3778 if ((ofun&3) == 1) {
3779 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3780 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3782 * Stop the copy from occurring.
3785 src_sbuf.st_size = 0;
3789 if (src_sbuf.st_size)
3790 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3792 close_file(fsp1,False);
3794 /* Ensure the modtime is set correctly on the destination file. */
3795 fsp2->pending_modtime = src_sbuf.st_mtime;
3798 * As we are opening fsp1 read-only we only expect
3799 * an error on close on fsp2 if we are out of space.
3800 * Thus we don't look at the error return from the
3803 *err_ret = close_file(fsp2,False);
3805 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3808 /****************************************************************************
3809 Reply to a file copy.
3810 ****************************************************************************/
3812 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3817 pstring mask,newname;
3820 int error = ERRnoaccess;
3824 int tid2 = SVAL(inbuf,smb_vwv0);
3825 int ofun = SVAL(inbuf,smb_vwv1);
3826 int flags = SVAL(inbuf,smb_vwv2);
3827 BOOL target_is_directory=False;
3828 BOOL bad_path1 = False;
3829 BOOL bad_path2 = False;
3831 SMB_STRUCT_STAT sbuf1, sbuf2;
3834 START_PROFILE(SMBcopy);
3836 *directory = *mask = 0;
3839 p += srvstr_get_path(inbuf, name, p, sizeof(name), STR_TERMINATE,&status);
3840 if (!NT_STATUS_IS_OK(status)) {
3841 END_PROFILE(SMBcopy);
3842 return ERROR_NT(status);
3844 p += srvstr_get_path(inbuf, newname, p, sizeof(newname), STR_TERMINATE,&status);
3845 if (!NT_STATUS_IS_OK(status)) {
3846 END_PROFILE(SMBcopy);
3847 return ERROR_NT(status);
3850 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3852 if (tid2 != conn->cnum) {
3853 /* can't currently handle inter share copies XXXX */
3854 DEBUG(3,("Rejecting inter-share copy\n"));
3855 END_PROFILE(SMBcopy);
3856 return ERROR_DOS(ERRSRV,ERRinvdevice);
3859 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3860 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3862 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3863 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3865 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3867 if ((flags&1) && target_is_directory) {
3868 END_PROFILE(SMBcopy);
3869 return ERROR_DOS(ERRDOS,ERRbadfile);
3872 if ((flags&2) && !target_is_directory) {
3873 END_PROFILE(SMBcopy);
3874 return ERROR_DOS(ERRDOS,ERRbadpath);
3877 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3878 /* wants a tree copy! XXXX */
3879 DEBUG(3,("Rejecting tree copy\n"));
3880 END_PROFILE(SMBcopy);
3881 return ERROR_DOS(ERRSRV,ERRerror);
3884 p = strrchr_m(name,'/');
3886 pstrcpy(directory,"./");
3890 pstrcpy(directory,name);
3895 * We should only check the mangled cache
3896 * here if unix_convert failed. This means
3897 * that the path in 'mask' doesn't exist
3898 * on the file system and so we need to look
3899 * for a possible mangle. This patch from
3900 * Tine Smukavec <valentin.smukavec@hermes.si>.
3903 if (!rc && mangle_is_mangled(mask))
3904 mangle_check_cache( mask );
3906 has_wild = ms_has_wild(mask);
3909 pstrcat(directory,"/");
3910 pstrcat(directory,mask);
3911 if (resolve_wildcards(directory,newname) &&
3912 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3916 END_PROFILE(SMBcopy);
3917 return(UNIXERROR(ERRHRD,ERRgeneral));
3920 exists = vfs_file_exist(conn,directory,NULL);
3923 void *dirptr = NULL;
3927 if (check_name(directory,conn))
3928 dirptr = OpenDir(conn, directory, True);
3933 if (strequal(mask,"????????.???"))
3936 while ((dname = ReadDirName(dirptr))) {
3938 pstrcpy(fname,dname);
3940 if(!mask_match(fname, mask, case_sensitive))
3943 error = ERRnoaccess;
3944 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3945 pstrcpy(destname,newname);
3946 if (resolve_wildcards(fname,destname) &&
3947 copy_file(fname,destname,conn,ofun,
3948 count,target_is_directory,&err))
3950 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3958 /* Error on close... */
3960 END_PROFILE(SMBcopy);
3961 return(UNIXERROR(ERRHRD,ERRgeneral));
3965 END_PROFILE(SMBcopy);
3966 return ERROR_DOS(ERRDOS,error);
3968 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3969 unix_ERR_class = ERRDOS;
3970 unix_ERR_code = ERRbadpath;
3972 END_PROFILE(SMBcopy);
3973 return(UNIXERROR(ERRDOS,error));
3977 outsize = set_message(outbuf,1,0,True);
3978 SSVAL(outbuf,smb_vwv0,count);
3980 END_PROFILE(SMBcopy);
3984 /****************************************************************************
3986 ****************************************************************************/
3988 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3996 START_PROFILE(pathworks_setdir);
3999 if (!CAN_SETDIR(snum)) {
4000 END_PROFILE(pathworks_setdir);
4001 return ERROR_DOS(ERRDOS,ERRnoaccess);
4004 srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE,&status);
4005 if (!NT_STATUS_IS_OK(status)) {
4006 END_PROFILE(pathworks_setdir);
4007 return ERROR_NT(status);
4010 if (strlen(newdir) == 0) {
4013 ok = vfs_directory_exist(conn,newdir,NULL);
4015 string_set(&conn->connectpath,newdir);
4019 END_PROFILE(pathworks_setdir);
4020 return ERROR_DOS(ERRDOS,ERRbadpath);
4023 outsize = set_message(outbuf,0,0,True);
4024 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
4026 DEBUG(3,("setdir %s\n", newdir));
4028 END_PROFILE(pathworks_setdir);
4032 /****************************************************************************
4033 Get a lock pid, dealing with large count requests.
4034 ****************************************************************************/
4036 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
4038 if(!large_file_format)
4039 return SVAL(data,SMB_LPID_OFFSET(data_offset));
4041 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
4044 /****************************************************************************
4045 Get a lock count, dealing with large count requests.
4046 ****************************************************************************/
4048 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
4050 SMB_BIG_UINT count = 0;
4052 if(!large_file_format) {
4053 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
4056 #if defined(HAVE_LONGLONG)
4057 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
4058 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
4059 #else /* HAVE_LONGLONG */
4062 * NT4.x seems to be broken in that it sends large file (64 bit)
4063 * lockingX calls even if the CAP_LARGE_FILES was *not*
4064 * negotiated. For boxes without large unsigned ints truncate the
4065 * lock count by dropping the top 32 bits.
4068 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
4069 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
4070 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
4071 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
4072 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
4075 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
4076 #endif /* HAVE_LONGLONG */
4082 #if !defined(HAVE_LONGLONG)
4083 /****************************************************************************
4084 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
4085 ****************************************************************************/
4087 static uint32 map_lock_offset(uint32 high, uint32 low)
4091 uint32 highcopy = high;
4094 * Try and find out how many significant bits there are in high.
4097 for(i = 0; highcopy; i++)
4101 * We use 31 bits not 32 here as POSIX
4102 * lock offsets may not be negative.
4105 mask = (~0) << (31 - i);
4108 return 0; /* Fail. */
4114 #endif /* !defined(HAVE_LONGLONG) */
4116 /****************************************************************************
4117 Get a lock offset, dealing with large offset requests.
4118 ****************************************************************************/
4120 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
4122 SMB_BIG_UINT offset = 0;
4126 if(!large_file_format) {
4127 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
4130 #if defined(HAVE_LONGLONG)
4131 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
4132 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
4133 #else /* HAVE_LONGLONG */
4136 * NT4.x seems to be broken in that it sends large file (64 bit)
4137 * lockingX calls even if the CAP_LARGE_FILES was *not*
4138 * negotiated. For boxes without large unsigned ints mangle the
4139 * lock offset by mapping the top 32 bits onto the lower 32.
4142 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4143 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4144 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4147 if((new_low = map_lock_offset(high, low)) == 0) {
4149 return (SMB_BIG_UINT)-1;
4152 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4153 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4154 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4155 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4158 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4159 #endif /* HAVE_LONGLONG */
4165 /****************************************************************************
4166 Reply to a lockingX request.
4167 ****************************************************************************/
4169 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4171 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4172 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4173 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4174 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4175 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4176 SMB_BIG_UINT count = 0, offset = 0;
4178 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4181 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4183 BOOL my_lock_ctx = False;
4186 START_PROFILE(SMBlockingX);
4188 CHECK_FSP(fsp,conn);
4190 data = smb_buf(inbuf);
4192 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4193 /* we don't support these - and CANCEL_LOCK makes w2k
4194 and XP reboot so I don't really want to be
4195 compatible! (tridge) */
4196 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4199 /* Check if this is an oplock break on a file
4200 we have granted an oplock on.
4202 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4203 /* Client can insist on breaking to none. */
4204 BOOL break_to_none = (oplocklevel == 0);
4206 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4207 (unsigned int)oplocklevel, fsp->fnum ));
4210 * Make sure we have granted an exclusive or batch oplock on this file.
4213 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4214 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4215 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4217 /* if this is a pure oplock break request then don't send a reply */
4218 if (num_locks == 0 && num_ulocks == 0) {
4219 END_PROFILE(SMBlockingX);
4222 END_PROFILE(SMBlockingX);
4223 return ERROR_DOS(ERRDOS,ERRlock);
4227 if (remove_oplock(fsp, break_to_none) == False) {
4228 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4232 /* if this is a pure oplock break request then don't send a reply */
4233 if (num_locks == 0 && num_ulocks == 0) {
4234 /* Sanity check - ensure a pure oplock break is not a
4236 if(CVAL(inbuf,smb_vwv0) != 0xff)
4237 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4238 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4239 END_PROFILE(SMBlockingX);
4245 * We do this check *after* we have checked this is not a oplock break
4246 * response message. JRA.
4249 release_level_2_oplocks_on_change(fsp);
4251 /* Data now points at the beginning of the list
4252 of smb_unlkrng structs */
4253 for(i = 0; i < (int)num_ulocks; i++) {
4254 lock_pid = get_lock_pid( data, i, large_file_format);
4255 count = get_lock_count( data, i, large_file_format);
4256 offset = get_lock_offset( data, i, large_file_format, &err);
4259 * There is no error code marked "stupid client bug".... :-).
4262 END_PROFILE(SMBlockingX);
4263 return ERROR_DOS(ERRDOS,ERRnoaccess);
4266 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4267 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4269 status = do_unlock(fsp,conn,lock_pid,count,offset);
4270 if (NT_STATUS_V(status)) {
4271 END_PROFILE(SMBlockingX);
4272 return ERROR_NT(status);
4276 /* Setup the timeout in seconds. */
4278 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500);
4280 /* Now do any requested locks */
4281 data += ((large_file_format ? 20 : 10)*num_ulocks);
4283 /* Data now points at the beginning of the list
4284 of smb_lkrng structs */
4286 for(i = 0; i < (int)num_locks; i++) {
4287 lock_pid = get_lock_pid( data, i, large_file_format);
4288 count = get_lock_count( data, i, large_file_format);
4289 offset = get_lock_offset( data, i, large_file_format, &err);
4292 * There is no error code marked "stupid client bug".... :-).
4295 END_PROFILE(SMBlockingX);
4296 return ERROR_DOS(ERRDOS,ERRnoaccess);
4299 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4300 (double)offset, (double)count, (unsigned int)lock_pid,
4301 fsp->fsp_name, (int)lock_timeout ));
4303 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4304 ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx);
4305 if (NT_STATUS_V(status)) {
4306 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && !my_lock_ctx && ERROR_WAS_LOCK_DENIED(status)) {
4308 * A blocking lock was requested. Package up
4309 * this smb into a queued request and push it
4310 * onto the blocking lock queue.
4312 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4313 END_PROFILE(SMBlockingX);
4321 /* If any of the above locks failed, then we must unlock
4322 all of the previous locks (X/Open spec). */
4323 if (i != num_locks && num_locks != 0) {
4325 * Ensure we don't do a remove on the lock that just failed,
4326 * as under POSIX rules, if we have a lock already there, we
4327 * will delete it (and we shouldn't) .....
4329 for(i--; i >= 0; i--) {
4330 lock_pid = get_lock_pid( data, i, large_file_format);
4331 count = get_lock_count( data, i, large_file_format);
4332 offset = get_lock_offset( data, i, large_file_format, &err);
4335 * There is no error code marked "stupid client bug".... :-).
4338 END_PROFILE(SMBlockingX);
4339 return ERROR_DOS(ERRDOS,ERRnoaccess);
4342 do_unlock(fsp,conn,lock_pid,count,offset);
4344 END_PROFILE(SMBlockingX);
4345 return ERROR_NT(status);
4348 set_message(outbuf,2,0,True);
4350 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4351 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4353 END_PROFILE(SMBlockingX);
4354 return chain_reply(inbuf,outbuf,length,bufsize);
4357 /****************************************************************************
4358 Reply to a SMBreadbmpx (read block multiplex) request.
4359 ****************************************************************************/
4361 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4372 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4373 START_PROFILE(SMBreadBmpx);
4375 /* this function doesn't seem to work - disable by default */
4376 if (!lp_readbmpx()) {
4377 END_PROFILE(SMBreadBmpx);
4378 return ERROR_DOS(ERRSRV,ERRuseSTD);
4381 outsize = set_message(outbuf,8,0,True);
4383 CHECK_FSP(fsp,conn);
4386 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4387 maxcount = SVAL(inbuf,smb_vwv3);
4389 data = smb_buf(outbuf);
4390 pad = ((long)data)%4;
4395 max_per_packet = bufsize-(outsize+pad);
4399 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4400 END_PROFILE(SMBreadBmpx);
4401 return ERROR_DOS(ERRDOS,ERRlock);
4405 size_t N = MIN(max_per_packet,tcount-total_read);
4407 nread = read_file(fsp,data,startpos,N);
4412 if (nread < (ssize_t)N)
4413 tcount = total_read + nread;
4415 set_message(outbuf,8,nread,False);
4416 SIVAL(outbuf,smb_vwv0,startpos);
4417 SSVAL(outbuf,smb_vwv2,tcount);
4418 SSVAL(outbuf,smb_vwv6,nread);
4419 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4421 if (!send_smb(smbd_server_fd(),outbuf))
4422 exit_server("reply_readbmpx: send_smb failed.");
4424 total_read += nread;
4426 } while (total_read < (ssize_t)tcount);
4428 END_PROFILE(SMBreadBmpx);
4432 /****************************************************************************
4433 Reply to a SMBsetattrE.
4434 ****************************************************************************/
4436 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4438 struct utimbuf unix_times;
4440 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4441 START_PROFILE(SMBsetattrE);
4443 outsize = set_message(outbuf,0,0,True);
4445 if(!fsp || (fsp->conn != conn)) {
4446 END_PROFILE(SMBgetattrE);
4447 return ERROR_DOS(ERRDOS,ERRbadfid);
4451 * Convert the DOS times into unix times. Ignore create
4452 * time as UNIX can't set this.
4455 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4456 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4459 * Patch from Ray Frush <frush@engr.colostate.edu>
4460 * Sometimes times are sent as zero - ignore them.
4463 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4464 /* Ignore request */
4465 if( DEBUGLVL( 3 ) ) {
4466 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4467 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4469 END_PROFILE(SMBsetattrE);
4471 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4472 /* set modify time = to access time if modify time was 0 */
4473 unix_times.modtime = unix_times.actime;
4476 /* Set the date on this file */
4477 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4478 END_PROFILE(SMBsetattrE);
4479 return ERROR_DOS(ERRDOS,ERRnoaccess);
4482 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4483 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4485 END_PROFILE(SMBsetattrE);
4490 /* Back from the dead for OS/2..... JRA. */
4492 /****************************************************************************
4493 Reply to a SMBwritebmpx (write block multiplex primary) request.
4494 ****************************************************************************/
4496 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4499 ssize_t nwritten = -1;
4506 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4507 START_PROFILE(SMBwriteBmpx);
4509 CHECK_FSP(fsp,conn);
4513 tcount = SVAL(inbuf,smb_vwv1);
4514 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4515 write_through = BITSETW(inbuf+smb_vwv7,0);
4516 numtowrite = SVAL(inbuf,smb_vwv10);
4517 smb_doff = SVAL(inbuf,smb_vwv11);
4519 data = smb_base(inbuf) + smb_doff;
4521 /* If this fails we need to send an SMBwriteC response,
4522 not an SMBwritebmpx - set this up now so we don't forget */
4523 SCVAL(outbuf,smb_com,SMBwritec);
4525 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4526 END_PROFILE(SMBwriteBmpx);
4527 return(ERROR_DOS(ERRDOS,ERRlock));
4530 nwritten = write_file(fsp,data,startpos,numtowrite);
4532 if(lp_syncalways(SNUM(conn)) || write_through)
4533 sync_file(conn,fsp);
4535 if(nwritten < (ssize_t)numtowrite) {
4536 END_PROFILE(SMBwriteBmpx);
4537 return(UNIXERROR(ERRHRD,ERRdiskfull));
4540 /* If the maximum to be written to this file
4541 is greater than what we just wrote then set
4542 up a secondary struct to be attached to this
4543 fd, we will use this to cache error messages etc. */
4545 if((ssize_t)tcount > nwritten) {
4546 write_bmpx_struct *wbms;
4547 if(fsp->wbmpx_ptr != NULL)
4548 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4550 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4552 DEBUG(0,("Out of memory in reply_readmpx\n"));
4553 END_PROFILE(SMBwriteBmpx);
4554 return(ERROR_DOS(ERRSRV,ERRnoresource));
4556 wbms->wr_mode = write_through;
4557 wbms->wr_discard = False; /* No errors yet */
4558 wbms->wr_total_written = nwritten;
4559 wbms->wr_errclass = 0;
4561 fsp->wbmpx_ptr = wbms;
4564 /* We are returning successfully, set the message type back to
4566 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4568 outsize = set_message(outbuf,1,0,True);
4570 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4572 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4573 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4575 if (write_through && tcount==nwritten) {
4576 /* We need to send both a primary and a secondary response */
4577 smb_setlen(outbuf,outsize - 4);
4578 if (!send_smb(smbd_server_fd(),outbuf))
4579 exit_server("reply_writebmpx: send_smb failed.");
4581 /* Now the secondary */
4582 outsize = set_message(outbuf,1,0,True);
4583 SCVAL(outbuf,smb_com,SMBwritec);
4584 SSVAL(outbuf,smb_vwv0,nwritten);
4587 END_PROFILE(SMBwriteBmpx);
4591 /****************************************************************************
4592 Reply to a SMBwritebs (write block multiplex secondary) request.
4593 ****************************************************************************/
4595 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4598 ssize_t nwritten = -1;
4605 write_bmpx_struct *wbms;
4606 BOOL send_response = False;
4607 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4608 START_PROFILE(SMBwriteBs);
4610 CHECK_FSP(fsp,conn);
4613 tcount = SVAL(inbuf,smb_vwv1);
4614 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4615 numtowrite = SVAL(inbuf,smb_vwv6);
4616 smb_doff = SVAL(inbuf,smb_vwv7);
4618 data = smb_base(inbuf) + smb_doff;
4620 /* We need to send an SMBwriteC response, not an SMBwritebs */
4621 SCVAL(outbuf,smb_com,SMBwritec);
4623 /* This fd should have an auxiliary struct attached,
4624 check that it does */
4625 wbms = fsp->wbmpx_ptr;
4627 END_PROFILE(SMBwriteBs);
4631 /* If write through is set we can return errors, else we must cache them */
4632 write_through = wbms->wr_mode;
4634 /* Check for an earlier error */
4635 if(wbms->wr_discard) {
4636 END_PROFILE(SMBwriteBs);
4637 return -1; /* Just discard the packet */
4640 nwritten = write_file(fsp,data,startpos,numtowrite);
4642 if(lp_syncalways(SNUM(conn)) || write_through)
4643 sync_file(conn,fsp);
4645 if (nwritten < (ssize_t)numtowrite) {
4647 /* We are returning an error - we can delete the aux struct */
4650 fsp->wbmpx_ptr = NULL;
4651 END_PROFILE(SMBwriteBs);
4652 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4654 END_PROFILE(SMBwriteBs);
4655 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4658 /* Increment the total written, if this matches tcount
4659 we can discard the auxiliary struct (hurrah !) and return a writeC */
4660 wbms->wr_total_written += nwritten;
4661 if(wbms->wr_total_written >= tcount) {
4662 if (write_through) {
4663 outsize = set_message(outbuf,1,0,True);
4664 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4665 send_response = True;
4669 fsp->wbmpx_ptr = NULL;
4673 END_PROFILE(SMBwriteBs);
4677 END_PROFILE(SMBwriteBs);
4681 /****************************************************************************
4682 Reply to a SMBgetattrE.
4683 ****************************************************************************/
4685 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4687 SMB_STRUCT_STAT sbuf;
4690 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4691 START_PROFILE(SMBgetattrE);
4693 outsize = set_message(outbuf,11,0,True);
4695 if(!fsp || (fsp->conn != conn)) {
4696 END_PROFILE(SMBgetattrE);
4697 return ERROR_DOS(ERRDOS,ERRbadfid);
4700 /* Do an fstat on this file */
4701 if(fsp_stat(fsp, &sbuf)) {
4702 END_PROFILE(SMBgetattrE);
4703 return(UNIXERROR(ERRDOS,ERRnoaccess));
4706 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4709 * Convert the times into dos times. Set create
4710 * date to be last modify date as UNIX doesn't save
4714 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4715 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4716 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4719 SIVAL(outbuf,smb_vwv6,0);
4720 SIVAL(outbuf,smb_vwv8,0);
4722 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4723 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4724 SIVAL(outbuf,smb_vwv8,allocation_size);
4726 SSVAL(outbuf,smb_vwv10, mode);
4728 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4730 END_PROFILE(SMBgetattrE);