2 Unix SMB/Netbios implementation.
4 Main SMB reply routines
5 Copyright (C) Andrew Tridgell 1992-1998
6 Copyright (C) Andrew Bartlett 2001
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles most of the reply_ calls that the server
24 makes to handle specific protocols
30 /* look in server.c for some explanation of these variables */
34 extern char magic_char;
35 extern BOOL case_sensitive;
36 extern BOOL case_preserve;
37 extern BOOL short_case_preserve;
38 extern userdom_struct current_user_info;
39 extern pstring global_myname;
40 extern int global_oplock_break;
41 uint32 global_client_caps = 0;
42 unsigned int smb_echo_count = 0;
44 extern fstring remote_machine;
45 extern BOOL global_encrypted_passwords_negotiated;
48 /****************************************************************************
49 reply to an special message
50 ****************************************************************************/
52 int reply_special(char *inbuf,char *outbuf)
55 int msg_type = CVAL(inbuf,0);
56 int msg_flags = CVAL(inbuf,1);
59 extern fstring local_machine;
65 memset(outbuf,'\0',smb_size);
70 case 0x81: /* session request */
71 CVAL(outbuf,0) = 0x82;
73 if (name_len(inbuf+4) > 50 ||
74 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
75 DEBUG(0,("Invalid name length in session request\n"));
78 name_extract(inbuf,4,name1);
79 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
80 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
83 fstrcpy(remote_machine,name2);
84 remote_machine[15] = 0;
85 trim_string(remote_machine," "," ");
86 strlower(remote_machine);
87 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
89 fstrcpy(local_machine,name1);
90 len = strlen(local_machine);
92 name_type = local_machine[15];
93 local_machine[15] = 0;
95 trim_string(local_machine," "," ");
96 strlower(local_machine);
97 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
99 DEBUG(2,("netbios connect: local=%s remote=%s\n",
100 local_machine, remote_machine ));
102 if (name_type == 'R') {
103 /* We are being asked for a pathworks session ---
105 CVAL(outbuf, 0) = 0x83;
109 /* only add the client's machine name to the list
110 of possibly valid usernames if we are operating
111 in share mode security */
112 if (lp_security() == SEC_SHARE) {
113 add_session_user(remote_machine);
116 reload_services(True);
119 claim_connection(NULL,"",MAXSTATUS,True);
123 case 0x89: /* session keepalive request
124 (some old clients produce this?) */
125 CVAL(outbuf,0) = SMBkeepalive;
129 case 0x82: /* positive session response */
130 case 0x83: /* negative session response */
131 case 0x84: /* retarget session response */
132 DEBUG(0,("Unexpected session response\n"));
135 case SMBkeepalive: /* session keepalive */
140 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
141 msg_type, msg_flags));
147 /****************************************************************************
149 ****************************************************************************/
151 int reply_tcon(connection_struct *conn,
152 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
158 uint16 vuid = SVAL(inbuf,smb_uid);
162 DATA_BLOB password_blob;
164 START_PROFILE(SMBtcon);
166 *service = *password = *dev = 0;
168 p = smb_buf(inbuf)+1;
169 p += srvstr_pull(inbuf, service, p, sizeof(service), -1, STR_TERMINATE) + 1;
170 pwlen = srvstr_pull(inbuf, password, p, sizeof(password), -1, STR_TERMINATE) + 1;
172 p += srvstr_pull(inbuf, dev, p, sizeof(dev), -1, STR_TERMINATE) + 1;
174 p = strrchr_m(service,'\\');
176 pstrcpy(service, p+1);
179 password_blob = data_blob(password, pwlen+1);
181 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
183 data_blob_clear_free(&password);
186 END_PROFILE(SMBtcon);
187 return ERROR_NT(nt_status);
190 outsize = set_message(outbuf,2,0,True);
191 SSVAL(outbuf,smb_vwv0,max_recv);
192 SSVAL(outbuf,smb_vwv1,conn->cnum);
193 SSVAL(outbuf,smb_tid,conn->cnum);
195 DEBUG(3,("tcon service=%s cnum=%d\n",
196 service, conn->cnum));
198 END_PROFILE(SMBtcon);
202 /****************************************************************************
203 Reply to a tcon and X.
204 ****************************************************************************/
206 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
212 uint16 vuid = SVAL(inbuf,smb_uid);
213 int passlen = SVAL(inbuf,smb_vwv3);
216 extern BOOL global_encrypted_passwords_negotiated;
217 START_PROFILE(SMBtconX);
219 *service = *devicename = 0;
221 /* we might have to close an old one */
222 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
223 close_cnum(conn,vuid);
226 if (passlen > MAX_PASS_LEN) {
227 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
230 if (global_encrypted_passwords_negotiated) {
231 password = data_blob(smb_buf(inbuf),passlen);
233 password = data_blob(smb_buf(inbuf),passlen+1);
234 /* Ensure correct termination */
235 password.data[passlen]=0;
238 p = smb_buf(inbuf) + passlen;
239 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
242 * the service name can be either: \\server\share
243 * or share directly like on the DELL PowerVault 705
246 q = strchr_m(path+2,'\\');
248 END_PROFILE(SMBtconX);
249 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
251 fstrcpy(service,q+1);
254 fstrcpy(service,path);
256 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
258 DEBUG(4,("Got device type %s\n",devicename));
260 conn = make_connection(service,password,devicename,vuid,&nt_status);
262 data_blob_clear_free(&password);
265 END_PROFILE(SMBtconX);
266 return ERROR_NT(nt_status);
269 if (Protocol < PROTOCOL_NT1) {
270 set_message(outbuf,2,0,True);
272 p += srvstr_push(outbuf, p, devicename, -1,
273 STR_TERMINATE|STR_ASCII);
274 set_message_end(outbuf,p);
276 /* NT sets the fstype of IPC$ to the null string */
277 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
279 set_message(outbuf,3,0,True);
282 p += srvstr_push(outbuf, p, devicename, -1,
283 STR_TERMINATE|STR_ASCII);
284 p += srvstr_push(outbuf, p, fsname, -1,
287 set_message_end(outbuf,p);
289 /* what does setting this bit do? It is set by NT4 and
290 may affect the ability to autorun mounted cdroms */
291 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS);
293 init_dfsroot(conn, inbuf, outbuf);
297 DEBUG(3,("tconX service=%s \n",
300 /* set the incoming and outgoing tid to the just created one */
301 SSVAL(inbuf,smb_tid,conn->cnum);
302 SSVAL(outbuf,smb_tid,conn->cnum);
304 END_PROFILE(SMBtconX);
305 return chain_reply(inbuf,outbuf,length,bufsize);
309 /****************************************************************************
310 reply to an unknown type
311 ****************************************************************************/
312 int reply_unknown(char *inbuf,char *outbuf)
315 type = CVAL(inbuf,smb_com);
317 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
318 smb_fn_name(type), type, type));
320 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
324 /****************************************************************************
326 ****************************************************************************/
327 int reply_ioctl(connection_struct *conn,
328 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
330 uint16 device = SVAL(inbuf,smb_vwv1);
331 uint16 function = SVAL(inbuf,smb_vwv2);
332 uint32 ioctl_code = (device << 16) + function;
333 int replysize, outsize;
335 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
336 START_PROFILE(SMBioctl);
338 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
342 case IOCTL_QUERY_JOB_INFO:
346 END_PROFILE(SMBioctl);
347 return(ERROR_DOS(ERRSRV,ERRnosupport));
350 outsize = set_message(outbuf,8,replysize+1,True);
351 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
352 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
353 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
354 p = smb_buf(outbuf) + 1; /* Allow for alignment */
358 case IOCTL_QUERY_JOB_INFO:
359 SSVAL(p,0,fsp->print_jobid); /* Job number */
360 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
361 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
365 END_PROFILE(SMBioctl);
369 /****************************************************************************
371 ****************************************************************************/
372 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
378 BOOL bad_path = False;
379 SMB_STRUCT_STAT sbuf;
380 START_PROFILE(SMBchkpth);
382 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
384 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
386 unix_convert(name,conn,0,&bad_path,&sbuf);
388 mode = SVAL(inbuf,smb_vwv0);
390 if (check_name(name,conn)) {
391 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
392 ok = S_ISDIR(sbuf.st_mode);
396 /* We special case this - as when a Windows machine
397 is parsing a path is steps through the components
398 one at a time - if a component fails it expects
399 ERRbadpath, not ERRbadfile.
401 if(errno == ENOENT) {
402 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
405 return(UNIXERROR(ERRDOS,ERRbadpath));
408 outsize = set_message(outbuf,0,0,True);
410 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
412 END_PROFILE(SMBchkpth);
417 /****************************************************************************
419 ****************************************************************************/
420 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
424 SMB_STRUCT_STAT sbuf;
429 BOOL bad_path = False;
431 START_PROFILE(SMBgetatr);
433 p = smb_buf(inbuf) + 1;
434 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
436 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
438 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
439 under WfWg - weird! */
442 mode = aHIDDEN | aDIR;
443 if (!CAN_WRITE(conn)) mode |= aRONLY;
450 unix_convert(fname,conn,0,&bad_path,&sbuf);
451 if (check_name(fname,conn))
453 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
455 mode = dos_mode(conn,fname,&sbuf);
457 mtime = sbuf.st_mtime;
463 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
469 if((errno == ENOENT) && bad_path)
471 unix_ERR_class = ERRDOS;
472 unix_ERR_code = ERRbadpath;
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) | 0x40); /* IS_LONG_NAME */
492 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
494 END_PROFILE(SMBgetatr);
499 /****************************************************************************
501 ****************************************************************************/
502 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
509 SMB_STRUCT_STAT sbuf;
510 BOOL bad_path = False;
513 START_PROFILE(SMBsetatr);
515 p = smb_buf(inbuf) + 1;
516 p += srvstr_pull(inbuf, fname, p, sizeof(fname), -1, STR_TERMINATE);
517 unix_convert(fname,conn,0,&bad_path,&sbuf);
519 mode = SVAL(inbuf,smb_vwv0);
520 mtime = make_unix_date3(inbuf+smb_vwv1);
522 if (VALID_STAT_OF_DIR(sbuf))
524 if (check_name(fname,conn))
525 ok = (file_chmod(conn,fname,mode,NULL) == 0);
527 ok = set_filetime(conn,fname,mtime);
531 if((errno == ENOENT) && bad_path)
533 unix_ERR_class = ERRDOS;
534 unix_ERR_code = ERRbadpath;
537 END_PROFILE(SMBsetatr);
538 return(UNIXERROR(ERRDOS,ERRnoaccess));
541 outsize = set_message(outbuf,0,0,True);
543 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
545 END_PROFILE(SMBsetatr);
550 /****************************************************************************
552 ****************************************************************************/
553 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
556 SMB_BIG_UINT dfree,dsize,bsize;
557 START_PROFILE(SMBdskattr);
559 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
561 outsize = set_message(outbuf,5,0,True);
563 SSVAL(outbuf,smb_vwv0,dsize);
564 SSVAL(outbuf,smb_vwv1,bsize/512);
565 SSVAL(outbuf,smb_vwv2,512);
566 SSVAL(outbuf,smb_vwv3,dfree);
568 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
570 END_PROFILE(SMBdskattr);
575 /****************************************************************************
577 Can be called from SMBsearch, SMBffirst or SMBfunique.
578 ****************************************************************************/
579 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
590 BOOL finished = False;
599 BOOL check_descend = False;
600 BOOL expect_close = False;
601 BOOL can_open = True;
602 BOOL bad_path = False;
603 START_PROFILE(SMBsearch);
605 *mask = *directory = *fname = 0;
607 /* If we were called as SMBffirst then we must expect close. */
608 if(CVAL(inbuf,smb_com) == SMBffirst)
611 outsize = set_message(outbuf,1,3,True);
612 maxentries = SVAL(inbuf,smb_vwv0);
613 dirtype = SVAL(inbuf,smb_vwv1);
614 p = smb_buf(inbuf) + 1;
615 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
617 status_len = SVAL(p, 0);
620 /* dirtype &= ~aDIR; */
624 SMB_STRUCT_STAT sbuf;
627 pstrcpy(directory,path);
629 unix_convert(directory,conn,0,&bad_path,&sbuf);
632 if (!check_name(directory,conn))
635 p = strrchr_m(dir2,'/');
647 p = strrchr_m(directory,'/');
653 if (strlen(directory) == 0)
654 pstrcpy(directory,"./");
655 memset((char *)status,'\0',21);
656 CVAL(status,0) = dirtype;
661 dirtype = CVAL(status,0) & 0x1F;
662 conn->dirptr = dptr_fetch(status+12,&dptr_num);
665 string_set(&conn->dirpath,dptr_path(dptr_num));
666 fstrcpy(mask, dptr_wcard(dptr_num));
671 p = smb_buf(outbuf) + 3;
677 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
682 if((errno == ENOENT) && bad_path)
684 unix_ERR_class = ERRDOS;
685 unix_ERR_code = ERRbadpath;
687 END_PROFILE(SMBsearch);
688 return (UNIXERROR(ERRDOS,ERRnofids));
690 END_PROFILE(SMBsearch);
691 return ERROR_DOS(ERRDOS,ERRnofids);
693 dptr_set_wcard(dptr_num, strdup(mask));
696 DEBUG(4,("dptr_num is %d\n",dptr_num));
700 if ((dirtype&0x1F) == aVOLID)
703 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
704 dptr_fill(p+12,dptr_num);
705 if (dptr_zero(p+12) && (status_len==0))
709 p += DIR_STRUCT_SIZE;
713 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
714 conn->dirpath,lp_dontdescend(SNUM(conn))));
715 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
716 check_descend = True;
718 for (i=numentries;(i<maxentries) && !finished;i++)
721 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
725 make_dir_struct(p,mask,fname,size,mode,date);
726 dptr_fill(p+12,dptr_num);
729 p += DIR_STRUCT_SIZE;
738 if (numentries == 0 || !ok)
740 CVAL(outbuf,smb_rcls) = ERRDOS;
741 SSVAL(outbuf,smb_err,ERRnofiles);
742 dptr_close(&dptr_num);
745 /* If we were called as SMBffirst with smb_search_id == NULL
746 and no entries were found then return error and close dirptr
749 if(ok && expect_close && numentries == 0 && status_len == 0)
751 CVAL(outbuf,smb_rcls) = ERRDOS;
752 SSVAL(outbuf,smb_err,ERRnofiles);
753 /* Also close the dptr - we know it's gone */
754 dptr_close(&dptr_num);
757 /* If we were called as SMBfunique, then we can close the dirptr now ! */
758 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
759 dptr_close(&dptr_num);
761 SSVAL(outbuf,smb_vwv0,numentries);
762 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
763 CVAL(smb_buf(outbuf),0) = 5;
764 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
766 if (Protocol >= PROTOCOL_NT1) {
767 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | 0x40); /* IS_LONG_NAME */
770 outsize += DIR_STRUCT_SIZE*numentries;
771 smb_setlen(outbuf,outsize - 4);
773 if ((! *directory) && dptr_path(dptr_num))
774 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
776 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
777 smb_fn_name(CVAL(inbuf,smb_com)),
778 mask, directory, dirtype, numentries, maxentries ) );
780 END_PROFILE(SMBsearch);
785 /****************************************************************************
786 reply to a fclose (stop directory search)
787 ****************************************************************************/
788 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
797 START_PROFILE(SMBfclose);
799 outsize = set_message(outbuf,1,0,True);
800 p = smb_buf(inbuf) + 1;
801 p += srvstr_pull(inbuf, path, p, sizeof(path), -1, STR_TERMINATE);
803 status_len = SVAL(p,0);
806 if (status_len == 0) {
807 END_PROFILE(SMBfclose);
808 return ERROR_DOS(ERRSRV,ERRsrverror);
813 if(dptr_fetch(status+12,&dptr_num)) {
814 /* Close the dptr - we know it's gone */
815 dptr_close(&dptr_num);
818 SSVAL(outbuf,smb_vwv0,0);
820 DEBUG(3,("search close\n"));
822 END_PROFILE(SMBfclose);
827 /****************************************************************************
829 ****************************************************************************/
831 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
841 SMB_STRUCT_STAT sbuf;
842 BOOL bad_path = False;
844 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
845 START_PROFILE(SMBopen);
847 share_mode = SVAL(inbuf,smb_vwv0);
849 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
851 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
853 unix_convert(fname,conn,0,&bad_path,&sbuf);
855 unixmode = unix_mode(conn,aARCH,fname);
857 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
858 unixmode, oplock_request,&rmode,NULL);
862 if((errno == ENOENT) && bad_path)
864 unix_ERR_class = ERRDOS;
865 unix_ERR_code = ERRbadpath;
867 END_PROFILE(SMBopen);
868 return(UNIXERROR(ERRDOS,ERRnoaccess));
872 fmode = dos_mode(conn,fname,&sbuf);
873 mtime = sbuf.st_mtime;
876 DEBUG(3,("attempt to open a directory %s\n",fname));
877 close_file(fsp,False);
878 END_PROFILE(SMBopen);
879 return ERROR_DOS(ERRDOS,ERRnoaccess);
882 outsize = set_message(outbuf,7,0,True);
883 SSVAL(outbuf,smb_vwv0,fsp->fnum);
884 SSVAL(outbuf,smb_vwv1,fmode);
885 if(lp_dos_filetime_resolution(SNUM(conn)) )
886 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
888 put_dos_date3(outbuf,smb_vwv2,mtime);
889 SIVAL(outbuf,smb_vwv4,(uint32)size);
890 SSVAL(outbuf,smb_vwv6,rmode);
892 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
893 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
896 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
897 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
898 END_PROFILE(SMBopen);
903 /****************************************************************************
904 reply to an open and X
905 ****************************************************************************/
906 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
909 int smb_mode = SVAL(inbuf,smb_vwv3);
910 int smb_attr = SVAL(inbuf,smb_vwv5);
911 /* Breakout the oplock request bits so we can set the
912 reply bits separately. */
913 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
914 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
915 BOOL oplock_request = ex_oplock_request | core_oplock_request;
917 int open_flags = SVAL(inbuf,smb_vwv2);
918 int smb_sattr = SVAL(inbuf,smb_vwv4);
919 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
921 int smb_ofun = SVAL(inbuf,smb_vwv8);
924 int fmode=0,mtime=0,rmode=0;
925 SMB_STRUCT_STAT sbuf;
927 BOOL bad_path = False;
929 START_PROFILE(SMBopenX);
931 /* If it's an IPC, pass off the pipe handler. */
933 if (lp_nt_pipe_support()) {
934 END_PROFILE(SMBopenX);
935 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
937 END_PROFILE(SMBopenX);
938 return ERROR_DOS(ERRSRV,ERRaccess);
942 /* XXXX we need to handle passed times, sattr and flags */
943 srvstr_pull(inbuf, fname, smb_buf(inbuf), sizeof(fname), -1, STR_TERMINATE);
945 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
947 unix_convert(fname,conn,0,&bad_path,&sbuf);
949 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
951 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
952 oplock_request, &rmode,&smb_action);
956 if((errno == ENOENT) && bad_path)
958 unix_ERR_class = ERRDOS;
959 unix_ERR_code = ERRbadpath;
961 END_PROFILE(SMBopenX);
962 return(UNIXERROR(ERRDOS,ERRnoaccess));
966 fmode = dos_mode(conn,fname,&sbuf);
967 mtime = sbuf.st_mtime;
969 close_file(fsp,False);
970 END_PROFILE(SMBopenX);
971 return ERROR_DOS(ERRDOS,ERRnoaccess);
974 /* If the caller set the extended oplock request bit
975 and we granted one (by whatever means) - set the
976 correct bit for extended oplock reply.
979 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
980 smb_action |= EXTENDED_OPLOCK_GRANTED;
983 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
984 smb_action |= EXTENDED_OPLOCK_GRANTED;
987 /* If the caller set the core oplock request bit
988 and we granted one (by whatever means) - set the
989 correct bit for core oplock reply.
992 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
993 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
996 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
997 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1000 set_message(outbuf,15,0,True);
1001 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1002 SSVAL(outbuf,smb_vwv3,fmode);
1003 if(lp_dos_filetime_resolution(SNUM(conn)) )
1004 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1006 put_dos_date3(outbuf,smb_vwv4,mtime);
1007 SIVAL(outbuf,smb_vwv6,(uint32)size);
1008 SSVAL(outbuf,smb_vwv8,rmode);
1009 SSVAL(outbuf,smb_vwv11,smb_action);
1011 END_PROFILE(SMBopenX);
1012 return chain_reply(inbuf,outbuf,length,bufsize);
1016 /****************************************************************************
1017 reply to a SMBulogoffX
1018 ****************************************************************************/
1019 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1021 uint16 vuid = SVAL(inbuf,smb_uid);
1022 user_struct *vuser = get_valid_user_struct(vuid);
1023 START_PROFILE(SMBulogoffX);
1026 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1029 /* in user level security we are supposed to close any files
1030 open by this user */
1031 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1032 file_close_user(vuid);
1035 invalidate_vuid(vuid);
1037 set_message(outbuf,2,0,True);
1039 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1041 END_PROFILE(SMBulogoffX);
1042 return chain_reply(inbuf,outbuf,length,bufsize);
1046 /****************************************************************************
1047 reply to a mknew or a create
1048 ****************************************************************************/
1049 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1057 BOOL bad_path = False;
1059 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1060 SMB_STRUCT_STAT sbuf;
1061 START_PROFILE(SMBcreate);
1063 com = SVAL(inbuf,smb_com);
1065 createmode = SVAL(inbuf,smb_vwv0);
1066 srvstr_pull(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), -1, STR_TERMINATE);
1068 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1070 unix_convert(fname,conn,0,&bad_path,&sbuf);
1072 if (createmode & aVOLID) {
1073 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1076 unixmode = unix_mode(conn,createmode,fname);
1080 /* We should fail if file exists. */
1081 ofun = FILE_CREATE_IF_NOT_EXIST;
1085 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1086 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1089 /* Open file in dos compatibility share mode. */
1090 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1091 ofun, unixmode, oplock_request, NULL, NULL);
1095 if((errno == ENOENT) && bad_path)
1097 unix_ERR_class = ERRDOS;
1098 unix_ERR_code = ERRbadpath;
1100 END_PROFILE(SMBcreate);
1101 return(UNIXERROR(ERRDOS,ERRnoaccess));
1104 outsize = set_message(outbuf,1,0,True);
1105 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1107 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1108 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1111 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1112 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1114 DEBUG( 2, ( "new file %s\n", fname ) );
1115 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1116 fname, fsp->fd, createmode, (int)unixmode ) );
1118 END_PROFILE(SMBcreate);
1123 /****************************************************************************
1124 reply to a create temporary file
1125 ****************************************************************************/
1126 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1132 BOOL bad_path = False;
1134 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1136 SMB_STRUCT_STAT sbuf;
1139 START_PROFILE(SMBctemp);
1141 createmode = SVAL(inbuf,smb_vwv0);
1142 srvstr_pull(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), -1, STR_TERMINATE);
1143 pstrcat(fname,"\\TMXXXXXX");
1145 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1147 unix_convert(fname,conn,0,&bad_path,&sbuf);
1149 unixmode = unix_mode(conn,createmode,fname);
1151 tmpfd = smb_mkstemp(fname);
1153 END_PROFILE(SMBctemp);
1154 return(UNIXERROR(ERRDOS,ERRnoaccess));
1157 vfs_stat(conn,fname,&sbuf);
1159 /* Open file in dos compatibility share mode. */
1160 /* We should fail if file does not exist. */
1161 fsp = open_file_shared(conn,fname,&sbuf,
1162 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1163 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1164 unixmode, oplock_request, NULL, NULL);
1166 /* close fd from smb_mkstemp() */
1171 if((errno == ENOENT) && bad_path)
1173 unix_ERR_class = ERRDOS;
1174 unix_ERR_code = ERRbadpath;
1176 END_PROFILE(SMBctemp);
1177 return(UNIXERROR(ERRDOS,ERRnoaccess));
1180 outsize = set_message(outbuf,1,0,True);
1181 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1183 /* the returned filename is relative to the directory */
1184 s = strrchr_m(fname, '/');
1191 p = smb_buf(outbuf);
1192 SSVALS(p, 0, -1); /* what is this? not in spec */
1193 SSVAL(p, 2, strlen(s));
1195 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1196 outsize = set_message_end(outbuf, p);
1198 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1199 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1202 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1203 CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
1205 DEBUG( 2, ( "created temp file %s\n", fname ) );
1206 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1207 fname, fsp->fd, createmode, (int)unixmode ) );
1209 END_PROFILE(SMBctemp);
1214 /*******************************************************************
1215 check if a user is allowed to delete a file
1216 ********************************************************************/
1217 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1219 SMB_STRUCT_STAT sbuf;
1222 if (!CAN_WRITE(conn)) return NT_STATUS_MEDIA_WRITE_PROTECTED;
1224 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1226 fmode = dos_mode(conn,fname,&sbuf);
1227 if (fmode & aDIR) return NT_STATUS_FILE_IS_A_DIRECTORY;
1228 if (!lp_delete_readonly(SNUM(conn))) {
1229 if (fmode & aRONLY) return NT_STATUS_CANNOT_DELETE;
1231 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1232 return NT_STATUS_CANNOT_DELETE;
1234 if (!check_file_sharing(conn,fname,False)) return NT_STATUS_SHARING_VIOLATION;
1236 return NT_STATUS_OK;
1239 /****************************************************************************
1240 The guts of the unlink command, split out so it may be called by the NT SMB
1242 ****************************************************************************/
1244 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1250 NTSTATUS error = NT_STATUS_OK;
1253 BOOL bad_path = False;
1255 SMB_STRUCT_STAT sbuf;
1257 *directory = *mask = 0;
1259 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1261 p = strrchr_m(name,'/');
1263 pstrcpy(directory,"./");
1267 pstrcpy(directory,name);
1272 * We should only check the mangled cache
1273 * here if unix_convert failed. This means
1274 * that the path in 'mask' doesn't exist
1275 * on the file system and so we need to look
1276 * for a possible mangle. This patch from
1277 * Tine Smukavec <valentin.smukavec@hermes.si>.
1280 if (!rc && is_mangled(mask))
1281 check_mangled_cache( mask );
1283 has_wild = ms_has_wild(mask);
1286 pstrcat(directory,"/");
1287 pstrcat(directory,mask);
1288 error = can_delete(directory,conn,dirtype);
1289 if (!NT_STATUS_IS_OK(error)) return error;
1291 if (vfs_unlink(conn,directory) == 0) {
1295 exists = vfs_file_exist(conn,directory,&sbuf);
1297 void *dirptr = NULL;
1300 if (check_name(directory,conn))
1301 dirptr = OpenDir(conn, directory, True);
1303 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1304 the pattern matches against the long name, otherwise the short name
1305 We don't implement this yet XXXX
1309 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1311 if (strequal(mask,"????????.???"))
1314 while ((dname = ReadDirName(dirptr))) {
1316 pstrcpy(fname,dname);
1318 if(!mask_match(fname, mask, case_sensitive)) continue;
1320 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1321 error = can_delete(fname,conn,dirtype);
1322 if (!NT_STATUS_IS_OK(error)) continue;
1323 if (vfs_unlink(conn,fname) == 0) count++;
1324 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1330 if (count == 0 && NT_STATUS_IS_OK(error)) {
1331 error = map_nt_error_from_unix(errno);
1337 /****************************************************************************
1339 ****************************************************************************/
1341 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1348 START_PROFILE(SMBunlink);
1350 dirtype = SVAL(inbuf,smb_vwv0);
1352 srvstr_pull(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), -1, STR_TERMINATE);
1354 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1356 DEBUG(3,("reply_unlink : %s\n",name));
1358 status = unlink_internals(conn, dirtype, name);
1359 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1362 * Win2k needs a changenotify request response before it will
1363 * update after a rename..
1365 process_pending_change_notify_queue((time_t)0);
1367 outsize = set_message(outbuf,0,0,True);
1369 END_PROFILE(SMBunlink);
1373 /****************************************************************************
1375 ****************************************************************************/
1377 void fail_readraw(void)
1380 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)\n",
1382 exit_server(errstr);
1385 /****************************************************************************
1386 Reply to a readbraw (core+ protocol).
1387 ****************************************************************************/
1389 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1391 size_t maxcount,mincount;
1394 char *header = outbuf;
1397 START_PROFILE(SMBreadbraw);
1400 * Special check if an oplock break has been issued
1401 * and the readraw request croses on the wire, we must
1402 * return a zero length response here.
1405 if(global_oplock_break) {
1406 _smb_setlen(header,0);
1407 if (write_data(smbd_server_fd(),header,4) != 4)
1409 DEBUG(5,("readbraw - oplock break finished\n"));
1410 END_PROFILE(SMBreadbraw);
1414 fsp = file_fsp(inbuf,smb_vwv0);
1416 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1418 * fsp could be NULL here so use the value from the packet. JRA.
1420 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1421 _smb_setlen(header,0);
1422 if (write_data(smbd_server_fd(),header,4) != 4)
1424 END_PROFILE(SMBreadbraw);
1428 CHECK_FSP(fsp,conn);
1430 flush_write_cache(fsp, READRAW_FLUSH);
1432 startpos = IVAL(inbuf,smb_vwv1);
1433 if(CVAL(inbuf,smb_wct) == 10) {
1435 * This is a large offset (64 bit) read.
1437 #ifdef LARGE_SMB_OFF_T
1439 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1441 #else /* !LARGE_SMB_OFF_T */
1444 * Ensure we haven't been sent a >32 bit offset.
1447 if(IVAL(inbuf,smb_vwv8) != 0) {
1448 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1449 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1450 _smb_setlen(header,0);
1451 if (write_data(smbd_server_fd(),header,4) != 4)
1453 END_PROFILE(SMBreadbraw);
1457 #endif /* LARGE_SMB_OFF_T */
1460 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1461 _smb_setlen(header,0);
1462 if (write_data(smbd_server_fd(),header,4) != 4)
1464 END_PROFILE(SMBreadbraw);
1468 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1469 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1471 /* ensure we don't overrun the packet size */
1472 maxcount = MIN(65535,maxcount);
1473 maxcount = MAX(mincount,maxcount);
1475 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1476 SMB_OFF_T size = fsp->size;
1477 SMB_OFF_T sizeneeded = startpos + maxcount;
1479 if (size < sizeneeded) {
1481 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1483 if (!fsp->can_write)
1487 if (startpos >= size)
1490 nread = MIN(maxcount,(size - startpos));
1493 if (nread < mincount)
1496 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1497 (int)maxcount, (int)mincount, (int)nread ) );
1500 ret = read_file(fsp,header+4,startpos,nread);
1505 _smb_setlen(header,ret);
1506 if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
1509 DEBUG(5,("readbraw finished\n"));
1510 END_PROFILE(SMBreadbraw);
1514 /****************************************************************************
1515 reply to a lockread (core+ protocol)
1516 ****************************************************************************/
1517 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1525 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1526 START_PROFILE(SMBlockread);
1528 CHECK_FSP(fsp,conn);
1531 release_level_2_oplocks_on_change(fsp);
1533 numtoread = SVAL(inbuf,smb_vwv1);
1534 startpos = IVAL(inbuf,smb_vwv2);
1536 outsize = set_message(outbuf,5,3,True);
1537 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1538 data = smb_buf(outbuf) + 3;
1541 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1542 * protocol request that predates the read/write lock concept.
1543 * Thus instead of asking for a read lock here we need to ask
1544 * for a write lock. JRA.
1547 status = do_lock(fsp, conn, SVAL(inbuf,smb_pid),
1548 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1550 if (NT_STATUS_V(status)) {
1551 if (lp_blocking_locks(SNUM(conn))) {
1553 * A blocking lock was requested. Package up
1554 * this smb into a queued request and push it
1555 * onto the blocking lock queue.
1557 if(push_blocking_lock_request(inbuf, length, -1, 0))
1558 END_PROFILE(SMBlockread);
1561 END_PROFILE(SMBlockread);
1562 return ERROR_NT(status);
1565 nread = read_file(fsp,data,startpos,numtoread);
1568 END_PROFILE(SMBlockread);
1569 return(UNIXERROR(ERRDOS,ERRnoaccess));
1573 SSVAL(outbuf,smb_vwv0,nread);
1574 SSVAL(outbuf,smb_vwv5,nread+3);
1575 SSVAL(smb_buf(outbuf),1,nread);
1577 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1578 fsp->fnum, (int)numtoread, (int)nread));
1580 END_PROFILE(SMBlockread);
1585 /****************************************************************************
1587 ****************************************************************************/
1589 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1596 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1597 START_PROFILE(SMBread);
1599 CHECK_FSP(fsp,conn);
1602 numtoread = SVAL(inbuf,smb_vwv1);
1603 startpos = IVAL(inbuf,smb_vwv2);
1606 outsize = set_message(outbuf,5,3,True);
1607 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1608 data = smb_buf(outbuf) + 3;
1610 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1611 END_PROFILE(SMBread);
1612 return ERROR_DOS(ERRDOS,ERRlock);
1616 nread = read_file(fsp,data,startpos,numtoread);
1619 END_PROFILE(SMBread);
1620 return(UNIXERROR(ERRDOS,ERRnoaccess));
1624 SSVAL(outbuf,smb_vwv0,nread);
1625 SSVAL(outbuf,smb_vwv5,nread+3);
1626 CVAL(smb_buf(outbuf),0) = 1;
1627 SSVAL(smb_buf(outbuf),1,nread);
1629 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1630 fsp->fnum, (int)numtoread, (int)nread ) );
1632 END_PROFILE(SMBread);
1637 /****************************************************************************
1638 reply to a read and X
1639 ****************************************************************************/
1640 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1642 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1643 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
1644 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1645 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1648 START_PROFILE(SMBreadX);
1650 /* If it's an IPC, pass off the pipe handler. */
1652 END_PROFILE(SMBreadX);
1653 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1656 CHECK_FSP(fsp,conn);
1659 set_message(outbuf,12,0,True);
1660 data = smb_buf(outbuf);
1662 if(CVAL(inbuf,smb_wct) == 12) {
1663 #ifdef LARGE_SMB_OFF_T
1665 * This is a large offset (64 bit) read.
1667 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1669 #else /* !LARGE_SMB_OFF_T */
1672 * Ensure we haven't been sent a >32 bit offset.
1675 if(IVAL(inbuf,smb_vwv10) != 0) {
1676 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1677 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1678 END_PROFILE(SMBreadX);
1679 return ERROR_DOS(ERRDOS,ERRbadaccess);
1682 #endif /* LARGE_SMB_OFF_T */
1686 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1687 END_PROFILE(SMBreadX);
1688 return ERROR_DOS(ERRDOS,ERRlock);
1690 nread = read_file(fsp,data,startpos,smb_maxcnt);
1693 END_PROFILE(SMBreadX);
1694 return(UNIXERROR(ERRDOS,ERRnoaccess));
1697 SSVAL(outbuf,smb_vwv5,nread);
1698 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1699 SSVAL(smb_buf(outbuf),-2,nread);
1701 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
1702 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
1704 END_PROFILE(SMBreadX);
1705 return chain_reply(inbuf,outbuf,length,bufsize);
1708 /****************************************************************************
1709 reply to a writebraw (core+ or LANMAN1.0 protocol)
1710 ****************************************************************************/
1712 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1715 ssize_t total_written=0;
1716 size_t numtowrite=0;
1721 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1723 START_PROFILE(SMBwritebraw);
1725 CHECK_FSP(fsp,conn);
1728 tcount = IVAL(inbuf,smb_vwv1);
1729 startpos = IVAL(inbuf,smb_vwv3);
1730 write_through = BITSETW(inbuf+smb_vwv7,0);
1732 /* We have to deal with slightly different formats depending
1733 on whether we are using the core+ or lanman1.0 protocol */
1735 if(Protocol <= PROTOCOL_COREPLUS) {
1736 numtowrite = SVAL(smb_buf(inbuf),-2);
1737 data = smb_buf(inbuf);
1739 numtowrite = SVAL(inbuf,smb_vwv10);
1740 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1743 /* force the error type */
1744 CVAL(inbuf,smb_com) = SMBwritec;
1745 CVAL(outbuf,smb_com) = SMBwritec;
1747 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1748 END_PROFILE(SMBwritebraw);
1749 return(ERROR_DOS(ERRDOS,ERRlock));
1753 nwritten = write_file(fsp,data,startpos,numtowrite);
1755 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1756 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1758 if (nwritten < numtowrite) {
1759 END_PROFILE(SMBwritebraw);
1760 return(UNIXERROR(ERRHRD,ERRdiskfull));
1763 total_written = nwritten;
1765 /* Return a message to the redirector to tell it to send more bytes */
1766 CVAL(outbuf,smb_com) = SMBwritebraw;
1767 SSVALS(outbuf,smb_vwv0,-1);
1768 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1769 if (!send_smb(smbd_server_fd(),outbuf))
1770 exit_server("reply_writebraw: send_smb failed.\n");
1772 /* Now read the raw data into the buffer and write it */
1773 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1774 exit_server("secondary writebraw failed");
1777 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1778 numtowrite = smb_len(inbuf);
1780 /* Set up outbuf to return the correct return */
1781 outsize = set_message(outbuf,1,0,True);
1782 CVAL(outbuf,smb_com) = SMBwritec;
1783 SSVAL(outbuf,smb_vwv0,total_written);
1785 if (numtowrite != 0) {
1787 if (numtowrite > BUFFER_SIZE) {
1788 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1789 (unsigned int)numtowrite ));
1790 exit_server("secondary writebraw failed");
1793 if (tcount > nwritten+numtowrite) {
1794 DEBUG(3,("Client overestimated the write %d %d %d\n",
1795 (int)tcount,(int)nwritten,(int)numtowrite));
1798 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1799 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1801 exit_server("secondary writebraw failed");
1804 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1806 if (nwritten < (ssize_t)numtowrite) {
1807 CVAL(outbuf,smb_rcls) = ERRHRD;
1808 SSVAL(outbuf,smb_err,ERRdiskfull);
1812 total_written += nwritten;
1815 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1816 sync_file(conn,fsp);
1818 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1819 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1821 /* we won't return a status if write through is not selected - this follows what WfWg does */
1822 END_PROFILE(SMBwritebraw);
1823 if (!write_through && total_written==tcount) {
1825 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
1826 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
1828 if (!send_keepalive(smbd_server_fd()))
1829 exit_server("reply_writebraw: send of keepalive failed");
1836 /****************************************************************************
1837 reply to a writeunlock (core+)
1838 ****************************************************************************/
1840 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
1841 int size, int dum_buffsize)
1843 ssize_t nwritten = -1;
1848 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1850 START_PROFILE(SMBwriteunlock);
1852 CHECK_FSP(fsp,conn);
1855 numtowrite = SVAL(inbuf,smb_vwv1);
1856 startpos = IVAL(inbuf,smb_vwv2);
1857 data = smb_buf(inbuf) + 3;
1859 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
1860 WRITE_LOCK,False)) {
1861 END_PROFILE(SMBwriteunlock);
1862 return ERROR_DOS(ERRDOS,ERRlock);
1865 /* The special X/Open SMB protocol handling of
1866 zero length writes is *NOT* done for
1871 nwritten = write_file(fsp,data,startpos,numtowrite);
1873 if (lp_syncalways(SNUM(conn)))
1874 sync_file(conn,fsp);
1876 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
1877 END_PROFILE(SMBwriteunlock);
1878 return(UNIXERROR(ERRDOS,ERRnoaccess));
1881 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
1882 (SMB_BIG_UINT)startpos);
1883 if (NT_STATUS_V(status)) {
1884 END_PROFILE(SMBwriteunlock);
1885 return ERROR_NT(status);
1888 outsize = set_message(outbuf,1,0,True);
1890 SSVAL(outbuf,smb_vwv0,nwritten);
1892 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
1893 fsp->fnum, (int)numtowrite, (int)nwritten));
1895 END_PROFILE(SMBwriteunlock);
1900 /****************************************************************************
1902 ****************************************************************************/
1904 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
1907 ssize_t nwritten = -1;
1910 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1912 START_PROFILE(SMBwrite);
1914 /* If it's an IPC, pass off the pipe handler. */
1916 END_PROFILE(SMBwrite);
1917 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
1920 CHECK_FSP(fsp,conn);
1923 numtowrite = SVAL(inbuf,smb_vwv1);
1924 startpos = IVAL(inbuf,smb_vwv2);
1925 data = smb_buf(inbuf) + 3;
1927 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1928 END_PROFILE(SMBwrite);
1929 return ERROR_DOS(ERRDOS,ERRlock);
1932 /* X/Open SMB protocol says that if smb_vwv1 is
1933 zero then the file size should be extended or
1934 truncated to the size given in smb_vwv[2-3] */
1935 if(numtowrite == 0) {
1936 /* This is actually an allocate call, not set EOF. JRA */
1937 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
1939 END_PROFILE(SMBwrite);
1940 return ERROR_NT(NT_STATUS_DISK_FULL);
1943 nwritten = write_file(fsp,data,startpos,numtowrite);
1945 if (lp_syncalways(SNUM(conn)))
1946 sync_file(conn,fsp);
1948 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
1949 END_PROFILE(SMBwrite);
1950 return(UNIXERROR(ERRDOS,ERRnoaccess));
1953 outsize = set_message(outbuf,1,0,True);
1955 SSVAL(outbuf,smb_vwv0,nwritten);
1957 if (nwritten < (ssize_t)numtowrite) {
1958 CVAL(outbuf,smb_rcls) = ERRHRD;
1959 SSVAL(outbuf,smb_err,ERRdiskfull);
1962 DEBUG(3,("write fnum=%d num=%d wrote=%d\n",
1963 fsp->fnum, (int)numtowrite, (int)nwritten));
1965 END_PROFILE(SMBwrite);
1970 /****************************************************************************
1971 reply to a write and X
1972 ****************************************************************************/
1973 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1975 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1976 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
1977 size_t numtowrite = SVAL(inbuf,smb_vwv10);
1978 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
1979 ssize_t nwritten = -1;
1980 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
1981 unsigned int smblen = smb_len(inbuf);
1983 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
1984 START_PROFILE(SMBwriteX);
1986 /* If it's an IPC, pass off the pipe handler. */
1988 END_PROFILE(SMBwriteX);
1989 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
1992 CHECK_FSP(fsp,conn);
1995 /* Deal with possible LARGE_WRITEX */
1997 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
1999 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2000 END_PROFILE(SMBwriteX);
2001 return ERROR_DOS(ERRDOS,ERRbadmem);
2004 data = smb_base(inbuf) + smb_doff;
2006 if(CVAL(inbuf,smb_wct) == 14) {
2007 #ifdef LARGE_SMB_OFF_T
2009 * This is a large offset (64 bit) write.
2011 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2013 #else /* !LARGE_SMB_OFF_T */
2016 * Ensure we haven't been sent a >32 bit offset.
2019 if(IVAL(inbuf,smb_vwv12) != 0) {
2020 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2021 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2022 END_PROFILE(SMBwriteX);
2023 return ERROR_DOS(ERRDOS,ERRbadaccess);
2026 #endif /* LARGE_SMB_OFF_T */
2029 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2030 END_PROFILE(SMBwriteX);
2031 return ERROR_DOS(ERRDOS,ERRlock);
2034 /* X/Open SMB protocol says that, unlike SMBwrite
2035 if the length is zero then NO truncation is
2036 done, just a write of zero. To truncate a file,
2041 nwritten = write_file(fsp,data,startpos,numtowrite);
2043 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2044 END_PROFILE(SMBwriteX);
2045 return(UNIXERROR(ERRDOS,ERRnoaccess));
2048 set_message(outbuf,6,0,True);
2050 SSVAL(outbuf,smb_vwv2,nwritten);
2052 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2054 if (nwritten < (ssize_t)numtowrite) {
2055 CVAL(outbuf,smb_rcls) = ERRHRD;
2056 SSVAL(outbuf,smb_err,ERRdiskfull);
2059 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2060 fsp->fnum, (int)numtowrite, (int)nwritten));
2062 if (lp_syncalways(SNUM(conn)) || write_through)
2063 sync_file(conn,fsp);
2065 END_PROFILE(SMBwriteX);
2066 return chain_reply(inbuf,outbuf,length,bufsize);
2070 /****************************************************************************
2072 ****************************************************************************/
2074 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2080 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2081 START_PROFILE(SMBlseek);
2083 CHECK_FSP(fsp,conn);
2085 flush_write_cache(fsp, SEEK_FLUSH);
2087 mode = SVAL(inbuf,smb_vwv1) & 3;
2088 startpos = IVALS(inbuf,smb_vwv2);
2091 case 0: umode = SEEK_SET; break;
2092 case 1: umode = SEEK_CUR; break;
2093 case 2: umode = SEEK_END; break;
2095 umode = SEEK_SET; break;
2098 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2100 * Check for the special case where a seek before the start
2101 * of the file sets the offset to zero. Added in the CIFS spec,
2105 if(errno == EINVAL) {
2106 SMB_OFF_T current_pos = startpos;
2108 if(umode == SEEK_CUR) {
2110 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2111 END_PROFILE(SMBlseek);
2112 return(UNIXERROR(ERRDOS,ERRnoaccess));
2115 current_pos += startpos;
2117 } else if (umode == SEEK_END) {
2119 SMB_STRUCT_STAT sbuf;
2121 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2122 END_PROFILE(SMBlseek);
2123 return(UNIXERROR(ERRDOS,ERRnoaccess));
2126 current_pos += sbuf.st_size;
2130 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2134 END_PROFILE(SMBlseek);
2135 return(UNIXERROR(ERRDOS,ERRnoaccess));
2141 outsize = set_message(outbuf,2,0,True);
2142 SIVAL(outbuf,smb_vwv0,res);
2144 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2145 fsp->fnum, (double)startpos, (double)res, mode));
2147 END_PROFILE(SMBlseek);
2151 /****************************************************************************
2153 ****************************************************************************/
2155 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2157 int outsize = set_message(outbuf,0,0,True);
2158 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2159 START_PROFILE(SMBflush);
2161 CHECK_FSP(fsp,conn);
2164 file_sync_all(conn);
2166 sync_file(conn,fsp);
2169 DEBUG(3,("flush\n"));
2170 END_PROFILE(SMBflush);
2175 /****************************************************************************
2177 ****************************************************************************/
2178 int reply_exit(connection_struct *conn,
2179 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2182 START_PROFILE(SMBexit);
2183 outsize = set_message(outbuf,0,0,True);
2185 DEBUG(3,("exit\n"));
2187 END_PROFILE(SMBexit);
2192 /****************************************************************************
2193 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2194 ****************************************************************************/
2195 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2200 int32 eclass = 0, err = 0;
2201 files_struct *fsp = NULL;
2202 START_PROFILE(SMBclose);
2204 outsize = set_message(outbuf,0,0,True);
2206 /* If it's an IPC, pass off to the pipe handler. */
2208 END_PROFILE(SMBclose);
2209 return reply_pipe_close(conn, inbuf,outbuf);
2212 fsp = file_fsp(inbuf,smb_vwv0);
2215 * We can only use CHECK_FSP if we know it's not a directory.
2218 if(!fsp || (fsp->conn != conn)) {
2219 END_PROFILE(SMBclose);
2220 return ERROR_DOS(ERRDOS,ERRbadfid);
2223 if(fsp->is_directory || fsp->stat_open) {
2225 * Special case - close NT SMB directory or stat file
2228 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2229 close_file(fsp,True);
2232 * Close ordinary file.
2237 * If there was a modify time outstanding,
2238 * try and set it here.
2240 if(fsp->pending_modtime)
2241 set_filetime(conn, fsp->fsp_name, fsp->pending_modtime);
2244 * Now take care of any time sent in the close.
2246 mtime = make_unix_date3(inbuf+smb_vwv1);
2248 /* try and set the date */
2249 set_filetime(conn, fsp->fsp_name,mtime);
2251 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2253 conn->num_files_open));
2256 * close_file() returns the unix errno if an error
2257 * was detected on close - normally this is due to
2258 * a disk full error. If not then it was probably an I/O error.
2261 if((close_err = close_file(fsp,True)) != 0) {
2263 END_PROFILE(SMBclose);
2264 return (UNIXERROR(ERRHRD,ERRgeneral));
2268 /* We have a cached error */
2270 END_PROFILE(SMBclose);
2271 return ERROR_DOS(eclass,err);
2274 END_PROFILE(SMBclose);
2279 /****************************************************************************
2280 reply to a writeclose (Core+ protocol)
2281 ****************************************************************************/
2283 int reply_writeclose(connection_struct *conn,
2284 char *inbuf,char *outbuf, int size, int dum_buffsize)
2287 ssize_t nwritten = -1;
2293 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2294 START_PROFILE(SMBwriteclose);
2296 CHECK_FSP(fsp,conn);
2299 numtowrite = SVAL(inbuf,smb_vwv1);
2300 startpos = IVAL(inbuf,smb_vwv2);
2301 mtime = make_unix_date3(inbuf+smb_vwv4);
2302 data = smb_buf(inbuf) + 1;
2304 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2305 END_PROFILE(SMBwriteclose);
2306 return ERROR_DOS(ERRDOS,ERRlock);
2309 nwritten = write_file(fsp,data,startpos,numtowrite);
2311 set_filetime(conn, fsp->fsp_name,mtime);
2313 close_err = close_file(fsp,True);
2315 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2316 fsp->fnum, (int)numtowrite, (int)nwritten,
2317 conn->num_files_open));
2319 if (nwritten <= 0) {
2320 END_PROFILE(SMBwriteclose);
2321 return(UNIXERROR(ERRDOS,ERRnoaccess));
2324 if(close_err != 0) {
2326 END_PROFILE(SMBwriteclose);
2327 return(UNIXERROR(ERRHRD,ERRgeneral));
2330 outsize = set_message(outbuf,1,0,True);
2332 SSVAL(outbuf,smb_vwv0,nwritten);
2333 END_PROFILE(SMBwriteclose);
2338 /****************************************************************************
2340 ****************************************************************************/
2341 int reply_lock(connection_struct *conn,
2342 char *inbuf,char *outbuf, int length, int dum_buffsize)
2344 int outsize = set_message(outbuf,0,0,True);
2345 SMB_BIG_UINT count,offset;
2347 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2348 START_PROFILE(SMBlock);
2350 CHECK_FSP(fsp,conn);
2352 release_level_2_oplocks_on_change(fsp);
2354 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2355 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2357 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2358 fsp->fd, fsp->fnum, (double)offset, (double)count));
2360 status = do_lock(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2361 if (NT_STATUS_V(status)) {
2362 if (lp_blocking_locks(SNUM(conn))) {
2364 * A blocking lock was requested. Package up
2365 * this smb into a queued request and push it
2366 * onto the blocking lock queue.
2368 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2369 END_PROFILE(SMBlock);
2373 END_PROFILE(SMBlock);
2374 return ERROR_NT(status);
2377 END_PROFILE(SMBlock);
2382 /****************************************************************************
2384 ****************************************************************************/
2385 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2388 int outsize = set_message(outbuf,0,0,True);
2389 SMB_BIG_UINT count,offset;
2391 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2392 START_PROFILE(SMBunlock);
2394 CHECK_FSP(fsp,conn);
2396 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2397 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2399 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2400 if (NT_STATUS_V(status)) {
2401 END_PROFILE(SMBunlock);
2402 return ERROR_NT(status);
2405 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2406 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2408 END_PROFILE(SMBunlock);
2413 /****************************************************************************
2415 ****************************************************************************/
2416 int reply_tdis(connection_struct *conn,
2417 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2419 int outsize = set_message(outbuf,0,0,True);
2421 START_PROFILE(SMBtdis);
2423 vuid = SVAL(inbuf,smb_uid);
2426 DEBUG(4,("Invalid connection in tdis\n"));
2427 END_PROFILE(SMBtdis);
2428 return ERROR_DOS(ERRSRV,ERRinvnid);
2433 close_cnum(conn,vuid);
2435 END_PROFILE(SMBtdis);
2441 /****************************************************************************
2443 ****************************************************************************/
2444 int reply_echo(connection_struct *conn,
2445 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2447 int smb_reverb = SVAL(inbuf,smb_vwv0);
2449 unsigned int data_len = smb_buflen(inbuf);
2450 int outsize = set_message(outbuf,1,data_len,True);
2451 START_PROFILE(SMBecho);
2453 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2455 /* copy any incoming data back out */
2457 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2459 if (smb_reverb > 100) {
2460 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2464 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2465 SSVAL(outbuf,smb_vwv0,seq_num);
2467 smb_setlen(outbuf,outsize - 4);
2469 if (!send_smb(smbd_server_fd(),outbuf))
2470 exit_server("reply_echo: send_smb failed.\n");
2473 DEBUG(3,("echo %d times\n", smb_reverb));
2477 END_PROFILE(SMBecho);
2482 /****************************************************************************
2483 reply to a printopen
2484 ****************************************************************************/
2485 int reply_printopen(connection_struct *conn,
2486 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2490 START_PROFILE(SMBsplopen);
2492 if (!CAN_PRINT(conn)) {
2493 END_PROFILE(SMBsplopen);
2494 return ERROR_DOS(ERRDOS,ERRnoaccess);
2497 /* Open for exclusive use, write only. */
2498 fsp = print_fsp_open(conn);
2501 END_PROFILE(SMBsplopen);
2502 return(UNIXERROR(ERRDOS,ERRnoaccess));
2505 outsize = set_message(outbuf,1,0,True);
2506 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2508 DEBUG(3,("openprint fd=%d fnum=%d\n",
2509 fsp->fd, fsp->fnum));
2511 END_PROFILE(SMBsplopen);
2516 /****************************************************************************
2517 reply to a printclose
2518 ****************************************************************************/
2519 int reply_printclose(connection_struct *conn,
2520 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2522 int outsize = set_message(outbuf,0,0,True);
2523 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2525 START_PROFILE(SMBsplclose);
2527 CHECK_FSP(fsp,conn);
2529 if (!CAN_PRINT(conn)) {
2530 END_PROFILE(SMBsplclose);
2531 return ERROR_DOS(ERRDOS,ERRnoaccess);
2534 DEBUG(3,("printclose fd=%d fnum=%d\n",
2535 fsp->fd,fsp->fnum));
2537 close_err = close_file(fsp,True);
2539 if(close_err != 0) {
2541 END_PROFILE(SMBsplclose);
2542 return(UNIXERROR(ERRHRD,ERRgeneral));
2545 END_PROFILE(SMBsplclose);
2550 /****************************************************************************
2551 reply to a printqueue
2552 ****************************************************************************/
2553 int reply_printqueue(connection_struct *conn,
2554 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2556 int outsize = set_message(outbuf,2,3,True);
2557 int max_count = SVAL(inbuf,smb_vwv0);
2558 int start_index = SVAL(inbuf,smb_vwv1);
2559 START_PROFILE(SMBsplretq);
2561 /* we used to allow the client to get the cnum wrong, but that
2562 is really quite gross and only worked when there was only
2563 one printer - I think we should now only accept it if they
2564 get it right (tridge) */
2565 if (!CAN_PRINT(conn)) {
2566 END_PROFILE(SMBsplretq);
2567 return ERROR_DOS(ERRDOS,ERRnoaccess);
2570 SSVAL(outbuf,smb_vwv0,0);
2571 SSVAL(outbuf,smb_vwv1,0);
2572 CVAL(smb_buf(outbuf),0) = 1;
2573 SSVAL(smb_buf(outbuf),1,0);
2575 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2576 start_index, max_count));
2579 print_queue_struct *queue = NULL;
2580 char *p = smb_buf(outbuf) + 3;
2581 int count = print_queue_status(SNUM(conn), &queue,NULL);
2582 int num_to_get = ABS(max_count);
2583 int first = (max_count>0?start_index:start_index+max_count+1);
2589 num_to_get = MIN(num_to_get,count-first);
2592 for (i=first;i<first+num_to_get;i++) {
2593 put_dos_date2(p,0,queue[i].time);
2594 CVAL(p,4) = (queue[i].status==LPQ_PRINTING?2:3);
2595 SSVAL(p,5, queue[i].job);
2596 SIVAL(p,7,queue[i].size);
2598 srvstr_push(outbuf, p+12, queue[i].user, 16, STR_ASCII);
2603 outsize = set_message(outbuf,2,28*count+3,False);
2604 SSVAL(outbuf,smb_vwv0,count);
2605 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2606 CVAL(smb_buf(outbuf),0) = 1;
2607 SSVAL(smb_buf(outbuf),1,28*count);
2612 DEBUG(3,("%d entries returned in queue\n",count));
2615 END_PROFILE(SMBsplretq);
2620 /****************************************************************************
2621 reply to a printwrite
2622 ****************************************************************************/
2623 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2626 int outsize = set_message(outbuf,0,0,True);
2628 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2629 START_PROFILE(SMBsplwr);
2631 if (!CAN_PRINT(conn)) {
2632 END_PROFILE(SMBsplwr);
2633 return ERROR_DOS(ERRDOS,ERRnoaccess);
2636 CHECK_FSP(fsp,conn);
2639 numtowrite = SVAL(smb_buf(inbuf),1);
2640 data = smb_buf(inbuf) + 3;
2642 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2643 END_PROFILE(SMBsplwr);
2644 return(UNIXERROR(ERRDOS,ERRnoaccess));
2647 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2649 END_PROFILE(SMBsplwr);
2654 /****************************************************************************
2655 The guts of the mkdir command, split out so it may be called by the NT SMB
2657 ****************************************************************************/
2658 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2660 BOOL bad_path = False;
2661 SMB_STRUCT_STAT sbuf;
2664 unix_convert(directory,conn,0,&bad_path,&sbuf);
2666 if (check_name(directory, conn))
2667 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2670 return map_nt_error_from_unix(errno);
2673 return NT_STATUS_OK;
2676 /****************************************************************************
2678 ****************************************************************************/
2680 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2685 START_PROFILE(SMBmkdir);
2687 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
2689 status = mkdir_internal(conn, directory);
2690 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
2692 outsize = set_message(outbuf,0,0,True);
2694 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2696 END_PROFILE(SMBmkdir);
2700 /****************************************************************************
2701 Static function used by reply_rmdir to delete an entire directory
2702 tree recursively. Return False on ok, True on fail.
2703 ****************************************************************************/
2705 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2709 void *dirptr = OpenDir(conn, directory, False);
2714 while((dname = ReadDirName(dirptr))) {
2718 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2721 /* Construct the full name. */
2722 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2728 pstrcpy(fullname, directory);
2729 pstrcat(fullname, "/");
2730 pstrcat(fullname, dname);
2732 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
2737 if(st.st_mode & S_IFDIR) {
2738 if(recursive_rmdir(conn, fullname)!=0) {
2742 if(vfs_rmdir(conn,fullname) != 0) {
2746 } else if(vfs_unlink(conn,fullname) != 0) {
2755 /****************************************************************************
2756 The internals of the rmdir code - called elsewhere.
2757 ****************************************************************************/
2759 BOOL rmdir_internals(connection_struct *conn, char *directory)
2763 ok = (vfs_rmdir(conn,directory) == 0);
2764 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2766 * Check to see if the only thing in this directory are
2767 * vetoed files/directories. If so then delete them and
2768 * retry. If we fail to delete any of them (and we *don't*
2769 * do a recursive delete) then fail the rmdir.
2771 BOOL all_veto_files = True;
2773 void *dirptr = OpenDir(conn, directory, False);
2775 if(dirptr != NULL) {
2776 int dirpos = TellDir(dirptr);
2777 while ((dname = ReadDirName(dirptr))) {
2778 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2780 if(!IS_VETO_PATH(conn, dname)) {
2781 all_veto_files = False;
2786 if(all_veto_files) {
2787 SeekDir(dirptr,dirpos);
2788 while ((dname = ReadDirName(dirptr))) {
2792 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2795 /* Construct the full name. */
2796 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2801 pstrcpy(fullname, directory);
2802 pstrcat(fullname, "/");
2803 pstrcat(fullname, dname);
2805 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
2807 if(st.st_mode & S_IFDIR) {
2808 if(lp_recursive_veto_delete(SNUM(conn))) {
2809 if(recursive_rmdir(conn, fullname) != 0)
2812 if(vfs_rmdir(conn,fullname) != 0)
2814 } else if(vfs_unlink(conn,fullname) != 0)
2818 /* Retry the rmdir */
2819 ok = (vfs_rmdir(conn,directory) == 0);
2829 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
2834 /****************************************************************************
2836 ****************************************************************************/
2838 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2843 BOOL bad_path = False;
2844 SMB_STRUCT_STAT sbuf;
2845 START_PROFILE(SMBrmdir);
2847 srvstr_pull(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), -1, STR_TERMINATE);
2849 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
2851 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
2853 if (check_name(directory,conn))
2855 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2856 ok = rmdir_internals(conn, directory);
2861 if((errno == ENOENT) && bad_path)
2863 unix_ERR_class = ERRDOS;
2864 unix_ERR_code = ERRbadpath;
2866 END_PROFILE(SMBrmdir);
2867 return(UNIXERROR(ERRDOS,ERRbadpath));
2870 outsize = set_message(outbuf,0,0,True);
2872 DEBUG( 3, ( "rmdir %s\n", directory ) );
2874 END_PROFILE(SMBrmdir);
2879 /*******************************************************************
2880 resolve wildcards in a filename rename
2881 ********************************************************************/
2882 static BOOL resolve_wildcards(char *name1,char *name2)
2884 fstring root1,root2;
2888 name1 = strrchr_m(name1,'/');
2889 name2 = strrchr_m(name2,'/');
2891 if (!name1 || !name2) return(False);
2893 fstrcpy(root1,name1);
2894 fstrcpy(root2,name2);
2895 p = strrchr_m(root1,'.');
2902 p = strrchr_m(root2,'.');
2934 pstrcpy(name2,root2);
2937 pstrcat(name2,ext2);
2943 /*******************************************************************
2944 check if a user is allowed to rename a file
2945 ********************************************************************/
2946 static BOOL can_rename(char *fname,connection_struct *conn)
2948 SMB_STRUCT_STAT sbuf;
2950 if (!CAN_WRITE(conn)) return(False);
2952 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0) return(False);
2953 if (!check_file_sharing(conn,fname,True)) return(False);
2957 /****************************************************************************
2958 The guts of the rename command, split out so it may be called by the NT SMB
2960 ****************************************************************************/
2961 NTSTATUS rename_internals(connection_struct *conn,
2963 char *newname, BOOL replace_if_exists)
2967 pstring newname_last_component;
2970 BOOL bad_path1 = False;
2971 BOOL bad_path2 = False;
2973 NTSTATUS error = NT_STATUS_OK;
2976 SMB_STRUCT_STAT sbuf1, sbuf2;
2978 *directory = *mask = 0;
2980 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
2981 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
2984 * Split the old name into directory and last component
2985 * strings. Note that unix_convert may have stripped off a
2986 * leading ./ from both name and newname if the rename is
2987 * at the root of the share. We need to make sure either both
2988 * name and newname contain a / character or neither of them do
2989 * as this is checked in resolve_wildcards().
2992 p = strrchr_m(name,'/');
2994 pstrcpy(directory,".");
2998 pstrcpy(directory,name);
3000 *p = '/'; /* Replace needed for exceptional test below. */
3004 * We should only check the mangled cache
3005 * here if unix_convert failed. This means
3006 * that the path in 'mask' doesn't exist
3007 * on the file system and so we need to look
3008 * for a possible mangle. This patch from
3009 * Tine Smukavec <valentin.smukavec@hermes.si>.
3013 if (!rc && is_mangled(mask))
3014 check_mangled_cache( mask );
3020 unmangled = dos_unmangle(mask);
3022 strncpy(mask, unmangled, strlen(unmangled) + 1);
3024 SAFE_FREE(unmangled);
3027 has_wild = ms_has_wild(mask);
3031 * No wildcards - just process the one file.
3033 BOOL is_short_name = is_8_3(name, True);
3035 /* Add a terminating '/' to the directory name. */
3036 pstrcat(directory,"/");
3037 pstrcat(directory,mask);
3039 /* Ensure newname contains a '/' also */
3040 if(strrchr_m(newname,'/') == 0) {
3043 pstrcpy(tmpstr, "./");
3044 pstrcat(tmpstr, newname);
3045 pstrcpy(newname, tmpstr);
3048 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3049 case_sensitive, case_preserve, short_case_preserve, directory,
3050 newname, newname_last_component, is_short_name));
3053 * Check for special case with case preserving and not
3054 * case sensitive, if directory and newname are identical,
3055 * and the old last component differs from the original
3056 * last component only by case, then we should allow
3057 * the rename (user is trying to change the case of the
3060 if((case_sensitive == False) &&
3061 (((case_preserve == True) &&
3062 (is_short_name == False)) ||
3063 ((short_case_preserve == True) &&
3064 (is_short_name == True))) &&
3065 strcsequal(directory, newname)) {
3066 pstring newname_modified_last_component;
3069 * Get the last component of the modified name.
3070 * Note that we guarantee that newname contains a '/'
3073 p = strrchr_m(newname,'/');
3074 pstrcpy(newname_modified_last_component,p+1);
3076 if(strcsequal(newname_modified_last_component,
3077 newname_last_component) == False) {
3079 * Replace the modified last component with
3082 pstrcpy(p+1, newname_last_component);
3086 if(replace_if_exists) {
3088 * NT SMB specific flag - rename can overwrite
3089 * file with the same name so don't check for
3093 if(resolve_wildcards(directory,newname) &&
3094 can_rename(directory,conn) &&
3095 conn->vfs_ops.rename(conn,directory,newname) == 0)
3098 if (resolve_wildcards(directory,newname) &&
3099 can_rename(directory,conn) &&
3100 !vfs_file_exist(conn,newname,NULL) &&
3101 conn->vfs_ops.rename(conn,directory,newname) == 0)
3105 DEBUG(3,("rename_internals: %s doing rename on %s -> %s\n",(count != 0) ? "succeeded" : "failed",
3106 directory,newname));
3108 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3109 if (!count && exists && vfs_file_exist(conn,newname,NULL)) {
3111 error = NT_STATUS_OBJECT_NAME_COLLISION;
3115 * Wildcards - process each file that matches.
3117 void *dirptr = NULL;
3121 if (check_name(directory,conn))
3122 dirptr = OpenDir(conn, directory, True);
3125 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3127 if (strequal(mask,"????????.???"))
3130 while ((dname = ReadDirName(dirptr))) {
3133 pstrcpy(fname,dname);
3135 if(!mask_match(fname, mask, case_sensitive))
3138 error = NT_STATUS_ACCESS_DENIED;
3139 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3140 if (!can_rename(fname,conn)) {
3141 DEBUG(6,("rename %s refused\n", fname));
3144 pstrcpy(destname,newname);
3146 if (!resolve_wildcards(fname,destname)) {
3147 DEBUG(6,("resolve_wildcards %s %s failed\n",
3152 if (!replace_if_exists &&
3153 vfs_file_exist(conn,destname, NULL)) {
3154 DEBUG(6,("file_exist %s\n", destname));
3155 error = NT_STATUS_OBJECT_NAME_COLLISION;
3159 if (!conn->vfs_ops.rename(conn,fname,destname))
3161 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3167 if (count == 0 && NT_STATUS_IS_OK(error)) {
3168 error = map_nt_error_from_unix(errno);
3174 /****************************************************************************
3176 ****************************************************************************/
3178 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3187 START_PROFILE(SMBmv);
3189 p = smb_buf(inbuf) + 1;
3190 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3192 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3194 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3195 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3197 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3199 status = rename_internals(conn, name, newname, False);
3200 if (!NT_STATUS_IS_OK(status)) {
3201 return ERROR_NT(status);
3205 * Win2k needs a changenotify request response before it will
3206 * update after a rename..
3208 process_pending_change_notify_queue((time_t)0);
3209 outsize = set_message(outbuf,0,0,True);
3215 /*******************************************************************
3216 Copy a file as part of a reply_copy.
3217 ******************************************************************/
3219 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3220 int count,BOOL target_is_directory, int *err_ret)
3223 SMB_STRUCT_STAT src_sbuf, sbuf2;
3225 files_struct *fsp1,*fsp2;
3230 pstrcpy(dest,dest1);
3231 if (target_is_directory) {
3232 char *p = strrchr_m(src,'/');
3241 if (!vfs_file_exist(conn,src,&src_sbuf))
3244 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3245 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3250 if (!target_is_directory && count)
3251 ofun = FILE_EXISTS_OPEN;
3253 if (vfs_stat(conn,dest,&sbuf2) == -1)
3254 ZERO_STRUCTP(&sbuf2);
3256 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3257 ofun,src_sbuf.st_mode,0,&Access,&action);
3260 close_file(fsp1,False);
3264 if ((ofun&3) == 1) {
3265 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3266 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3268 * Stop the copy from occurring.
3271 src_sbuf.st_size = 0;
3275 if (src_sbuf.st_size)
3276 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3278 close_file(fsp1,False);
3280 * As we are opening fsp1 read-only we only expect
3281 * an error on close on fsp2 if we are out of space.
3282 * Thus we don't look at the error return from the
3285 *err_ret = close_file(fsp2,False);
3287 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3290 /****************************************************************************
3291 reply to a file copy.
3292 ****************************************************************************/
3293 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3298 pstring mask,newname;
3301 int error = ERRnoaccess;
3305 int tid2 = SVAL(inbuf,smb_vwv0);
3306 int ofun = SVAL(inbuf,smb_vwv1);
3307 int flags = SVAL(inbuf,smb_vwv2);
3308 BOOL target_is_directory=False;
3309 BOOL bad_path1 = False;
3310 BOOL bad_path2 = False;
3312 SMB_STRUCT_STAT sbuf1, sbuf2;
3313 START_PROFILE(SMBcopy);
3315 *directory = *mask = 0;
3318 p += srvstr_pull(inbuf, name, p, sizeof(name), -1, STR_TERMINATE);
3319 p += srvstr_pull(inbuf, newname, p, sizeof(newname), -1, STR_TERMINATE);
3321 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3323 if (tid2 != conn->cnum) {
3324 /* can't currently handle inter share copies XXXX */
3325 DEBUG(3,("Rejecting inter-share copy\n"));
3326 END_PROFILE(SMBcopy);
3327 return ERROR_DOS(ERRSRV,ERRinvdevice);
3330 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3331 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3333 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3334 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3336 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3338 if ((flags&1) && target_is_directory) {
3339 END_PROFILE(SMBcopy);
3340 return ERROR_DOS(ERRDOS,ERRbadfile);
3343 if ((flags&2) && !target_is_directory) {
3344 END_PROFILE(SMBcopy);
3345 return ERROR_DOS(ERRDOS,ERRbadpath);
3348 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3349 /* wants a tree copy! XXXX */
3350 DEBUG(3,("Rejecting tree copy\n"));
3351 END_PROFILE(SMBcopy);
3352 return ERROR_DOS(ERRSRV,ERRerror);
3355 p = strrchr_m(name,'/');
3357 pstrcpy(directory,"./");
3361 pstrcpy(directory,name);
3366 * We should only check the mangled cache
3367 * here if unix_convert failed. This means
3368 * that the path in 'mask' doesn't exist
3369 * on the file system and so we need to look
3370 * for a possible mangle. This patch from
3371 * Tine Smukavec <valentin.smukavec@hermes.si>.
3375 if (!rc && is_mangled(mask))
3376 check_mangled_cache( mask );
3382 unmangled = dos_unmangle(mask);
3384 strncpy(mask, unmangled, strlen(unmangled) + 1);
3386 SAFE_FREE(unmangled);
3390 has_wild = ms_has_wild(mask);
3393 pstrcat(directory,"/");
3394 pstrcat(directory,mask);
3395 if (resolve_wildcards(directory,newname) &&
3396 copy_file(directory,newname,conn,ofun,
3397 count,target_is_directory,&err)) count++;
3400 END_PROFILE(SMBcopy);
3401 return(UNIXERROR(ERRHRD,ERRgeneral));
3403 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3405 void *dirptr = NULL;
3409 if (check_name(directory,conn))
3410 dirptr = OpenDir(conn, directory, True);
3415 if (strequal(mask,"????????.???"))
3418 while ((dname = ReadDirName(dirptr))) {
3420 pstrcpy(fname,dname);
3422 if(!mask_match(fname, mask, case_sensitive))
3425 error = ERRnoaccess;
3426 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3427 pstrcpy(destname,newname);
3428 if (resolve_wildcards(fname,destname) &&
3429 copy_file(fname,destname,conn,ofun,
3430 count,target_is_directory,&err)) count++;
3431 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3439 /* Error on close... */
3441 END_PROFILE(SMBcopy);
3442 return(UNIXERROR(ERRHRD,ERRgeneral));
3446 END_PROFILE(SMBcopy);
3447 return ERROR_DOS(ERRDOS,error);
3450 if((errno == ENOENT) && (bad_path1 || bad_path2))
3452 unix_ERR_class = ERRDOS;
3453 unix_ERR_code = ERRbadpath;
3455 END_PROFILE(SMBcopy);
3456 return(UNIXERROR(ERRDOS,error));
3460 outsize = set_message(outbuf,1,0,True);
3461 SSVAL(outbuf,smb_vwv0,count);
3463 END_PROFILE(SMBcopy);
3467 /****************************************************************************
3469 ****************************************************************************/
3470 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3476 START_PROFILE(pathworks_setdir);
3479 if (!CAN_SETDIR(snum)) {
3480 END_PROFILE(pathworks_setdir);
3481 return ERROR_DOS(ERRDOS,ERRnoaccess);
3484 srvstr_pull(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), -1, STR_TERMINATE);
3486 if (strlen(newdir) == 0) {
3489 ok = vfs_directory_exist(conn,newdir,NULL);
3491 string_set(&conn->connectpath,newdir);
3496 END_PROFILE(pathworks_setdir);
3497 return ERROR_DOS(ERRDOS,ERRbadpath);
3500 outsize = set_message(outbuf,0,0,True);
3501 CVAL(outbuf,smb_reh) = CVAL(inbuf,smb_reh);
3503 DEBUG(3,("setdir %s\n", newdir));
3505 END_PROFILE(pathworks_setdir);
3509 /****************************************************************************
3510 Get a lock pid, dealing with large count requests.
3511 ****************************************************************************/
3513 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3515 if(!large_file_format)
3516 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3518 return SVAL(data,SMB_LARGE__LPID_OFFSET(data_offset));
3521 /****************************************************************************
3522 Get a lock count, dealing with large count requests.
3523 ****************************************************************************/
3525 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3527 SMB_BIG_UINT count = 0;
3529 if(!large_file_format) {
3530 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3533 #if defined(HAVE_LONGLONG)
3534 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3535 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3536 #else /* HAVE_LONGLONG */
3539 * NT4.x seems to be broken in that it sends large file (64 bit)
3540 * lockingX calls even if the CAP_LARGE_FILES was *not*
3541 * negotiated. For boxes without large unsigned ints truncate the
3542 * lock count by dropping the top 32 bits.
3545 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3546 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3547 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3548 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3549 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3552 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3553 #endif /* HAVE_LONGLONG */
3559 #if !defined(HAVE_LONGLONG)
3560 /****************************************************************************
3561 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3562 ****************************************************************************/
3563 static uint32 map_lock_offset(uint32 high, uint32 low)
3567 uint32 highcopy = high;
3570 * Try and find out how many significant bits there are in high.
3573 for(i = 0; highcopy; i++)
3577 * We use 31 bits not 32 here as POSIX
3578 * lock offsets may not be negative.
3581 mask = (~0) << (31 - i);
3584 return 0; /* Fail. */
3590 #endif /* !defined(HAVE_LONGLONG) */
3592 /****************************************************************************
3593 Get a lock offset, dealing with large offset requests.
3594 ****************************************************************************/
3596 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3598 SMB_BIG_UINT offset = 0;
3602 if(!large_file_format) {
3603 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3606 #if defined(HAVE_LONGLONG)
3607 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3608 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3609 #else /* HAVE_LONGLONG */
3612 * NT4.x seems to be broken in that it sends large file (64 bit)
3613 * lockingX calls even if the CAP_LARGE_FILES was *not*
3614 * negotiated. For boxes without large unsigned ints mangle the
3615 * lock offset by mapping the top 32 bits onto the lower 32.
3618 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3619 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3620 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3623 if((new_low = map_lock_offset(high, low)) == 0) {
3625 return (SMB_BIG_UINT)-1;
3628 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3629 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3630 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3631 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3634 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3635 #endif /* HAVE_LONGLONG */
3641 /****************************************************************************
3642 reply to a lockingX request
3643 ****************************************************************************/
3645 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3647 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3648 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3649 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3650 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3651 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3652 SMB_BIG_UINT count = 0, offset = 0;
3654 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3657 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3661 START_PROFILE(SMBlockingX);
3663 CHECK_FSP(fsp,conn);
3665 data = smb_buf(inbuf);
3667 /* Check if this is an oplock break on a file
3668 we have granted an oplock on.
3670 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3671 /* Client can insist on breaking to none. */
3672 BOOL break_to_none = (oplocklevel == 0);
3674 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3675 (unsigned int)oplocklevel, fsp->fnum ));
3678 * Make sure we have granted an exclusive or batch oplock on this file.
3681 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3682 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3683 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3685 /* if this is a pure oplock break request then don't send a reply */
3686 if (num_locks == 0 && num_ulocks == 0) {
3687 END_PROFILE(SMBlockingX);
3690 END_PROFILE(SMBlockingX);
3691 return ERROR_DOS(ERRDOS,ERRlock);
3695 if (remove_oplock(fsp, break_to_none) == False) {
3696 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3700 /* if this is a pure oplock break request then don't send a reply */
3701 if (num_locks == 0 && num_ulocks == 0) {
3702 /* Sanity check - ensure a pure oplock break is not a
3704 if(CVAL(inbuf,smb_vwv0) != 0xff)
3705 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3706 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3707 END_PROFILE(SMBlockingX);
3713 * We do this check *after* we have checked this is not a oplock break
3714 * response message. JRA.
3717 release_level_2_oplocks_on_change(fsp);
3719 /* Data now points at the beginning of the list
3720 of smb_unlkrng structs */
3721 for(i = 0; i < (int)num_ulocks; i++) {
3722 lock_pid = get_lock_pid( data, i, large_file_format);
3723 count = get_lock_count( data, i, large_file_format);
3724 offset = get_lock_offset( data, i, large_file_format, &err);
3727 * There is no error code marked "stupid client bug".... :-).
3730 END_PROFILE(SMBlockingX);
3731 return ERROR_DOS(ERRDOS,ERRnoaccess);
3734 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3735 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3737 status = do_unlock(fsp,conn,lock_pid,count,offset);
3738 if (NT_STATUS_V(status)) {
3739 END_PROFILE(SMBlockingX);
3740 return ERROR_NT(status);
3744 /* Setup the timeout in seconds. */
3745 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3747 /* Now do any requested locks */
3748 data += ((large_file_format ? 20 : 10)*num_ulocks);
3750 /* Data now points at the beginning of the list
3751 of smb_lkrng structs */
3753 for(i = 0; i < (int)num_locks; i++) {
3754 lock_pid = get_lock_pid( data, i, large_file_format);
3755 count = get_lock_count( data, i, large_file_format);
3756 offset = get_lock_offset( data, i, large_file_format, &err);
3759 * There is no error code marked "stupid client bug".... :-).
3762 END_PROFILE(SMBlockingX);
3763 return ERROR_DOS(ERRDOS,ERRnoaccess);
3766 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s\n",
3767 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3769 status = do_lock(fsp,conn,lock_pid, count,offset,
3770 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3771 if (NT_STATUS_V(status)) {
3772 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3774 * A blocking lock was requested. Package up
3775 * this smb into a queued request and push it
3776 * onto the blocking lock queue.
3778 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
3779 END_PROFILE(SMBlockingX);
3787 /* If any of the above locks failed, then we must unlock
3788 all of the previous locks (X/Open spec). */
3789 if (i != num_locks && num_locks != 0) {
3791 * Ensure we don't do a remove on the lock that just failed,
3792 * as under POSIX rules, if we have a lock already there, we
3793 * will delete it (and we shouldn't) .....
3795 for(i--; i >= 0; i--) {
3796 lock_pid = get_lock_pid( data, i, large_file_format);
3797 count = get_lock_count( data, i, large_file_format);
3798 offset = get_lock_offset( data, i, large_file_format, &err);
3801 * There is no error code marked "stupid client bug".... :-).
3804 END_PROFILE(SMBlockingX);
3805 return ERROR_DOS(ERRDOS,ERRnoaccess);
3808 do_unlock(fsp,conn,lock_pid,count,offset);
3810 END_PROFILE(SMBlockingX);
3811 return ERROR_NT(status);
3814 set_message(outbuf,2,0,True);
3816 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3817 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3819 END_PROFILE(SMBlockingX);
3820 return chain_reply(inbuf,outbuf,length,bufsize);
3823 /****************************************************************************
3824 Reply to a SMBreadbmpx (read block multiplex) request.
3825 ****************************************************************************/
3827 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3838 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3839 START_PROFILE(SMBreadBmpx);
3841 /* this function doesn't seem to work - disable by default */
3842 if (!lp_readbmpx()) {
3843 END_PROFILE(SMBreadBmpx);
3844 return ERROR_DOS(ERRSRV,ERRuseSTD);
3847 outsize = set_message(outbuf,8,0,True);
3849 CHECK_FSP(fsp,conn);
3852 startpos = IVAL(inbuf,smb_vwv1);
3853 maxcount = SVAL(inbuf,smb_vwv3);
3855 data = smb_buf(outbuf);
3856 pad = ((long)data)%4;
3861 max_per_packet = bufsize-(outsize+pad);
3865 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
3866 END_PROFILE(SMBreadBmpx);
3867 return ERROR_DOS(ERRDOS,ERRlock);
3871 size_t N = MIN(max_per_packet,tcount-total_read);
3873 nread = read_file(fsp,data,startpos,N);
3878 if (nread < (ssize_t)N)
3879 tcount = total_read + nread;
3881 set_message(outbuf,8,nread,False);
3882 SIVAL(outbuf,smb_vwv0,startpos);
3883 SSVAL(outbuf,smb_vwv2,tcount);
3884 SSVAL(outbuf,smb_vwv6,nread);
3885 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3887 if (!send_smb(smbd_server_fd(),outbuf))
3888 exit_server("reply_readbmpx: send_smb failed.\n");
3890 total_read += nread;
3892 } while (total_read < (ssize_t)tcount);
3894 END_PROFILE(SMBreadBmpx);
3898 /****************************************************************************
3899 Reply to a SMBsetattrE.
3900 ****************************************************************************/
3902 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3904 struct utimbuf unix_times;
3906 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3907 START_PROFILE(SMBsetattrE);
3909 outsize = set_message(outbuf,0,0,True);
3911 CHECK_FSP(fsp,conn);
3913 /* Convert the DOS times into unix times. Ignore create
3914 time as UNIX can't set this.
3916 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3917 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
3920 * Patch from Ray Frush <frush@engr.colostate.edu>
3921 * Sometimes times are sent as zero - ignore them.
3924 if ((unix_times.actime == 0) && (unix_times.modtime == 0))
3926 /* Ignore request */
3929 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
3930 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
3932 END_PROFILE(SMBsetattrE);
3935 else if ((unix_times.actime != 0) && (unix_times.modtime == 0))
3937 /* set modify time = to access time if modify time was 0 */
3938 unix_times.modtime = unix_times.actime;
3941 /* Set the date on this file */
3942 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
3943 END_PROFILE(SMBsetattrE);
3944 return ERROR_DOS(ERRDOS,ERRnoaccess);
3947 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
3948 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
3950 END_PROFILE(SMBsetattrE);
3955 /* Back from the dead for OS/2..... JRA. */
3957 /****************************************************************************
3958 Reply to a SMBwritebmpx (write block multiplex primary) request.
3959 ****************************************************************************/
3961 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3964 ssize_t nwritten = -1;
3971 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3972 START_PROFILE(SMBwriteBmpx);
3974 CHECK_FSP(fsp,conn);
3978 tcount = SVAL(inbuf,smb_vwv1);
3979 startpos = IVAL(inbuf,smb_vwv3);
3980 write_through = BITSETW(inbuf+smb_vwv7,0);
3981 numtowrite = SVAL(inbuf,smb_vwv10);
3982 smb_doff = SVAL(inbuf,smb_vwv11);
3984 data = smb_base(inbuf) + smb_doff;
3986 /* If this fails we need to send an SMBwriteC response,
3987 not an SMBwritebmpx - set this up now so we don't forget */
3988 CVAL(outbuf,smb_com) = SMBwritec;
3990 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
3991 END_PROFILE(SMBwriteBmpx);
3992 return(ERROR_DOS(ERRDOS,ERRlock));
3995 nwritten = write_file(fsp,data,startpos,numtowrite);
3997 if(lp_syncalways(SNUM(conn)) || write_through)
3998 sync_file(conn,fsp);
4000 if(nwritten < (ssize_t)numtowrite) {
4001 END_PROFILE(SMBwriteBmpx);
4002 return(UNIXERROR(ERRHRD,ERRdiskfull));
4005 /* If the maximum to be written to this file
4006 is greater than what we just wrote then set
4007 up a secondary struct to be attached to this
4008 fd, we will use this to cache error messages etc. */
4010 if((ssize_t)tcount > nwritten) {
4011 write_bmpx_struct *wbms;
4012 if(fsp->wbmpx_ptr != NULL)
4013 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4015 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4017 DEBUG(0,("Out of memory in reply_readmpx\n"));
4018 END_PROFILE(SMBwriteBmpx);
4019 return(ERROR_DOS(ERRSRV,ERRnoresource));
4021 wbms->wr_mode = write_through;
4022 wbms->wr_discard = False; /* No errors yet */
4023 wbms->wr_total_written = nwritten;
4024 wbms->wr_errclass = 0;
4026 fsp->wbmpx_ptr = wbms;
4029 /* We are returning successfully, set the message type back to
4031 CVAL(outbuf,smb_com) = SMBwriteBmpx;
4033 outsize = set_message(outbuf,1,0,True);
4035 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4037 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4038 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4040 if (write_through && tcount==nwritten) {
4041 /* We need to send both a primary and a secondary response */
4042 smb_setlen(outbuf,outsize - 4);
4043 if (!send_smb(smbd_server_fd(),outbuf))
4044 exit_server("reply_writebmpx: send_smb failed.\n");
4046 /* Now the secondary */
4047 outsize = set_message(outbuf,1,0,True);
4048 CVAL(outbuf,smb_com) = SMBwritec;
4049 SSVAL(outbuf,smb_vwv0,nwritten);
4052 END_PROFILE(SMBwriteBmpx);
4056 /****************************************************************************
4057 Reply to a SMBwritebs (write block multiplex secondary) request.
4058 ****************************************************************************/
4060 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4063 ssize_t nwritten = -1;
4070 write_bmpx_struct *wbms;
4071 BOOL send_response = False;
4072 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4073 START_PROFILE(SMBwriteBs);
4075 CHECK_FSP(fsp,conn);
4078 tcount = SVAL(inbuf,smb_vwv1);
4079 startpos = IVAL(inbuf,smb_vwv2);
4080 numtowrite = SVAL(inbuf,smb_vwv6);
4081 smb_doff = SVAL(inbuf,smb_vwv7);
4083 data = smb_base(inbuf) + smb_doff;
4085 /* We need to send an SMBwriteC response, not an SMBwritebs */
4086 CVAL(outbuf,smb_com) = SMBwritec;
4088 /* This fd should have an auxiliary struct attached,
4089 check that it does */
4090 wbms = fsp->wbmpx_ptr;
4092 END_PROFILE(SMBwriteBs);
4096 /* If write through is set we can return errors, else we must cache them */
4097 write_through = wbms->wr_mode;
4099 /* Check for an earlier error */
4100 if(wbms->wr_discard) {
4101 END_PROFILE(SMBwriteBs);
4102 return -1; /* Just discard the packet */
4105 nwritten = write_file(fsp,data,startpos,numtowrite);
4107 if(lp_syncalways(SNUM(conn)) || write_through)
4108 sync_file(conn,fsp);
4110 if (nwritten < (ssize_t)numtowrite) {
4112 /* We are returning an error - we can delete the aux struct */
4115 fsp->wbmpx_ptr = NULL;
4116 END_PROFILE(SMBwriteBs);
4117 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4119 END_PROFILE(SMBwriteBs);
4120 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4123 /* Increment the total written, if this matches tcount
4124 we can discard the auxiliary struct (hurrah !) and return a writeC */
4125 wbms->wr_total_written += nwritten;
4126 if(wbms->wr_total_written >= tcount) {
4127 if (write_through) {
4128 outsize = set_message(outbuf,1,0,True);
4129 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4130 send_response = True;
4134 fsp->wbmpx_ptr = NULL;
4138 END_PROFILE(SMBwriteBs);
4142 END_PROFILE(SMBwriteBs);
4146 /****************************************************************************
4147 Reply to a SMBgetattrE.
4148 ****************************************************************************/
4150 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4152 SMB_STRUCT_STAT sbuf;
4155 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4156 START_PROFILE(SMBgetattrE);
4158 outsize = set_message(outbuf,11,0,True);
4160 CHECK_FSP(fsp,conn);
4162 /* Do an fstat on this file */
4163 if(vfs_fstat(fsp,fsp->fd, &sbuf)) {
4164 END_PROFILE(SMBgetattrE);
4165 return(UNIXERROR(ERRDOS,ERRnoaccess));
4168 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4170 /* Convert the times into dos times. Set create
4171 date to be last modify date as UNIX doesn't save
4173 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4174 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4175 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4178 SIVAL(outbuf,smb_vwv6,0);
4179 SIVAL(outbuf,smb_vwv8,0);
4183 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4184 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4186 SSVAL(outbuf,smb_vwv10, mode);
4188 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4190 END_PROFILE(SMBgetattrE);