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 Reply to an special message.
43 ****************************************************************************/
45 int reply_special(char *inbuf,char *outbuf)
48 int msg_type = CVAL(inbuf,0);
49 int msg_flags = CVAL(inbuf,1);
55 static BOOL already_got_session = False;
59 memset(outbuf,'\0',smb_size);
64 case 0x81: /* session request */
66 if (already_got_session) {
67 exit_server("multiple session request not permitted");
72 if (name_len(inbuf+4) > 50 ||
73 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
74 DEBUG(0,("Invalid name length in session request\n"));
77 name_extract(inbuf,4,name1);
78 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
79 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
86 name_type = name2[15];
90 set_local_machine_name(name1, True);
91 set_remote_machine_name(name2, True);
93 DEBUG(2,("netbios connect: local=%s remote=%s\n",
94 get_local_machine_name(), get_remote_machine_name() ));
96 if (name_type == 'R') {
97 /* We are being asked for a pathworks session ---
99 SCVAL(outbuf, 0,0x83);
103 /* only add the client's machine name to the list
104 of possibly valid usernames if we are operating
105 in share mode security */
106 if (lp_security() == SEC_SHARE) {
107 add_session_user(get_remote_machine_name());
110 reload_services(True);
113 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
115 already_got_session = True;
118 case 0x89: /* session keepalive request
119 (some old clients produce this?) */
120 SCVAL(outbuf,0,SMBkeepalive);
124 case 0x82: /* positive session response */
125 case 0x83: /* negative session response */
126 case 0x84: /* retarget session response */
127 DEBUG(0,("Unexpected session response\n"));
130 case SMBkeepalive: /* session keepalive */
135 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
136 msg_type, msg_flags));
141 /****************************************************************************
143 ****************************************************************************/
145 int reply_tcon(connection_struct *conn,
146 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
153 uint16 vuid = SVAL(inbuf,smb_uid);
157 DATA_BLOB password_blob;
159 START_PROFILE(SMBtcon);
161 *service_buf = *password = *dev = 0;
163 p = smb_buf(inbuf)+1;
164 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
165 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
167 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
169 p = strrchr_m(service_buf,'\\');
173 service = service_buf;
176 password_blob = data_blob(password, pwlen+1);
178 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
180 data_blob_clear_free(&password_blob);
183 END_PROFILE(SMBtcon);
184 return ERROR_NT(nt_status);
187 outsize = set_message(outbuf,2,0,True);
188 SSVAL(outbuf,smb_vwv0,max_recv);
189 SSVAL(outbuf,smb_vwv1,conn->cnum);
190 SSVAL(outbuf,smb_tid,conn->cnum);
192 DEBUG(3,("tcon service=%s cnum=%d\n",
193 service, conn->cnum));
195 END_PROFILE(SMBtcon);
199 /****************************************************************************
200 Reply to a tcon and X.
201 ****************************************************************************/
203 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
208 /* what the cleint thinks the device is */
209 fstring client_devicetype;
210 /* what the server tells the client the share represents */
211 const char *server_devicetype;
213 uint16 vuid = SVAL(inbuf,smb_uid);
214 int passlen = SVAL(inbuf,smb_vwv3);
217 extern BOOL global_encrypted_passwords_negotiated;
219 START_PROFILE(SMBtconX);
221 *service = *client_devicetype = 0;
223 /* we might have to close an old one */
224 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
225 close_cnum(conn,vuid);
228 if (passlen > MAX_PASS_LEN) {
229 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
232 if (global_encrypted_passwords_negotiated) {
233 password = data_blob(smb_buf(inbuf),passlen);
235 password = data_blob(smb_buf(inbuf),passlen+1);
236 /* Ensure correct termination */
237 password.data[passlen]=0;
240 p = smb_buf(inbuf) + passlen;
241 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
244 * the service name can be either: \\server\share
245 * or share directly like on the DELL PowerVault 705
248 q = strchr_m(path+2,'\\');
250 END_PROFILE(SMBtconX);
251 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
253 fstrcpy(service,q+1);
256 fstrcpy(service,path);
258 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
260 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
262 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
264 data_blob_clear_free(&password);
267 END_PROFILE(SMBtconX);
268 return ERROR_NT(nt_status);
272 server_devicetype = "IPC";
273 else if ( IS_PRINT(conn) )
274 server_devicetype = "LPT1:";
276 server_devicetype = "A:";
278 if (Protocol < PROTOCOL_NT1) {
279 set_message(outbuf,2,0,True);
281 p += srvstr_push(outbuf, p, server_devicetype, -1,
282 STR_TERMINATE|STR_ASCII);
283 set_message_end(outbuf,p);
285 /* NT sets the fstype of IPC$ to the null string */
286 const char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
288 set_message(outbuf,3,0,True);
291 p += srvstr_push(outbuf, p, server_devicetype, -1,
292 STR_TERMINATE|STR_ASCII);
293 p += srvstr_push(outbuf, p, fsname, -1,
295 set_message_end(outbuf,p);
297 /* what does setting this bit do? It is set by NT4 and
298 may affect the ability to autorun mounted cdroms */
299 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
300 (lp_csc_policy(SNUM(conn)) << 2));
302 init_dfsroot(conn, inbuf, outbuf);
306 DEBUG(3,("tconX service=%s \n",
309 /* set the incoming and outgoing tid to the just created one */
310 SSVAL(inbuf,smb_tid,conn->cnum);
311 SSVAL(outbuf,smb_tid,conn->cnum);
313 END_PROFILE(SMBtconX);
314 return chain_reply(inbuf,outbuf,length,bufsize);
317 /****************************************************************************
318 Reply to an unknown type.
319 ****************************************************************************/
321 int reply_unknown(char *inbuf,char *outbuf)
324 type = CVAL(inbuf,smb_com);
326 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
327 smb_fn_name(type), type, type));
329 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
332 /****************************************************************************
334 ****************************************************************************/
336 int reply_ioctl(connection_struct *conn,
337 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
339 uint16 device = SVAL(inbuf,smb_vwv1);
340 uint16 function = SVAL(inbuf,smb_vwv2);
341 uint32 ioctl_code = (device << 16) + function;
342 int replysize, outsize;
344 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
345 START_PROFILE(SMBioctl);
347 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
349 switch (ioctl_code) {
350 case IOCTL_QUERY_JOB_INFO:
354 END_PROFILE(SMBioctl);
355 return(ERROR_DOS(ERRSRV,ERRnosupport));
358 outsize = set_message(outbuf,8,replysize+1,True);
359 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
360 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
361 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
362 p = smb_buf(outbuf) + 1; /* Allow for alignment */
364 switch (ioctl_code) {
365 case IOCTL_QUERY_JOB_INFO:
367 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
368 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
369 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
374 END_PROFILE(SMBioctl);
378 /****************************************************************************
380 ****************************************************************************/
382 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
388 BOOL bad_path = False;
389 SMB_STRUCT_STAT sbuf;
390 START_PROFILE(SMBchkpth);
392 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
394 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
396 unix_convert(name,conn,0,&bad_path,&sbuf);
398 mode = SVAL(inbuf,smb_vwv0);
400 if (check_name(name,conn)) {
401 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
402 if (!(ok = S_ISDIR(sbuf.st_mode)))
407 /* We special case this - as when a Windows machine
408 is parsing a path is steps through the components
409 one at a time - if a component fails it expects
410 ERRbadpath, not ERRbadfile.
413 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
415 return(UNIXERROR(ERRDOS,ERRbadpath));
418 outsize = set_message(outbuf,0,0,True);
420 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
422 END_PROFILE(SMBchkpth);
426 /****************************************************************************
428 ****************************************************************************/
430 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
434 SMB_STRUCT_STAT sbuf;
439 BOOL bad_path = False;
441 START_PROFILE(SMBgetatr);
443 p = smb_buf(inbuf) + 1;
444 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
446 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
448 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
449 under WfWg - weird! */
451 mode = aHIDDEN | aDIR;
452 if (!CAN_WRITE(conn))
458 unix_convert(fname,conn,0,&bad_path,&sbuf);
459 if (check_name(fname,conn)) {
460 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0) {
461 mode = dos_mode(conn,fname,&sbuf);
463 mtime = sbuf.st_mtime;
468 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
474 set_bad_path_error(errno, bad_path);
475 END_PROFILE(SMBgetatr);
476 return(UNIXERROR(ERRDOS,ERRbadfile));
479 outsize = set_message(outbuf,10,0,True);
481 SSVAL(outbuf,smb_vwv0,mode);
482 if(lp_dos_filetime_resolution(SNUM(conn)) )
483 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
485 put_dos_date3(outbuf,smb_vwv1,mtime);
486 SIVAL(outbuf,smb_vwv3,(uint32)size);
488 if (Protocol >= PROTOCOL_NT1)
489 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
491 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
493 END_PROFILE(SMBgetatr);
497 /****************************************************************************
499 ****************************************************************************/
501 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
508 SMB_STRUCT_STAT sbuf;
509 BOOL bad_path = False;
512 START_PROFILE(SMBsetatr);
514 p = smb_buf(inbuf) + 1;
515 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
516 unix_convert(fname,conn,0,&bad_path,&sbuf);
518 mode = SVAL(inbuf,smb_vwv0);
519 mtime = make_unix_date3(inbuf+smb_vwv1);
521 if (VALID_STAT_OF_DIR(sbuf))
526 if (check_name(fname,conn))
527 ok = (file_chmod(conn,fname,mode,NULL) == 0);
529 ok = set_filetime(conn,fname,mtime);
532 set_bad_path_error(errno, bad_path);
533 END_PROFILE(SMBsetatr);
534 return(UNIXERROR(ERRDOS,ERRnoaccess));
537 outsize = set_message(outbuf,0,0,True);
539 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
541 END_PROFILE(SMBsetatr);
545 /****************************************************************************
547 ****************************************************************************/
549 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
552 SMB_BIG_UINT dfree,dsize,bsize;
553 START_PROFILE(SMBdskattr);
555 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
557 outsize = set_message(outbuf,5,0,True);
559 if (Protocol <= PROTOCOL_LANMAN2) {
560 double total_space, free_space;
561 /* we need to scale this to a number that DOS6 can handle. We
562 use floating point so we can handle large drives on systems
563 that don't have 64 bit integers
565 we end up displaying a maximum of 2G to DOS systems
567 total_space = dsize * (double)bsize;
568 free_space = dfree * (double)bsize;
570 dsize = (total_space+63*512) / (64*512);
571 dfree = (free_space+63*512) / (64*512);
573 if (dsize > 0xFFFF) dsize = 0xFFFF;
574 if (dfree > 0xFFFF) dfree = 0xFFFF;
576 SSVAL(outbuf,smb_vwv0,dsize);
577 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
578 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
579 SSVAL(outbuf,smb_vwv3,dfree);
581 SSVAL(outbuf,smb_vwv0,dsize);
582 SSVAL(outbuf,smb_vwv1,bsize/512);
583 SSVAL(outbuf,smb_vwv2,512);
584 SSVAL(outbuf,smb_vwv3,dfree);
587 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
589 END_PROFILE(SMBdskattr);
593 /****************************************************************************
595 Can be called from SMBsearch, SMBffirst or SMBfunique.
596 ****************************************************************************/
598 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
609 BOOL finished = False;
618 BOOL check_descend = False;
619 BOOL expect_close = False;
620 BOOL can_open = True;
621 BOOL bad_path = False;
622 START_PROFILE(SMBsearch);
624 *mask = *directory = *fname = 0;
626 /* If we were called as SMBffirst then we must expect close. */
627 if(CVAL(inbuf,smb_com) == SMBffirst)
630 outsize = set_message(outbuf,1,3,True);
631 maxentries = SVAL(inbuf,smb_vwv0);
632 dirtype = SVAL(inbuf,smb_vwv1);
633 p = smb_buf(inbuf) + 1;
634 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
636 status_len = SVAL(p, 0);
639 /* dirtype &= ~aDIR; */
641 if (status_len == 0) {
642 SMB_STRUCT_STAT sbuf;
645 pstrcpy(directory,path);
647 unix_convert(directory,conn,0,&bad_path,&sbuf);
650 if (!check_name(directory,conn))
653 p = strrchr_m(dir2,'/');
662 p = strrchr_m(directory,'/');
668 if (strlen(directory) == 0)
669 pstrcpy(directory,".");
670 memset((char *)status,'\0',21);
671 SCVAL(status,0,(dirtype & 0x1F));
676 status_dirtype = CVAL(status,0) & 0x1F;
677 if (status_dirtype != (dirtype & 0x1F))
678 dirtype = status_dirtype;
680 conn->dirptr = dptr_fetch(status+12,&dptr_num);
683 string_set(&conn->dirpath,dptr_path(dptr_num));
684 pstrcpy(mask, dptr_wcard(dptr_num));
688 p = smb_buf(outbuf) + 3;
691 if (status_len == 0) {
692 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
695 set_bad_path_error(errno, bad_path);
696 END_PROFILE(SMBsearch);
697 return (UNIXERROR(ERRDOS,ERRnofids));
699 END_PROFILE(SMBsearch);
700 return ERROR_DOS(ERRDOS,ERRnofids);
702 dptr_set_wcard(dptr_num, strdup(mask));
703 dptr_set_attr(dptr_num, dirtype);
705 dirtype = dptr_attr(dptr_num);
708 DEBUG(4,("dptr_num is %d\n",dptr_num));
711 if ((dirtype&0x1F) == aVOLID) {
713 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
714 dptr_fill(p+12,dptr_num);
715 if (dptr_zero(p+12) && (status_len==0))
719 p += DIR_STRUCT_SIZE;
721 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
722 conn->dirpath,lp_dontdescend(SNUM(conn))));
723 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
724 check_descend = True;
726 for (i=numentries;(i<maxentries) && !finished;i++) {
727 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
730 make_dir_struct(p,mask,fname,size,mode,date);
731 dptr_fill(p+12,dptr_num);
734 p += DIR_STRUCT_SIZE;
743 if (numentries == 0 || !ok) {
744 SCVAL(outbuf,smb_rcls,ERRDOS);
745 SSVAL(outbuf,smb_err,ERRnofiles);
746 dptr_close(&dptr_num);
749 /* If we were called as SMBffirst with smb_search_id == NULL
750 and no entries were found then return error and close dirptr
753 if(ok && expect_close && numentries == 0 && status_len == 0) {
754 SCVAL(outbuf,smb_rcls,ERRDOS);
755 SSVAL(outbuf,smb_err,ERRnofiles);
756 /* Also close the dptr - we know it's gone */
757 dptr_close(&dptr_num);
760 /* If we were called as SMBfunique, then we can close the dirptr now ! */
761 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
762 dptr_close(&dptr_num);
764 SSVAL(outbuf,smb_vwv0,numentries);
765 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
766 SCVAL(smb_buf(outbuf),0,5);
767 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
769 if (Protocol >= PROTOCOL_NT1)
770 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
772 outsize += DIR_STRUCT_SIZE*numentries;
773 smb_setlen(outbuf,outsize - 4);
775 if ((! *directory) && dptr_path(dptr_num))
776 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
778 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
779 smb_fn_name(CVAL(inbuf,smb_com)),
780 mask, directory, dirtype, numentries, maxentries ) );
782 END_PROFILE(SMBsearch);
786 /****************************************************************************
787 Reply to a fclose (stop directory search).
788 ****************************************************************************/
790 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
799 START_PROFILE(SMBfclose);
801 outsize = set_message(outbuf,1,0,True);
802 p = smb_buf(inbuf) + 1;
803 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
805 status_len = SVAL(p,0);
808 if (status_len == 0) {
809 END_PROFILE(SMBfclose);
810 return ERROR_DOS(ERRSRV,ERRsrverror);
815 if(dptr_fetch(status+12,&dptr_num)) {
816 /* Close the dptr - we know it's gone */
817 dptr_close(&dptr_num);
820 SSVAL(outbuf,smb_vwv0,0);
822 DEBUG(3,("search close\n"));
824 END_PROFILE(SMBfclose);
828 /****************************************************************************
830 ****************************************************************************/
832 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
842 SMB_STRUCT_STAT sbuf;
843 BOOL bad_path = False;
845 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
846 START_PROFILE(SMBopen);
848 share_mode = SVAL(inbuf,smb_vwv0);
850 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
852 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
854 unix_convert(fname,conn,0,&bad_path,&sbuf);
856 unixmode = unix_mode(conn,aARCH,fname);
858 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
859 unixmode, oplock_request,&rmode,NULL);
862 set_bad_path_error(errno, bad_path);
863 END_PROFILE(SMBopen);
864 return(UNIXERROR(ERRDOS,ERRnoaccess));
868 fmode = dos_mode(conn,fname,&sbuf);
869 mtime = sbuf.st_mtime;
872 DEBUG(3,("attempt to open a directory %s\n",fname));
873 close_file(fsp,False);
874 END_PROFILE(SMBopen);
875 return ERROR_DOS(ERRDOS,ERRnoaccess);
878 outsize = set_message(outbuf,7,0,True);
879 SSVAL(outbuf,smb_vwv0,fsp->fnum);
880 SSVAL(outbuf,smb_vwv1,fmode);
881 if(lp_dos_filetime_resolution(SNUM(conn)) )
882 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
884 put_dos_date3(outbuf,smb_vwv2,mtime);
885 SIVAL(outbuf,smb_vwv4,(uint32)size);
886 SSVAL(outbuf,smb_vwv6,rmode);
888 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
889 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
891 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
892 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
893 END_PROFILE(SMBopen);
897 /****************************************************************************
898 Reply to an open and X.
899 ****************************************************************************/
901 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
904 int smb_mode = SVAL(inbuf,smb_vwv3);
905 int smb_attr = SVAL(inbuf,smb_vwv5);
906 /* Breakout the oplock request bits so we can set the
907 reply bits separately. */
908 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
909 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
910 BOOL oplock_request = ex_oplock_request | core_oplock_request;
912 int open_flags = SVAL(inbuf,smb_vwv2);
913 int smb_sattr = SVAL(inbuf,smb_vwv4);
914 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
916 int smb_ofun = SVAL(inbuf,smb_vwv8);
919 int fmode=0,mtime=0,rmode=0;
920 SMB_STRUCT_STAT sbuf;
922 BOOL bad_path = False;
924 START_PROFILE(SMBopenX);
926 /* If it's an IPC, pass off the pipe handler. */
928 if (lp_nt_pipe_support()) {
929 END_PROFILE(SMBopenX);
930 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
932 END_PROFILE(SMBopenX);
933 return ERROR_DOS(ERRSRV,ERRaccess);
937 /* XXXX we need to handle passed times, sattr and flags */
938 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
940 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
942 unix_convert(fname,conn,0,&bad_path,&sbuf);
944 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
946 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
947 oplock_request, &rmode,&smb_action);
950 set_bad_path_error(errno, bad_path);
951 END_PROFILE(SMBopenX);
952 return(UNIXERROR(ERRDOS,ERRnoaccess));
956 fmode = dos_mode(conn,fname,&sbuf);
957 mtime = sbuf.st_mtime;
959 close_file(fsp,False);
960 END_PROFILE(SMBopenX);
961 return ERROR_DOS(ERRDOS,ERRnoaccess);
964 /* If the caller set the extended oplock request bit
965 and we granted one (by whatever means) - set the
966 correct bit for extended oplock reply.
969 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
970 smb_action |= EXTENDED_OPLOCK_GRANTED;
972 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
973 smb_action |= EXTENDED_OPLOCK_GRANTED;
975 /* If the caller set the core oplock request bit
976 and we granted one (by whatever means) - set the
977 correct bit for core oplock reply.
980 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
981 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
983 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
984 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
986 set_message(outbuf,15,0,True);
987 SSVAL(outbuf,smb_vwv2,fsp->fnum);
988 SSVAL(outbuf,smb_vwv3,fmode);
989 if(lp_dos_filetime_resolution(SNUM(conn)) )
990 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
992 put_dos_date3(outbuf,smb_vwv4,mtime);
993 SIVAL(outbuf,smb_vwv6,(uint32)size);
994 SSVAL(outbuf,smb_vwv8,rmode);
995 SSVAL(outbuf,smb_vwv11,smb_action);
997 END_PROFILE(SMBopenX);
998 return chain_reply(inbuf,outbuf,length,bufsize);
1001 /****************************************************************************
1002 Reply to a SMBulogoffX.
1003 ****************************************************************************/
1005 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1007 uint16 vuid = SVAL(inbuf,smb_uid);
1008 user_struct *vuser = get_valid_user_struct(vuid);
1009 START_PROFILE(SMBulogoffX);
1012 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1014 /* in user level security we are supposed to close any files
1015 open by this user */
1016 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1017 file_close_user(vuid);
1019 invalidate_vuid(vuid);
1021 set_message(outbuf,2,0,True);
1023 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1025 END_PROFILE(SMBulogoffX);
1026 return chain_reply(inbuf,outbuf,length,bufsize);
1029 /****************************************************************************
1030 Reply to a mknew or a create.
1031 ****************************************************************************/
1033 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1041 BOOL bad_path = False;
1043 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1044 SMB_STRUCT_STAT sbuf;
1045 START_PROFILE(SMBcreate);
1047 com = SVAL(inbuf,smb_com);
1049 createmode = SVAL(inbuf,smb_vwv0);
1050 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
1052 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1054 unix_convert(fname,conn,0,&bad_path,&sbuf);
1056 if (createmode & aVOLID)
1057 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1059 unixmode = unix_mode(conn,createmode,fname);
1061 if(com == SMBmknew) {
1062 /* We should fail if file exists. */
1063 ofun = FILE_CREATE_IF_NOT_EXIST;
1065 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1066 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1069 /* Open file in dos compatibility share mode. */
1070 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1071 ofun, unixmode, oplock_request, NULL, NULL);
1074 set_bad_path_error(errno, bad_path);
1075 END_PROFILE(SMBcreate);
1076 return(UNIXERROR(ERRDOS,ERRnoaccess));
1079 outsize = set_message(outbuf,1,0,True);
1080 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1082 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1083 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1085 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1086 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1088 DEBUG( 2, ( "new file %s\n", fname ) );
1089 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1091 END_PROFILE(SMBcreate);
1095 /****************************************************************************
1096 Reply to a create temporary file.
1097 ****************************************************************************/
1099 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1105 BOOL bad_path = False;
1107 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1109 SMB_STRUCT_STAT sbuf;
1112 START_PROFILE(SMBctemp);
1114 createmode = SVAL(inbuf,smb_vwv0);
1115 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1116 pstrcat(fname,"\\TMXXXXXX");
1118 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1120 unix_convert(fname,conn,0,&bad_path,&sbuf);
1122 unixmode = unix_mode(conn,createmode,fname);
1124 tmpfd = smb_mkstemp(fname);
1126 END_PROFILE(SMBctemp);
1127 return(UNIXERROR(ERRDOS,ERRnoaccess));
1130 vfs_stat(conn,fname,&sbuf);
1132 /* Open file in dos compatibility share mode. */
1133 /* We should fail if file does not exist. */
1134 fsp = open_file_shared(conn,fname,&sbuf,
1135 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1136 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1137 unixmode, oplock_request, NULL, NULL);
1139 /* close fd from smb_mkstemp() */
1143 set_bad_path_error(errno, bad_path);
1144 END_PROFILE(SMBctemp);
1145 return(UNIXERROR(ERRDOS,ERRnoaccess));
1148 outsize = set_message(outbuf,1,0,True);
1149 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1151 /* the returned filename is relative to the directory */
1152 s = strrchr_m(fname, '/');
1158 p = smb_buf(outbuf);
1159 SSVALS(p, 0, -1); /* what is this? not in spec */
1160 SSVAL(p, 2, strlen(s));
1162 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1163 outsize = set_message_end(outbuf, p);
1165 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1166 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1168 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1169 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1171 DEBUG( 2, ( "created temp file %s\n", fname ) );
1172 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1173 fname, fsp->fd, createmode, (int)unixmode ) );
1175 END_PROFILE(SMBctemp);
1179 /*******************************************************************
1180 Check if a user is allowed to rename a file.
1181 ********************************************************************/
1183 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1189 if (!CAN_WRITE(conn))
1190 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1192 if (S_ISDIR(pst->st_mode))
1193 return NT_STATUS_OK;
1195 /* We need a better way to return NT status codes from open... */
1199 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1200 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1203 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1204 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1205 ret = NT_STATUS_SHARING_VIOLATION;
1210 close_file(fsp,False);
1211 return NT_STATUS_OK;
1214 /*******************************************************************
1215 Check if a user is allowed to delete a file.
1216 ********************************************************************/
1218 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1220 SMB_STRUCT_STAT sbuf;
1226 if (!CAN_WRITE(conn))
1227 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1229 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
1230 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1232 fmode = dos_mode(conn,fname,&sbuf);
1234 return NT_STATUS_FILE_IS_A_DIRECTORY;
1235 if (!lp_delete_readonly(SNUM(conn))) {
1237 return NT_STATUS_CANNOT_DELETE;
1239 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1240 return NT_STATUS_CANNOT_DELETE;
1242 /* We need a better way to return NT status codes from open... */
1246 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1247 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1250 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1251 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1252 ret = unix_ERR_ntstatus;
1253 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1254 ret = NT_STATUS_SHARING_VIOLATION;
1257 unix_ERR_ntstatus = NT_STATUS_OK;
1260 close_file(fsp,False);
1261 return NT_STATUS_OK;
1264 /****************************************************************************
1265 The guts of the unlink command, split out so it may be called by the NT SMB
1267 ****************************************************************************/
1269 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1275 NTSTATUS error = NT_STATUS_OK;
1277 BOOL bad_path = False;
1279 SMB_STRUCT_STAT sbuf;
1281 *directory = *mask = 0;
1283 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1285 p = strrchr_m(name,'/');
1287 pstrcpy(directory,".");
1291 pstrcpy(directory,name);
1296 * We should only check the mangled cache
1297 * here if unix_convert failed. This means
1298 * that the path in 'mask' doesn't exist
1299 * on the file system and so we need to look
1300 * for a possible mangle. This patch from
1301 * Tine Smukavec <valentin.smukavec@hermes.si>.
1304 if (!rc && mangle_is_mangled(mask))
1305 mangle_check_cache( mask );
1307 has_wild = ms_has_wild(mask);
1310 pstrcat(directory,"/");
1311 pstrcat(directory,mask);
1312 error = can_delete(directory,conn,dirtype);
1313 if (!NT_STATUS_IS_OK(error)) return error;
1315 if (vfs_unlink(conn,directory) == 0) {
1319 void *dirptr = NULL;
1322 if (check_name(directory,conn))
1323 dirptr = OpenDir(conn, directory, True);
1325 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1326 the pattern matches against the long name, otherwise the short name
1327 We don't implement this yet XXXX
1331 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1333 if (strequal(mask,"????????.???"))
1336 while ((dname = ReadDirName(dirptr))) {
1338 pstrcpy(fname,dname);
1340 if(!mask_match(fname, mask, case_sensitive)) continue;
1342 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1343 error = can_delete(fname,conn,dirtype);
1344 if (!NT_STATUS_IS_OK(error)) continue;
1345 if (vfs_unlink(conn,fname) == 0) count++;
1346 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1352 if (count == 0 && NT_STATUS_IS_OK(error)) {
1353 error = map_nt_error_from_unix(errno);
1359 /****************************************************************************
1361 ****************************************************************************/
1363 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1370 START_PROFILE(SMBunlink);
1372 dirtype = SVAL(inbuf,smb_vwv0);
1374 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1376 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1378 DEBUG(3,("reply_unlink : %s\n",name));
1380 status = unlink_internals(conn, dirtype, name);
1381 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1384 * Win2k needs a changenotify request response before it will
1385 * update after a rename..
1387 process_pending_change_notify_queue((time_t)0);
1389 outsize = set_message(outbuf,0,0,True);
1391 END_PROFILE(SMBunlink);
1395 /****************************************************************************
1397 ****************************************************************************/
1399 void fail_readraw(void)
1402 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1404 exit_server(errstr);
1407 /****************************************************************************
1408 Use sendfile in readbraw.
1409 ****************************************************************************/
1411 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1412 ssize_t mincount, char *outbuf)
1416 #if defined(WITH_SENDFILE)
1418 * We can only use sendfile on a non-chained packet and on a file
1419 * that is exclusively oplocked. reply_readbraw has already checked the length.
1422 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1423 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1426 _smb_setlen(outbuf,nread);
1427 header.data = outbuf;
1431 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1433 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1434 * return ENOSYS then pretend we just got a normal read.
1436 if (errno == ENOSYS)
1439 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1440 fsp->fsp_name, strerror(errno) ));
1441 exit_server("send_file_readbraw sendfile failed");
1450 ret = read_file(fsp,outbuf+4,startpos,nread);
1455 _smb_setlen(outbuf,ret);
1456 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1460 /****************************************************************************
1461 Reply to a readbraw (core+ protocol).
1462 ****************************************************************************/
1464 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1466 ssize_t maxcount,mincount;
1469 char *header = outbuf;
1471 START_PROFILE(SMBreadbraw);
1474 * Special check if an oplock break has been issued
1475 * and the readraw request croses on the wire, we must
1476 * return a zero length response here.
1479 if(global_oplock_break) {
1480 _smb_setlen(header,0);
1481 if (write_data(smbd_server_fd(),header,4) != 4)
1483 DEBUG(5,("readbraw - oplock break finished\n"));
1484 END_PROFILE(SMBreadbraw);
1488 fsp = file_fsp(inbuf,smb_vwv0);
1490 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1492 * fsp could be NULL here so use the value from the packet. JRA.
1494 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1495 _smb_setlen(header,0);
1496 if (write_data(smbd_server_fd(),header,4) != 4)
1498 END_PROFILE(SMBreadbraw);
1502 CHECK_FSP(fsp,conn);
1504 flush_write_cache(fsp, READRAW_FLUSH);
1506 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1507 if(CVAL(inbuf,smb_wct) == 10) {
1509 * This is a large offset (64 bit) read.
1511 #ifdef LARGE_SMB_OFF_T
1513 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1515 #else /* !LARGE_SMB_OFF_T */
1518 * Ensure we haven't been sent a >32 bit offset.
1521 if(IVAL(inbuf,smb_vwv8) != 0) {
1522 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1523 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1524 _smb_setlen(header,0);
1525 if (write_data(smbd_server_fd(),header,4) != 4)
1527 END_PROFILE(SMBreadbraw);
1531 #endif /* LARGE_SMB_OFF_T */
1534 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1535 _smb_setlen(header,0);
1536 if (write_data(smbd_server_fd(),header,4) != 4)
1538 END_PROFILE(SMBreadbraw);
1542 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1543 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1545 /* ensure we don't overrun the packet size */
1546 maxcount = MIN(65535,maxcount);
1547 maxcount = MAX(mincount,maxcount);
1549 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1550 SMB_OFF_T size = fsp->size;
1551 SMB_OFF_T sizeneeded = startpos + maxcount;
1553 if (size < sizeneeded) {
1555 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1557 if (!fsp->can_write)
1561 if (startpos >= size)
1564 nread = MIN(maxcount,(size - startpos));
1567 if (nread < mincount)
1570 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1571 (int)maxcount, (int)mincount, (int)nread ) );
1573 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1575 DEBUG(5,("readbraw finished\n"));
1576 END_PROFILE(SMBreadbraw);
1580 /****************************************************************************
1581 Reply to a lockread (core+ protocol).
1582 ****************************************************************************/
1584 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1592 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1593 START_PROFILE(SMBlockread);
1595 CHECK_FSP(fsp,conn);
1598 release_level_2_oplocks_on_change(fsp);
1600 numtoread = SVAL(inbuf,smb_vwv1);
1601 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1603 outsize = set_message(outbuf,5,3,True);
1604 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1605 data = smb_buf(outbuf) + 3;
1608 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1609 * protocol request that predates the read/write lock concept.
1610 * Thus instead of asking for a read lock here we need to ask
1611 * for a write lock. JRA.
1614 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1615 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1617 if (NT_STATUS_V(status)) {
1618 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
1620 * A blocking lock was requested. Package up
1621 * this smb into a queued request and push it
1622 * onto the blocking lock queue.
1624 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1625 (SMB_BIG_UINT)numtoread)) {
1626 END_PROFILE(SMBlockread);
1630 END_PROFILE(SMBlockread);
1631 return ERROR_NT(status);
1634 nread = read_file(fsp,data,startpos,numtoread);
1637 END_PROFILE(SMBlockread);
1638 return(UNIXERROR(ERRDOS,ERRnoaccess));
1642 SSVAL(outbuf,smb_vwv0,nread);
1643 SSVAL(outbuf,smb_vwv5,nread+3);
1644 SSVAL(smb_buf(outbuf),1,nread);
1646 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1647 fsp->fnum, (int)numtoread, (int)nread));
1649 END_PROFILE(SMBlockread);
1653 /****************************************************************************
1655 ****************************************************************************/
1657 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1664 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1665 START_PROFILE(SMBread);
1667 CHECK_FSP(fsp,conn);
1670 numtoread = SVAL(inbuf,smb_vwv1);
1671 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1673 outsize = set_message(outbuf,5,3,True);
1674 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1675 data = smb_buf(outbuf) + 3;
1677 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1678 END_PROFILE(SMBread);
1679 return ERROR_DOS(ERRDOS,ERRlock);
1683 nread = read_file(fsp,data,startpos,numtoread);
1686 END_PROFILE(SMBread);
1687 return(UNIXERROR(ERRDOS,ERRnoaccess));
1691 SSVAL(outbuf,smb_vwv0,nread);
1692 SSVAL(outbuf,smb_vwv5,nread+3);
1693 SCVAL(smb_buf(outbuf),0,1);
1694 SSVAL(smb_buf(outbuf),1,nread);
1696 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1697 fsp->fnum, (int)numtoread, (int)nread ) );
1699 END_PROFILE(SMBread);
1703 /****************************************************************************
1704 Reply to a read and X - possibly using sendfile.
1705 ****************************************************************************/
1707 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1708 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1711 char *data = smb_buf(outbuf);
1713 #if defined(WITH_SENDFILE)
1715 * We can only use sendfile on a non-chained packet and on a file
1716 * that is exclusively oplocked.
1719 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1720 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1721 SMB_STRUCT_STAT sbuf;
1724 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1)
1725 return(UNIXERROR(ERRDOS,ERRnoaccess));
1727 if (startpos > sbuf.st_size)
1730 if (smb_maxcnt > (sbuf.st_size - startpos))
1731 smb_maxcnt = (sbuf.st_size - startpos);
1733 if (smb_maxcnt == 0)
1737 * Set up the packet header before send. We
1738 * assume here the sendfile will work (get the
1739 * correct amount of data).
1742 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1743 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1744 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1745 SCVAL(outbuf,smb_vwv0,0xFF);
1746 set_message(outbuf,12,smb_maxcnt,False);
1747 header.data = outbuf;
1748 header.length = data - outbuf;
1751 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1753 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1754 * return ENOSYS then pretend we just got a normal read.
1756 if (errno == ENOSYS)
1759 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1760 fsp->fsp_name, strerror(errno) ));
1761 exit_server("send_file_readX sendfile failed");
1764 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1765 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1773 nread = read_file(fsp,data,startpos,smb_maxcnt);
1776 END_PROFILE(SMBreadX);
1777 return(UNIXERROR(ERRDOS,ERRnoaccess));
1780 SSVAL(outbuf,smb_vwv5,nread);
1781 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1782 SSVAL(smb_buf(outbuf),-2,nread);
1784 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1785 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1790 /****************************************************************************
1791 Reply to a read and X.
1792 ****************************************************************************/
1794 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1796 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1797 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1799 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1801 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1804 START_PROFILE(SMBreadX);
1806 /* If it's an IPC, pass off the pipe handler. */
1808 END_PROFILE(SMBreadX);
1809 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1812 CHECK_FSP(fsp,conn);
1815 set_message(outbuf,12,0,True);
1817 if(CVAL(inbuf,smb_wct) == 12) {
1818 #ifdef LARGE_SMB_OFF_T
1820 * This is a large offset (64 bit) read.
1822 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1824 #else /* !LARGE_SMB_OFF_T */
1827 * Ensure we haven't been sent a >32 bit offset.
1830 if(IVAL(inbuf,smb_vwv10) != 0) {
1831 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1832 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1833 END_PROFILE(SMBreadX);
1834 return ERROR_DOS(ERRDOS,ERRbadaccess);
1837 #endif /* LARGE_SMB_OFF_T */
1841 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1842 END_PROFILE(SMBreadX);
1843 return ERROR_DOS(ERRDOS,ERRlock);
1846 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
1848 nread = chain_reply(inbuf,outbuf,length,bufsize);
1850 END_PROFILE(SMBreadX);
1854 /****************************************************************************
1855 Reply to a writebraw (core+ or LANMAN1.0 protocol).
1856 ****************************************************************************/
1858 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1861 ssize_t total_written=0;
1862 size_t numtowrite=0;
1867 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1869 START_PROFILE(SMBwritebraw);
1871 CHECK_FSP(fsp,conn);
1874 tcount = IVAL(inbuf,smb_vwv1);
1875 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1876 write_through = BITSETW(inbuf+smb_vwv7,0);
1878 /* We have to deal with slightly different formats depending
1879 on whether we are using the core+ or lanman1.0 protocol */
1881 if(Protocol <= PROTOCOL_COREPLUS) {
1882 numtowrite = SVAL(smb_buf(inbuf),-2);
1883 data = smb_buf(inbuf);
1885 numtowrite = SVAL(inbuf,smb_vwv10);
1886 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1889 /* force the error type */
1890 SCVAL(inbuf,smb_com,SMBwritec);
1891 SCVAL(outbuf,smb_com,SMBwritec);
1893 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1894 END_PROFILE(SMBwritebraw);
1895 return(ERROR_DOS(ERRDOS,ERRlock));
1899 nwritten = write_file(fsp,data,startpos,numtowrite);
1901 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1902 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1904 if (nwritten < (ssize_t)numtowrite) {
1905 END_PROFILE(SMBwritebraw);
1906 return(UNIXERROR(ERRHRD,ERRdiskfull));
1909 total_written = nwritten;
1911 /* Return a message to the redirector to tell it to send more bytes */
1912 SCVAL(outbuf,smb_com,SMBwritebraw);
1913 SSVALS(outbuf,smb_vwv0,-1);
1914 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1915 if (!send_smb(smbd_server_fd(),outbuf))
1916 exit_server("reply_writebraw: send_smb failed.");
1918 /* Now read the raw data into the buffer and write it */
1919 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1920 exit_server("secondary writebraw failed");
1923 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1924 numtowrite = smb_len(inbuf);
1926 /* Set up outbuf to return the correct return */
1927 outsize = set_message(outbuf,1,0,True);
1928 SCVAL(outbuf,smb_com,SMBwritec);
1929 SSVAL(outbuf,smb_vwv0,total_written);
1931 if (numtowrite != 0) {
1933 if (numtowrite > BUFFER_SIZE) {
1934 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1935 (unsigned int)numtowrite ));
1936 exit_server("secondary writebraw failed");
1939 if (tcount > nwritten+numtowrite) {
1940 DEBUG(3,("Client overestimated the write %d %d %d\n",
1941 (int)tcount,(int)nwritten,(int)numtowrite));
1944 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1945 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1947 exit_server("secondary writebraw failed");
1950 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1952 if (nwritten < (ssize_t)numtowrite) {
1953 SCVAL(outbuf,smb_rcls,ERRHRD);
1954 SSVAL(outbuf,smb_err,ERRdiskfull);
1958 total_written += nwritten;
1961 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1962 sync_file(conn,fsp);
1964 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1965 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1967 /* we won't return a status if write through is not selected - this follows what WfWg does */
1968 END_PROFILE(SMBwritebraw);
1969 if (!write_through && total_written==tcount) {
1971 #if RABBIT_PELLET_FIX
1973 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
1974 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
1976 if (!send_keepalive(smbd_server_fd()))
1977 exit_server("reply_writebraw: send of keepalive failed");
1985 /****************************************************************************
1986 Reply to a writeunlock (core+).
1987 ****************************************************************************/
1989 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
1990 int size, int dum_buffsize)
1992 ssize_t nwritten = -1;
1997 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1999 START_PROFILE(SMBwriteunlock);
2001 CHECK_FSP(fsp,conn);
2004 numtowrite = SVAL(inbuf,smb_vwv1);
2005 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2006 data = smb_buf(inbuf) + 3;
2008 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2009 WRITE_LOCK,False)) {
2010 END_PROFILE(SMBwriteunlock);
2011 return ERROR_DOS(ERRDOS,ERRlock);
2014 /* The special X/Open SMB protocol handling of
2015 zero length writes is *NOT* done for
2020 nwritten = write_file(fsp,data,startpos,numtowrite);
2022 if (lp_syncalways(SNUM(conn)))
2023 sync_file(conn,fsp);
2025 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2026 END_PROFILE(SMBwriteunlock);
2027 return(UNIXERROR(ERRHRD,ERRdiskfull));
2030 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2031 (SMB_BIG_UINT)startpos);
2032 if (NT_STATUS_V(status)) {
2033 END_PROFILE(SMBwriteunlock);
2034 return ERROR_NT(status);
2037 outsize = set_message(outbuf,1,0,True);
2039 SSVAL(outbuf,smb_vwv0,nwritten);
2041 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2042 fsp->fnum, (int)numtowrite, (int)nwritten));
2044 END_PROFILE(SMBwriteunlock);
2048 /****************************************************************************
2050 ****************************************************************************/
2052 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2055 ssize_t nwritten = -1;
2058 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2060 START_PROFILE(SMBwrite);
2062 /* If it's an IPC, pass off the pipe handler. */
2064 END_PROFILE(SMBwrite);
2065 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2068 CHECK_FSP(fsp,conn);
2071 numtowrite = SVAL(inbuf,smb_vwv1);
2072 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2073 data = smb_buf(inbuf) + 3;
2075 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2076 END_PROFILE(SMBwrite);
2077 return ERROR_DOS(ERRDOS,ERRlock);
2081 * X/Open SMB protocol says that if smb_vwv1 is
2082 * zero then the file size should be extended or
2083 * truncated to the size given in smb_vwv[2-3].
2086 if(numtowrite == 0) {
2088 * This is actually an allocate call, and set EOF. JRA.
2090 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2092 END_PROFILE(SMBwrite);
2093 return ERROR_NT(NT_STATUS_DISK_FULL);
2095 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2097 END_PROFILE(SMBwrite);
2098 return ERROR_NT(NT_STATUS_DISK_FULL);
2101 nwritten = write_file(fsp,data,startpos,numtowrite);
2103 if (lp_syncalways(SNUM(conn)))
2104 sync_file(conn,fsp);
2106 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2107 END_PROFILE(SMBwrite);
2108 return(UNIXERROR(ERRHRD,ERRdiskfull));
2111 outsize = set_message(outbuf,1,0,True);
2113 SSVAL(outbuf,smb_vwv0,nwritten);
2115 if (nwritten < (ssize_t)numtowrite) {
2116 SCVAL(outbuf,smb_rcls,ERRHRD);
2117 SSVAL(outbuf,smb_err,ERRdiskfull);
2120 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2122 END_PROFILE(SMBwrite);
2126 /****************************************************************************
2127 Reply to a write and X.
2128 ****************************************************************************/
2130 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2132 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2133 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2134 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2135 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2136 ssize_t nwritten = -1;
2137 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2138 unsigned int smblen = smb_len(inbuf);
2140 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2141 START_PROFILE(SMBwriteX);
2143 /* If it's an IPC, pass off the pipe handler. */
2145 END_PROFILE(SMBwriteX);
2146 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2149 CHECK_FSP(fsp,conn);
2152 /* Deal with possible LARGE_WRITEX */
2154 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2156 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2157 END_PROFILE(SMBwriteX);
2158 return ERROR_DOS(ERRDOS,ERRbadmem);
2161 data = smb_base(inbuf) + smb_doff;
2163 if(CVAL(inbuf,smb_wct) == 14) {
2164 #ifdef LARGE_SMB_OFF_T
2166 * This is a large offset (64 bit) write.
2168 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2170 #else /* !LARGE_SMB_OFF_T */
2173 * Ensure we haven't been sent a >32 bit offset.
2176 if(IVAL(inbuf,smb_vwv12) != 0) {
2177 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2178 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2179 END_PROFILE(SMBwriteX);
2180 return ERROR_DOS(ERRDOS,ERRbadaccess);
2183 #endif /* LARGE_SMB_OFF_T */
2186 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2187 END_PROFILE(SMBwriteX);
2188 return ERROR_DOS(ERRDOS,ERRlock);
2191 /* X/Open SMB protocol says that, unlike SMBwrite
2192 if the length is zero then NO truncation is
2193 done, just a write of zero. To truncate a file,
2199 nwritten = write_file(fsp,data,startpos,numtowrite);
2201 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2202 END_PROFILE(SMBwriteX);
2203 return(UNIXERROR(ERRHRD,ERRdiskfull));
2206 set_message(outbuf,6,0,True);
2208 SSVAL(outbuf,smb_vwv2,nwritten);
2210 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2212 if (nwritten < (ssize_t)numtowrite) {
2213 SCVAL(outbuf,smb_rcls,ERRHRD);
2214 SSVAL(outbuf,smb_err,ERRdiskfull);
2217 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2218 fsp->fnum, (int)numtowrite, (int)nwritten));
2220 if (lp_syncalways(SNUM(conn)) || write_through)
2221 sync_file(conn,fsp);
2223 END_PROFILE(SMBwriteX);
2224 return chain_reply(inbuf,outbuf,length,bufsize);
2227 /****************************************************************************
2229 ****************************************************************************/
2231 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2237 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2238 START_PROFILE(SMBlseek);
2240 CHECK_FSP(fsp,conn);
2242 flush_write_cache(fsp, SEEK_FLUSH);
2244 mode = SVAL(inbuf,smb_vwv1) & 3;
2245 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2246 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2263 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2265 * Check for the special case where a seek before the start
2266 * of the file sets the offset to zero. Added in the CIFS spec,
2270 if(errno == EINVAL) {
2271 SMB_OFF_T current_pos = startpos;
2273 if(umode == SEEK_CUR) {
2275 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2276 END_PROFILE(SMBlseek);
2277 return(UNIXERROR(ERRDOS,ERRnoaccess));
2280 current_pos += startpos;
2282 } else if (umode == SEEK_END) {
2284 SMB_STRUCT_STAT sbuf;
2286 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2287 END_PROFILE(SMBlseek);
2288 return(UNIXERROR(ERRDOS,ERRnoaccess));
2291 current_pos += sbuf.st_size;
2295 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2299 END_PROFILE(SMBlseek);
2300 return(UNIXERROR(ERRDOS,ERRnoaccess));
2306 outsize = set_message(outbuf,2,0,True);
2307 SIVAL(outbuf,smb_vwv0,res);
2309 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2310 fsp->fnum, (double)startpos, (double)res, mode));
2312 END_PROFILE(SMBlseek);
2316 /****************************************************************************
2318 ****************************************************************************/
2320 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2322 int outsize = set_message(outbuf,0,0,True);
2323 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2324 START_PROFILE(SMBflush);
2326 CHECK_FSP(fsp,conn);
2329 file_sync_all(conn);
2331 sync_file(conn,fsp);
2334 DEBUG(3,("flush\n"));
2335 END_PROFILE(SMBflush);
2339 /****************************************************************************
2341 ****************************************************************************/
2343 int reply_exit(connection_struct *conn,
2344 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2347 START_PROFILE(SMBexit);
2348 outsize = set_message(outbuf,0,0,True);
2350 DEBUG(3,("exit\n"));
2352 END_PROFILE(SMBexit);
2356 /****************************************************************************
2357 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2358 ****************************************************************************/
2360 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2365 int32 eclass = 0, err = 0;
2366 files_struct *fsp = NULL;
2367 START_PROFILE(SMBclose);
2369 outsize = set_message(outbuf,0,0,True);
2371 /* If it's an IPC, pass off to the pipe handler. */
2373 END_PROFILE(SMBclose);
2374 return reply_pipe_close(conn, inbuf,outbuf);
2377 fsp = file_fsp(inbuf,smb_vwv0);
2380 * We can only use CHECK_FSP if we know it's not a directory.
2383 if(!fsp || (fsp->conn != conn)) {
2384 END_PROFILE(SMBclose);
2385 return ERROR_DOS(ERRDOS,ERRbadfid);
2388 if(fsp->is_directory) {
2390 * Special case - close NT SMB directory handle.
2392 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2393 close_file(fsp,True);
2396 * Close ordinary file.
2401 /* Save the name for time set in close. */
2402 pstrcpy( file_name, fsp->fsp_name);
2404 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2406 conn->num_files_open));
2409 * close_file() returns the unix errno if an error
2410 * was detected on close - normally this is due to
2411 * a disk full error. If not then it was probably an I/O error.
2414 if((close_err = close_file(fsp,True)) != 0) {
2416 END_PROFILE(SMBclose);
2417 return (UNIXERROR(ERRHRD,ERRgeneral));
2421 * Now take care of any time sent in the close.
2424 mtime = make_unix_date3(inbuf+smb_vwv1);
2426 /* try and set the date */
2427 set_filetime(conn, file_name, mtime);
2431 /* We have a cached error */
2433 END_PROFILE(SMBclose);
2434 return ERROR_DOS(eclass,err);
2437 END_PROFILE(SMBclose);
2441 /****************************************************************************
2442 Reply to a writeclose (Core+ protocol).
2443 ****************************************************************************/
2445 int reply_writeclose(connection_struct *conn,
2446 char *inbuf,char *outbuf, int size, int dum_buffsize)
2449 ssize_t nwritten = -1;
2455 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2456 START_PROFILE(SMBwriteclose);
2458 CHECK_FSP(fsp,conn);
2461 numtowrite = SVAL(inbuf,smb_vwv1);
2462 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2463 mtime = make_unix_date3(inbuf+smb_vwv4);
2464 data = smb_buf(inbuf) + 1;
2466 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2467 END_PROFILE(SMBwriteclose);
2468 return ERROR_DOS(ERRDOS,ERRlock);
2471 nwritten = write_file(fsp,data,startpos,numtowrite);
2473 set_filetime(conn, fsp->fsp_name,mtime);
2475 close_err = close_file(fsp,True);
2477 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2478 fsp->fnum, (int)numtowrite, (int)nwritten,
2479 conn->num_files_open));
2481 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2482 END_PROFILE(SMBwriteclose);
2483 return(UNIXERROR(ERRHRD,ERRdiskfull));
2486 if(close_err != 0) {
2488 END_PROFILE(SMBwriteclose);
2489 return(UNIXERROR(ERRHRD,ERRgeneral));
2492 outsize = set_message(outbuf,1,0,True);
2494 SSVAL(outbuf,smb_vwv0,nwritten);
2495 END_PROFILE(SMBwriteclose);
2499 /****************************************************************************
2501 ****************************************************************************/
2503 int reply_lock(connection_struct *conn,
2504 char *inbuf,char *outbuf, int length, int dum_buffsize)
2506 int outsize = set_message(outbuf,0,0,True);
2507 SMB_BIG_UINT count,offset;
2509 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2510 START_PROFILE(SMBlock);
2512 CHECK_FSP(fsp,conn);
2514 release_level_2_oplocks_on_change(fsp);
2516 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2517 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2519 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2520 fsp->fd, fsp->fnum, (double)offset, (double)count));
2522 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2523 if (NT_STATUS_V(status)) {
2524 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2526 * A blocking lock was requested. Package up
2527 * this smb into a queued request and push it
2528 * onto the blocking lock queue.
2530 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2531 END_PROFILE(SMBlock);
2535 END_PROFILE(SMBlock);
2536 return ERROR_NT(status);
2539 END_PROFILE(SMBlock);
2543 /****************************************************************************
2545 ****************************************************************************/
2547 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2550 int outsize = set_message(outbuf,0,0,True);
2551 SMB_BIG_UINT count,offset;
2553 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2554 START_PROFILE(SMBunlock);
2556 CHECK_FSP(fsp,conn);
2558 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2559 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2561 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2562 if (NT_STATUS_V(status)) {
2563 END_PROFILE(SMBunlock);
2564 return ERROR_NT(status);
2567 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2568 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2570 END_PROFILE(SMBunlock);
2574 /****************************************************************************
2576 ****************************************************************************/
2578 int reply_tdis(connection_struct *conn,
2579 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2581 int outsize = set_message(outbuf,0,0,True);
2583 START_PROFILE(SMBtdis);
2585 vuid = SVAL(inbuf,smb_uid);
2588 DEBUG(4,("Invalid connection in tdis\n"));
2589 END_PROFILE(SMBtdis);
2590 return ERROR_DOS(ERRSRV,ERRinvnid);
2595 close_cnum(conn,vuid);
2597 END_PROFILE(SMBtdis);
2601 /****************************************************************************
2603 ****************************************************************************/
2605 int reply_echo(connection_struct *conn,
2606 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2608 int smb_reverb = SVAL(inbuf,smb_vwv0);
2610 unsigned int data_len = smb_buflen(inbuf);
2611 int outsize = set_message(outbuf,1,data_len,True);
2612 START_PROFILE(SMBecho);
2614 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2616 /* copy any incoming data back out */
2618 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2620 if (smb_reverb > 100) {
2621 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2625 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2626 SSVAL(outbuf,smb_vwv0,seq_num);
2628 smb_setlen(outbuf,outsize - 4);
2630 if (!send_smb(smbd_server_fd(),outbuf))
2631 exit_server("reply_echo: send_smb failed.");
2634 DEBUG(3,("echo %d times\n", smb_reverb));
2638 END_PROFILE(SMBecho);
2642 /****************************************************************************
2643 Reply to a printopen.
2644 ****************************************************************************/
2646 int reply_printopen(connection_struct *conn,
2647 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2651 START_PROFILE(SMBsplopen);
2653 if (!CAN_PRINT(conn)) {
2654 END_PROFILE(SMBsplopen);
2655 return ERROR_DOS(ERRDOS,ERRnoaccess);
2658 /* Open for exclusive use, write only. */
2659 fsp = print_fsp_open(conn, NULL);
2662 END_PROFILE(SMBsplopen);
2663 return(UNIXERROR(ERRDOS,ERRnoaccess));
2666 outsize = set_message(outbuf,1,0,True);
2667 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2669 DEBUG(3,("openprint fd=%d fnum=%d\n",
2670 fsp->fd, fsp->fnum));
2672 END_PROFILE(SMBsplopen);
2676 /****************************************************************************
2677 Reply to a printclose.
2678 ****************************************************************************/
2680 int reply_printclose(connection_struct *conn,
2681 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2683 int outsize = set_message(outbuf,0,0,True);
2684 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2686 START_PROFILE(SMBsplclose);
2688 CHECK_FSP(fsp,conn);
2690 if (!CAN_PRINT(conn)) {
2691 END_PROFILE(SMBsplclose);
2692 return ERROR_DOS(ERRDOS,ERRnoaccess);
2695 DEBUG(3,("printclose fd=%d fnum=%d\n",
2696 fsp->fd,fsp->fnum));
2698 close_err = close_file(fsp,True);
2700 if(close_err != 0) {
2702 END_PROFILE(SMBsplclose);
2703 return(UNIXERROR(ERRHRD,ERRgeneral));
2706 END_PROFILE(SMBsplclose);
2710 /****************************************************************************
2711 Reply to a printqueue.
2712 ****************************************************************************/
2714 int reply_printqueue(connection_struct *conn,
2715 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2717 int outsize = set_message(outbuf,2,3,True);
2718 int max_count = SVAL(inbuf,smb_vwv0);
2719 int start_index = SVAL(inbuf,smb_vwv1);
2720 START_PROFILE(SMBsplretq);
2722 /* we used to allow the client to get the cnum wrong, but that
2723 is really quite gross and only worked when there was only
2724 one printer - I think we should now only accept it if they
2725 get it right (tridge) */
2726 if (!CAN_PRINT(conn)) {
2727 END_PROFILE(SMBsplretq);
2728 return ERROR_DOS(ERRDOS,ERRnoaccess);
2731 SSVAL(outbuf,smb_vwv0,0);
2732 SSVAL(outbuf,smb_vwv1,0);
2733 SCVAL(smb_buf(outbuf),0,1);
2734 SSVAL(smb_buf(outbuf),1,0);
2736 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2737 start_index, max_count));
2740 print_queue_struct *queue = NULL;
2741 print_status_struct status;
2742 char *p = smb_buf(outbuf) + 3;
2743 int count = print_queue_status(SNUM(conn), &queue, &status);
2744 int num_to_get = ABS(max_count);
2745 int first = (max_count>0?start_index:start_index+max_count+1);
2751 num_to_get = MIN(num_to_get,count-first);
2754 for (i=first;i<first+num_to_get;i++) {
2755 put_dos_date2(p,0,queue[i].time);
2756 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2757 SSVAL(p,5, queue[i].job);
2758 SIVAL(p,7,queue[i].size);
2760 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2765 outsize = set_message(outbuf,2,28*count+3,False);
2766 SSVAL(outbuf,smb_vwv0,count);
2767 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2768 SCVAL(smb_buf(outbuf),0,1);
2769 SSVAL(smb_buf(outbuf),1,28*count);
2774 DEBUG(3,("%d entries returned in queue\n",count));
2777 END_PROFILE(SMBsplretq);
2781 /****************************************************************************
2782 Reply to a printwrite.
2783 ****************************************************************************/
2785 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2788 int outsize = set_message(outbuf,0,0,True);
2790 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2792 START_PROFILE(SMBsplwr);
2794 if (!CAN_PRINT(conn)) {
2795 END_PROFILE(SMBsplwr);
2796 return ERROR_DOS(ERRDOS,ERRnoaccess);
2799 CHECK_FSP(fsp,conn);
2802 numtowrite = SVAL(smb_buf(inbuf),1);
2803 data = smb_buf(inbuf) + 3;
2805 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2806 END_PROFILE(SMBsplwr);
2807 return(UNIXERROR(ERRHRD,ERRdiskfull));
2810 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2812 END_PROFILE(SMBsplwr);
2816 /****************************************************************************
2817 The guts of the mkdir command, split out so it may be called by the NT SMB
2819 ****************************************************************************/
2821 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2823 BOOL bad_path = False;
2824 SMB_STRUCT_STAT sbuf;
2827 unix_convert(directory,conn,0,&bad_path,&sbuf);
2829 if (check_name(directory, conn))
2830 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2833 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
2834 if (!NT_STATUS_IS_OK(nterr))
2836 return map_nt_error_from_unix(errno);
2839 return NT_STATUS_OK;
2842 /****************************************************************************
2844 ****************************************************************************/
2846 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2851 START_PROFILE(SMBmkdir);
2853 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2855 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
2857 status = mkdir_internal(conn, directory);
2858 if (!NT_STATUS_IS_OK(status))
2859 return ERROR_NT(status);
2861 outsize = set_message(outbuf,0,0,True);
2863 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2865 END_PROFILE(SMBmkdir);
2869 /****************************************************************************
2870 Static function used by reply_rmdir to delete an entire directory
2871 tree recursively. Return False on ok, True on fail.
2872 ****************************************************************************/
2874 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2876 const char *dname = NULL;
2878 void *dirptr = OpenDir(conn, directory, False);
2883 while((dname = ReadDirName(dirptr))) {
2887 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2890 /* Construct the full name. */
2891 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2897 pstrcpy(fullname, directory);
2898 pstrcat(fullname, "/");
2899 pstrcat(fullname, dname);
2901 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
2906 if(st.st_mode & S_IFDIR) {
2907 if(recursive_rmdir(conn, fullname)!=0) {
2911 if(vfs_rmdir(conn,fullname) != 0) {
2915 } else if(vfs_unlink(conn,fullname) != 0) {
2924 /****************************************************************************
2925 The internals of the rmdir code - called elsewhere.
2926 ****************************************************************************/
2928 BOOL rmdir_internals(connection_struct *conn, char *directory)
2932 ok = (vfs_rmdir(conn,directory) == 0);
2933 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2935 * Check to see if the only thing in this directory are
2936 * vetoed files/directories. If so then delete them and
2937 * retry. If we fail to delete any of them (and we *don't*
2938 * do a recursive delete) then fail the rmdir.
2940 BOOL all_veto_files = True;
2942 void *dirptr = OpenDir(conn, directory, False);
2944 if(dirptr != NULL) {
2945 int dirpos = TellDir(dirptr);
2946 while ((dname = ReadDirName(dirptr))) {
2947 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2949 if(!IS_VETO_PATH(conn, dname)) {
2950 all_veto_files = False;
2955 if(all_veto_files) {
2956 SeekDir(dirptr,dirpos);
2957 while ((dname = ReadDirName(dirptr))) {
2961 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2964 /* Construct the full name. */
2965 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2970 pstrcpy(fullname, directory);
2971 pstrcat(fullname, "/");
2972 pstrcat(fullname, dname);
2974 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
2976 if(st.st_mode & S_IFDIR) {
2977 if(lp_recursive_veto_delete(SNUM(conn))) {
2978 if(recursive_rmdir(conn, fullname) != 0)
2981 if(vfs_rmdir(conn,fullname) != 0)
2983 } else if(vfs_unlink(conn,fullname) != 0)
2987 /* Retry the rmdir */
2988 ok = (vfs_rmdir(conn,directory) == 0);
2998 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3003 /****************************************************************************
3005 ****************************************************************************/
3007 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3012 BOOL bad_path = False;
3013 SMB_STRUCT_STAT sbuf;
3014 START_PROFILE(SMBrmdir);
3016 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
3018 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3020 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3022 if (check_name(directory,conn)) {
3023 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3024 ok = rmdir_internals(conn, directory);
3028 set_bad_path_error(errno, bad_path);
3029 END_PROFILE(SMBrmdir);
3030 return(UNIXERROR(ERRDOS,ERRbadpath));
3033 outsize = set_message(outbuf,0,0,True);
3035 DEBUG( 3, ( "rmdir %s\n", directory ) );
3037 END_PROFILE(SMBrmdir);
3041 /*******************************************************************
3042 Resolve wildcards in a filename rename.
3043 ********************************************************************/
3045 static BOOL resolve_wildcards(const char *name1, char *name2)
3047 fstring root1,root2;
3049 char *p,*p2, *pname1, *pname2;
3050 int available_space;
3053 pname1 = strrchr_m(name1,'/');
3054 pname2 = strrchr_m(name2,'/');
3056 if (!pname1 || !pname2)
3059 fstrcpy(root1,pname1);
3060 fstrcpy(root2,pname2);
3061 p = strrchr_m(root1,'.');
3068 p = strrchr_m(root2,'.');
3102 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3105 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3107 StrnCpy(pname2, root2, available_space - 1);
3113 /****************************************************************************
3114 The guts of the rename command, split out so it may be called by the NT SMB
3116 ****************************************************************************/
3118 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3122 pstring newname_last_component;
3125 BOOL bad_path1 = False;
3126 BOOL bad_path2 = False;
3128 NTSTATUS error = NT_STATUS_OK;
3130 SMB_STRUCT_STAT sbuf1, sbuf2;
3132 *directory = *mask = 0;
3134 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3135 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3138 * Split the old name into directory and last component
3139 * strings. Note that unix_convert may have stripped off a
3140 * leading ./ from both name and newname if the rename is
3141 * at the root of the share. We need to make sure either both
3142 * name and newname contain a / character or neither of them do
3143 * as this is checked in resolve_wildcards().
3146 p = strrchr_m(name,'/');
3148 pstrcpy(directory,".");
3152 pstrcpy(directory,name);
3154 *p = '/'; /* Replace needed for exceptional test below. */
3158 * We should only check the mangled cache
3159 * here if unix_convert failed. This means
3160 * that the path in 'mask' doesn't exist
3161 * on the file system and so we need to look
3162 * for a possible mangle. This patch from
3163 * Tine Smukavec <valentin.smukavec@hermes.si>.
3166 if (!rc && mangle_is_mangled(mask))
3167 mangle_check_cache( mask );
3169 has_wild = ms_has_wild(mask);
3173 * No wildcards - just process the one file.
3175 BOOL is_short_name = mangle_is_8_3(name, True);
3177 /* Add a terminating '/' to the directory name. */
3178 pstrcat(directory,"/");
3179 pstrcat(directory,mask);
3181 /* Ensure newname contains a '/' also */
3182 if(strrchr_m(newname,'/') == 0) {
3185 pstrcpy(tmpstr, "./");
3186 pstrcat(tmpstr, newname);
3187 pstrcpy(newname, tmpstr);
3190 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3191 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3192 case_sensitive, case_preserve, short_case_preserve, directory,
3193 newname, newname_last_component, is_short_name));
3196 * Check for special case with case preserving and not
3197 * case sensitive, if directory and newname are identical,
3198 * and the old last component differs from the original
3199 * last component only by case, then we should allow
3200 * the rename (user is trying to change the case of the
3203 if((case_sensitive == False) &&
3204 (((case_preserve == True) &&
3205 (is_short_name == False)) ||
3206 ((short_case_preserve == True) &&
3207 (is_short_name == True))) &&
3208 strcsequal(directory, newname)) {
3209 pstring newname_modified_last_component;
3212 * Get the last component of the modified name.
3213 * Note that we guarantee that newname contains a '/'
3216 p = strrchr_m(newname,'/');
3217 pstrcpy(newname_modified_last_component,p+1);
3219 if(strcsequal(newname_modified_last_component,
3220 newname_last_component) == False) {
3222 * Replace the modified last component with
3225 pstrcpy(p+1, newname_last_component);
3229 resolve_wildcards(directory,newname);
3232 * The source object must exist.
3235 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3236 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3237 directory,newname));
3239 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3241 * Must return different errors depending on whether the parent
3242 * directory existed or not.
3245 p = strrchr_m(directory, '/');
3247 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3249 if (vfs_object_exist(conn, directory, NULL))
3250 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3251 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3253 error = map_nt_error_from_unix(errno);
3254 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3255 nt_errstr(error), directory,newname));
3260 error = can_rename(directory,conn,&sbuf1);
3262 if (!NT_STATUS_IS_OK(error)) {
3263 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3264 nt_errstr(error), directory,newname));
3269 * If the src and dest names are identical - including case,
3270 * don't do the rename, just return success.
3273 if (strcsequal(directory, newname)) {
3274 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3275 return NT_STATUS_OK;
3278 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3279 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3280 directory,newname));
3281 return NT_STATUS_OBJECT_NAME_COLLISION;
3284 if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
3285 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3286 directory,newname));
3287 return NT_STATUS_OK;
3290 if (errno == ENOTDIR || errno == EISDIR)
3291 error = NT_STATUS_OBJECT_NAME_COLLISION;
3293 error = map_nt_error_from_unix(errno);
3295 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3296 nt_errstr(error), directory,newname));
3301 * Wildcards - process each file that matches.
3303 void *dirptr = NULL;
3307 if (check_name(directory,conn))
3308 dirptr = OpenDir(conn, directory, True);
3311 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3313 if (strequal(mask,"????????.???"))
3316 while ((dname = ReadDirName(dirptr))) {
3319 pstrcpy(fname,dname);
3321 if(!mask_match(fname, mask, case_sensitive))
3324 error = NT_STATUS_ACCESS_DENIED;
3325 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3326 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3327 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3328 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3331 error = can_rename(fname,conn,&sbuf1);
3332 if (!NT_STATUS_IS_OK(error)) {
3333 DEBUG(6,("rename %s refused\n", fname));
3336 pstrcpy(destname,newname);
3338 if (!resolve_wildcards(fname,destname)) {
3339 DEBUG(6,("resolve_wildcards %s %s failed\n",
3344 if (!replace_if_exists &&
3345 vfs_file_exist(conn,destname, NULL)) {
3346 DEBUG(6,("file_exist %s\n", destname));
3347 error = NT_STATUS_OBJECT_NAME_COLLISION;
3351 if (!conn->vfs_ops.rename(conn,fname,destname))
3353 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3359 if (count == 0 && NT_STATUS_IS_OK(error)) {
3360 error = map_nt_error_from_unix(errno);
3366 /****************************************************************************
3368 ****************************************************************************/
3370 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3379 START_PROFILE(SMBmv);
3381 p = smb_buf(inbuf) + 1;
3382 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3384 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3386 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3387 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3389 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3391 status = rename_internals(conn, name, newname, False);
3392 if (!NT_STATUS_IS_OK(status)) {
3393 return ERROR_NT(status);
3397 * Win2k needs a changenotify request response before it will
3398 * update after a rename..
3400 process_pending_change_notify_queue((time_t)0);
3401 outsize = set_message(outbuf,0,0,True);
3407 /*******************************************************************
3408 Copy a file as part of a reply_copy.
3409 ******************************************************************/
3411 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3412 int count,BOOL target_is_directory, int *err_ret)
3415 SMB_STRUCT_STAT src_sbuf, sbuf2;
3417 files_struct *fsp1,*fsp2;
3422 pstrcpy(dest,dest1);
3423 if (target_is_directory) {
3424 char *p = strrchr_m(src,'/');
3433 if (!vfs_file_exist(conn,src,&src_sbuf))
3436 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3437 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3442 if (!target_is_directory && count)
3443 ofun = FILE_EXISTS_OPEN;
3445 if (vfs_stat(conn,dest,&sbuf2) == -1)
3446 ZERO_STRUCTP(&sbuf2);
3448 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3449 ofun,src_sbuf.st_mode,0,&Access,&action);
3452 close_file(fsp1,False);
3456 if ((ofun&3) == 1) {
3457 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3458 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3460 * Stop the copy from occurring.
3463 src_sbuf.st_size = 0;
3467 if (src_sbuf.st_size)
3468 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3470 close_file(fsp1,False);
3472 /* Ensure the modtime is set correctly on the destination file. */
3473 fsp2->pending_modtime = src_sbuf.st_mtime;
3476 * As we are opening fsp1 read-only we only expect
3477 * an error on close on fsp2 if we are out of space.
3478 * Thus we don't look at the error return from the
3481 *err_ret = close_file(fsp2,False);
3483 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3486 /****************************************************************************
3487 Reply to a file copy.
3488 ****************************************************************************/
3490 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3495 pstring mask,newname;
3498 int error = ERRnoaccess;
3502 int tid2 = SVAL(inbuf,smb_vwv0);
3503 int ofun = SVAL(inbuf,smb_vwv1);
3504 int flags = SVAL(inbuf,smb_vwv2);
3505 BOOL target_is_directory=False;
3506 BOOL bad_path1 = False;
3507 BOOL bad_path2 = False;
3509 SMB_STRUCT_STAT sbuf1, sbuf2;
3511 START_PROFILE(SMBcopy);
3513 *directory = *mask = 0;
3516 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3517 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3519 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3521 if (tid2 != conn->cnum) {
3522 /* can't currently handle inter share copies XXXX */
3523 DEBUG(3,("Rejecting inter-share copy\n"));
3524 END_PROFILE(SMBcopy);
3525 return ERROR_DOS(ERRSRV,ERRinvdevice);
3528 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3529 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3531 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3532 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3534 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3536 if ((flags&1) && target_is_directory) {
3537 END_PROFILE(SMBcopy);
3538 return ERROR_DOS(ERRDOS,ERRbadfile);
3541 if ((flags&2) && !target_is_directory) {
3542 END_PROFILE(SMBcopy);
3543 return ERROR_DOS(ERRDOS,ERRbadpath);
3546 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3547 /* wants a tree copy! XXXX */
3548 DEBUG(3,("Rejecting tree copy\n"));
3549 END_PROFILE(SMBcopy);
3550 return ERROR_DOS(ERRSRV,ERRerror);
3553 p = strrchr_m(name,'/');
3555 pstrcpy(directory,"./");
3559 pstrcpy(directory,name);
3564 * We should only check the mangled cache
3565 * here if unix_convert failed. This means
3566 * that the path in 'mask' doesn't exist
3567 * on the file system and so we need to look
3568 * for a possible mangle. This patch from
3569 * Tine Smukavec <valentin.smukavec@hermes.si>.
3572 if (!rc && mangle_is_mangled(mask))
3573 mangle_check_cache( mask );
3575 has_wild = ms_has_wild(mask);
3578 pstrcat(directory,"/");
3579 pstrcat(directory,mask);
3580 if (resolve_wildcards(directory,newname) &&
3581 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3585 END_PROFILE(SMBcopy);
3586 return(UNIXERROR(ERRHRD,ERRgeneral));
3589 exists = vfs_file_exist(conn,directory,NULL);
3592 void *dirptr = NULL;
3596 if (check_name(directory,conn))
3597 dirptr = OpenDir(conn, directory, True);
3602 if (strequal(mask,"????????.???"))
3605 while ((dname = ReadDirName(dirptr))) {
3607 pstrcpy(fname,dname);
3609 if(!mask_match(fname, mask, case_sensitive))
3612 error = ERRnoaccess;
3613 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3614 pstrcpy(destname,newname);
3615 if (resolve_wildcards(fname,destname) &&
3616 copy_file(fname,destname,conn,ofun,
3617 count,target_is_directory,&err))
3619 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3627 /* Error on close... */
3629 END_PROFILE(SMBcopy);
3630 return(UNIXERROR(ERRHRD,ERRgeneral));
3634 END_PROFILE(SMBcopy);
3635 return ERROR_DOS(ERRDOS,error);
3637 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3638 unix_ERR_class = ERRDOS;
3639 unix_ERR_code = ERRbadpath;
3641 END_PROFILE(SMBcopy);
3642 return(UNIXERROR(ERRDOS,error));
3646 outsize = set_message(outbuf,1,0,True);
3647 SSVAL(outbuf,smb_vwv0,count);
3649 END_PROFILE(SMBcopy);
3653 /****************************************************************************
3655 ****************************************************************************/
3657 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3664 START_PROFILE(pathworks_setdir);
3667 if (!CAN_SETDIR(snum)) {
3668 END_PROFILE(pathworks_setdir);
3669 return ERROR_DOS(ERRDOS,ERRnoaccess);
3672 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3674 if (strlen(newdir) == 0) {
3677 ok = vfs_directory_exist(conn,newdir,NULL);
3679 string_set(&conn->connectpath,newdir);
3683 END_PROFILE(pathworks_setdir);
3684 return ERROR_DOS(ERRDOS,ERRbadpath);
3687 outsize = set_message(outbuf,0,0,True);
3688 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3690 DEBUG(3,("setdir %s\n", newdir));
3692 END_PROFILE(pathworks_setdir);
3696 /****************************************************************************
3697 Get a lock pid, dealing with large count requests.
3698 ****************************************************************************/
3700 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3702 if(!large_file_format)
3703 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3705 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3708 /****************************************************************************
3709 Get a lock count, dealing with large count requests.
3710 ****************************************************************************/
3712 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3714 SMB_BIG_UINT count = 0;
3716 if(!large_file_format) {
3717 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3720 #if defined(HAVE_LONGLONG)
3721 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3722 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3723 #else /* HAVE_LONGLONG */
3726 * NT4.x seems to be broken in that it sends large file (64 bit)
3727 * lockingX calls even if the CAP_LARGE_FILES was *not*
3728 * negotiated. For boxes without large unsigned ints truncate the
3729 * lock count by dropping the top 32 bits.
3732 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3733 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3734 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3735 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3736 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3739 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3740 #endif /* HAVE_LONGLONG */
3746 #if !defined(HAVE_LONGLONG)
3747 /****************************************************************************
3748 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3749 ****************************************************************************/
3751 static uint32 map_lock_offset(uint32 high, uint32 low)
3755 uint32 highcopy = high;
3758 * Try and find out how many significant bits there are in high.
3761 for(i = 0; highcopy; i++)
3765 * We use 31 bits not 32 here as POSIX
3766 * lock offsets may not be negative.
3769 mask = (~0) << (31 - i);
3772 return 0; /* Fail. */
3778 #endif /* !defined(HAVE_LONGLONG) */
3780 /****************************************************************************
3781 Get a lock offset, dealing with large offset requests.
3782 ****************************************************************************/
3784 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3786 SMB_BIG_UINT offset = 0;
3790 if(!large_file_format) {
3791 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3794 #if defined(HAVE_LONGLONG)
3795 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3796 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3797 #else /* HAVE_LONGLONG */
3800 * NT4.x seems to be broken in that it sends large file (64 bit)
3801 * lockingX calls even if the CAP_LARGE_FILES was *not*
3802 * negotiated. For boxes without large unsigned ints mangle the
3803 * lock offset by mapping the top 32 bits onto the lower 32.
3806 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3807 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3808 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3811 if((new_low = map_lock_offset(high, low)) == 0) {
3813 return (SMB_BIG_UINT)-1;
3816 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3817 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3818 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3819 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3822 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3823 #endif /* HAVE_LONGLONG */
3829 /****************************************************************************
3830 Reply to a lockingX request.
3831 ****************************************************************************/
3833 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3835 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3836 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3837 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3838 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3839 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3840 SMB_BIG_UINT count = 0, offset = 0;
3842 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3845 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3849 START_PROFILE(SMBlockingX);
3851 CHECK_FSP(fsp,conn);
3853 data = smb_buf(inbuf);
3855 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3856 /* we don't support these - and CANCEL_LOCK makes w2k
3857 and XP reboot so I don't really want to be
3858 compatible! (tridge) */
3859 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3862 /* Check if this is an oplock break on a file
3863 we have granted an oplock on.
3865 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3866 /* Client can insist on breaking to none. */
3867 BOOL break_to_none = (oplocklevel == 0);
3869 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3870 (unsigned int)oplocklevel, fsp->fnum ));
3873 * Make sure we have granted an exclusive or batch oplock on this file.
3876 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3877 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3878 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3880 /* if this is a pure oplock break request then don't send a reply */
3881 if (num_locks == 0 && num_ulocks == 0) {
3882 END_PROFILE(SMBlockingX);
3885 END_PROFILE(SMBlockingX);
3886 return ERROR_DOS(ERRDOS,ERRlock);
3890 if (remove_oplock(fsp, break_to_none) == False) {
3891 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3895 /* if this is a pure oplock break request then don't send a reply */
3896 if (num_locks == 0 && num_ulocks == 0) {
3897 /* Sanity check - ensure a pure oplock break is not a
3899 if(CVAL(inbuf,smb_vwv0) != 0xff)
3900 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3901 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3902 END_PROFILE(SMBlockingX);
3908 * We do this check *after* we have checked this is not a oplock break
3909 * response message. JRA.
3912 release_level_2_oplocks_on_change(fsp);
3914 /* Data now points at the beginning of the list
3915 of smb_unlkrng structs */
3916 for(i = 0; i < (int)num_ulocks; i++) {
3917 lock_pid = get_lock_pid( data, i, large_file_format);
3918 count = get_lock_count( data, i, large_file_format);
3919 offset = get_lock_offset( data, i, large_file_format, &err);
3922 * There is no error code marked "stupid client bug".... :-).
3925 END_PROFILE(SMBlockingX);
3926 return ERROR_DOS(ERRDOS,ERRnoaccess);
3929 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3930 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3932 status = do_unlock(fsp,conn,lock_pid,count,offset);
3933 if (NT_STATUS_V(status)) {
3934 END_PROFILE(SMBlockingX);
3935 return ERROR_NT(status);
3939 /* Setup the timeout in seconds. */
3941 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
3943 /* Now do any requested locks */
3944 data += ((large_file_format ? 20 : 10)*num_ulocks);
3946 /* Data now points at the beginning of the list
3947 of smb_lkrng structs */
3949 for(i = 0; i < (int)num_locks; i++) {
3950 lock_pid = get_lock_pid( data, i, large_file_format);
3951 count = get_lock_count( data, i, large_file_format);
3952 offset = get_lock_offset( data, i, large_file_format, &err);
3955 * There is no error code marked "stupid client bug".... :-).
3958 END_PROFILE(SMBlockingX);
3959 return ERROR_DOS(ERRDOS,ERRnoaccess);
3962 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3963 (double)offset, (double)count, (unsigned int)lock_pid,
3964 fsp->fsp_name, (int)lock_timeout ));
3966 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
3967 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3968 if (NT_STATUS_V(status)) {
3969 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
3971 * A blocking lock was requested. Package up
3972 * this smb into a queued request and push it
3973 * onto the blocking lock queue.
3975 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
3976 END_PROFILE(SMBlockingX);
3984 /* If any of the above locks failed, then we must unlock
3985 all of the previous locks (X/Open spec). */
3986 if (i != num_locks && num_locks != 0) {
3988 * Ensure we don't do a remove on the lock that just failed,
3989 * as under POSIX rules, if we have a lock already there, we
3990 * will delete it (and we shouldn't) .....
3992 for(i--; i >= 0; i--) {
3993 lock_pid = get_lock_pid( data, i, large_file_format);
3994 count = get_lock_count( data, i, large_file_format);
3995 offset = get_lock_offset( data, i, large_file_format, &err);
3998 * There is no error code marked "stupid client bug".... :-).
4001 END_PROFILE(SMBlockingX);
4002 return ERROR_DOS(ERRDOS,ERRnoaccess);
4005 do_unlock(fsp,conn,lock_pid,count,offset);
4007 END_PROFILE(SMBlockingX);
4008 return ERROR_NT(status);
4011 set_message(outbuf,2,0,True);
4013 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4014 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4016 END_PROFILE(SMBlockingX);
4017 return chain_reply(inbuf,outbuf,length,bufsize);
4020 /****************************************************************************
4021 Reply to a SMBreadbmpx (read block multiplex) request.
4022 ****************************************************************************/
4024 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4035 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4036 START_PROFILE(SMBreadBmpx);
4038 /* this function doesn't seem to work - disable by default */
4039 if (!lp_readbmpx()) {
4040 END_PROFILE(SMBreadBmpx);
4041 return ERROR_DOS(ERRSRV,ERRuseSTD);
4044 outsize = set_message(outbuf,8,0,True);
4046 CHECK_FSP(fsp,conn);
4049 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4050 maxcount = SVAL(inbuf,smb_vwv3);
4052 data = smb_buf(outbuf);
4053 pad = ((long)data)%4;
4058 max_per_packet = bufsize-(outsize+pad);
4062 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4063 END_PROFILE(SMBreadBmpx);
4064 return ERROR_DOS(ERRDOS,ERRlock);
4068 size_t N = MIN(max_per_packet,tcount-total_read);
4070 nread = read_file(fsp,data,startpos,N);
4075 if (nread < (ssize_t)N)
4076 tcount = total_read + nread;
4078 set_message(outbuf,8,nread,False);
4079 SIVAL(outbuf,smb_vwv0,startpos);
4080 SSVAL(outbuf,smb_vwv2,tcount);
4081 SSVAL(outbuf,smb_vwv6,nread);
4082 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4084 if (!send_smb(smbd_server_fd(),outbuf))
4085 exit_server("reply_readbmpx: send_smb failed.");
4087 total_read += nread;
4089 } while (total_read < (ssize_t)tcount);
4091 END_PROFILE(SMBreadBmpx);
4095 /****************************************************************************
4096 Reply to a SMBsetattrE.
4097 ****************************************************************************/
4099 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4101 struct utimbuf unix_times;
4103 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4104 START_PROFILE(SMBsetattrE);
4106 outsize = set_message(outbuf,0,0,True);
4108 if(!fsp || (fsp->conn != conn)) {
4109 END_PROFILE(SMBgetattrE);
4110 return ERROR_DOS(ERRDOS,ERRbadfid);
4114 * Convert the DOS times into unix times. Ignore create
4115 * time as UNIX can't set this.
4118 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4119 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4122 * Patch from Ray Frush <frush@engr.colostate.edu>
4123 * Sometimes times are sent as zero - ignore them.
4126 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4127 /* Ignore request */
4128 if( DEBUGLVL( 3 ) ) {
4129 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4130 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4132 END_PROFILE(SMBsetattrE);
4134 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4135 /* set modify time = to access time if modify time was 0 */
4136 unix_times.modtime = unix_times.actime;
4139 /* Set the date on this file */
4140 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4141 END_PROFILE(SMBsetattrE);
4142 return ERROR_DOS(ERRDOS,ERRnoaccess);
4145 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4146 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4148 END_PROFILE(SMBsetattrE);
4153 /* Back from the dead for OS/2..... JRA. */
4155 /****************************************************************************
4156 Reply to a SMBwritebmpx (write block multiplex primary) request.
4157 ****************************************************************************/
4159 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4162 ssize_t nwritten = -1;
4169 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4170 START_PROFILE(SMBwriteBmpx);
4172 CHECK_FSP(fsp,conn);
4176 tcount = SVAL(inbuf,smb_vwv1);
4177 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4178 write_through = BITSETW(inbuf+smb_vwv7,0);
4179 numtowrite = SVAL(inbuf,smb_vwv10);
4180 smb_doff = SVAL(inbuf,smb_vwv11);
4182 data = smb_base(inbuf) + smb_doff;
4184 /* If this fails we need to send an SMBwriteC response,
4185 not an SMBwritebmpx - set this up now so we don't forget */
4186 SCVAL(outbuf,smb_com,SMBwritec);
4188 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4189 END_PROFILE(SMBwriteBmpx);
4190 return(ERROR_DOS(ERRDOS,ERRlock));
4193 nwritten = write_file(fsp,data,startpos,numtowrite);
4195 if(lp_syncalways(SNUM(conn)) || write_through)
4196 sync_file(conn,fsp);
4198 if(nwritten < (ssize_t)numtowrite) {
4199 END_PROFILE(SMBwriteBmpx);
4200 return(UNIXERROR(ERRHRD,ERRdiskfull));
4203 /* If the maximum to be written to this file
4204 is greater than what we just wrote then set
4205 up a secondary struct to be attached to this
4206 fd, we will use this to cache error messages etc. */
4208 if((ssize_t)tcount > nwritten) {
4209 write_bmpx_struct *wbms;
4210 if(fsp->wbmpx_ptr != NULL)
4211 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4213 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4215 DEBUG(0,("Out of memory in reply_readmpx\n"));
4216 END_PROFILE(SMBwriteBmpx);
4217 return(ERROR_DOS(ERRSRV,ERRnoresource));
4219 wbms->wr_mode = write_through;
4220 wbms->wr_discard = False; /* No errors yet */
4221 wbms->wr_total_written = nwritten;
4222 wbms->wr_errclass = 0;
4224 fsp->wbmpx_ptr = wbms;
4227 /* We are returning successfully, set the message type back to
4229 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4231 outsize = set_message(outbuf,1,0,True);
4233 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4235 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4236 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4238 if (write_through && tcount==nwritten) {
4239 /* We need to send both a primary and a secondary response */
4240 smb_setlen(outbuf,outsize - 4);
4241 if (!send_smb(smbd_server_fd(),outbuf))
4242 exit_server("reply_writebmpx: send_smb failed.");
4244 /* Now the secondary */
4245 outsize = set_message(outbuf,1,0,True);
4246 SCVAL(outbuf,smb_com,SMBwritec);
4247 SSVAL(outbuf,smb_vwv0,nwritten);
4250 END_PROFILE(SMBwriteBmpx);
4254 /****************************************************************************
4255 Reply to a SMBwritebs (write block multiplex secondary) request.
4256 ****************************************************************************/
4258 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4261 ssize_t nwritten = -1;
4268 write_bmpx_struct *wbms;
4269 BOOL send_response = False;
4270 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4271 START_PROFILE(SMBwriteBs);
4273 CHECK_FSP(fsp,conn);
4276 tcount = SVAL(inbuf,smb_vwv1);
4277 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4278 numtowrite = SVAL(inbuf,smb_vwv6);
4279 smb_doff = SVAL(inbuf,smb_vwv7);
4281 data = smb_base(inbuf) + smb_doff;
4283 /* We need to send an SMBwriteC response, not an SMBwritebs */
4284 SCVAL(outbuf,smb_com,SMBwritec);
4286 /* This fd should have an auxiliary struct attached,
4287 check that it does */
4288 wbms = fsp->wbmpx_ptr;
4290 END_PROFILE(SMBwriteBs);
4294 /* If write through is set we can return errors, else we must cache them */
4295 write_through = wbms->wr_mode;
4297 /* Check for an earlier error */
4298 if(wbms->wr_discard) {
4299 END_PROFILE(SMBwriteBs);
4300 return -1; /* Just discard the packet */
4303 nwritten = write_file(fsp,data,startpos,numtowrite);
4305 if(lp_syncalways(SNUM(conn)) || write_through)
4306 sync_file(conn,fsp);
4308 if (nwritten < (ssize_t)numtowrite) {
4310 /* We are returning an error - we can delete the aux struct */
4313 fsp->wbmpx_ptr = NULL;
4314 END_PROFILE(SMBwriteBs);
4315 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4317 END_PROFILE(SMBwriteBs);
4318 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4321 /* Increment the total written, if this matches tcount
4322 we can discard the auxiliary struct (hurrah !) and return a writeC */
4323 wbms->wr_total_written += nwritten;
4324 if(wbms->wr_total_written >= tcount) {
4325 if (write_through) {
4326 outsize = set_message(outbuf,1,0,True);
4327 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4328 send_response = True;
4332 fsp->wbmpx_ptr = NULL;
4336 END_PROFILE(SMBwriteBs);
4340 END_PROFILE(SMBwriteBs);
4344 /****************************************************************************
4345 Reply to a SMBgetattrE.
4346 ****************************************************************************/
4348 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4350 SMB_STRUCT_STAT sbuf;
4353 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4354 START_PROFILE(SMBgetattrE);
4356 outsize = set_message(outbuf,11,0,True);
4358 if(!fsp || (fsp->conn != conn)) {
4359 END_PROFILE(SMBgetattrE);
4360 return ERROR_DOS(ERRDOS,ERRbadfid);
4363 /* Do an fstat on this file */
4364 if(fsp_stat(fsp, &sbuf)) {
4365 END_PROFILE(SMBgetattrE);
4366 return(UNIXERROR(ERRDOS,ERRnoaccess));
4369 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4372 * Convert the times into dos times. Set create
4373 * date to be last modify date as UNIX doesn't save
4377 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4378 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4379 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4382 SIVAL(outbuf,smb_vwv6,0);
4383 SIVAL(outbuf,smb_vwv8,0);
4385 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4386 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4388 SSVAL(outbuf,smb_vwv10, mode);
4390 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4392 END_PROFILE(SMBgetattrE);