2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
29 /* look in server.c for some explanation of these variables */
33 extern char magic_char;
34 extern BOOL case_sensitive;
35 extern BOOL case_preserve;
36 extern BOOL short_case_preserve;
37 extern pstring global_myname;
38 extern int global_oplock_break;
39 unsigned int smb_echo_count = 0;
41 extern fstring remote_machine;
42 extern BOOL global_encrypted_passwords_negotiated;
45 /****************************************************************************
46 reply to an special message
47 ****************************************************************************/
49 int reply_special(char *inbuf,char *outbuf)
52 int msg_type = CVAL(inbuf,0);
53 int msg_flags = CVAL(inbuf,1);
56 extern fstring local_machine;
62 memset(outbuf,'\0',smb_size);
67 case 0x81: /* session request */
70 if (name_len(inbuf+4) > 50 ||
71 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
72 DEBUG(0,("Invalid name length in session request\n"));
75 name_extract(inbuf,4,name1);
76 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
77 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
80 fstrcpy(remote_machine,name2);
81 remote_machine[15] = 0;
82 trim_string(remote_machine," "," ");
83 strlower(remote_machine);
84 alpha_strcpy(remote_machine,remote_machine,SAFE_NETBIOS_CHARS,sizeof(remote_machine)-1);
86 fstrcpy(local_machine,name1);
87 len = strlen(local_machine);
89 name_type = local_machine[15];
90 local_machine[15] = 0;
92 trim_string(local_machine," "," ");
93 strlower(local_machine);
94 alpha_strcpy(local_machine,local_machine,SAFE_NETBIOS_CHARS,sizeof(local_machine)-1);
96 DEBUG(2,("netbios connect: local=%s remote=%s\n",
97 local_machine, remote_machine ));
99 if (name_type == 'R') {
100 /* We are being asked for a pathworks session ---
102 SCVAL(outbuf, 0,0x83);
106 /* only add the client's machine name to the list
107 of possibly valid usernames if we are operating
108 in share mode security */
109 if (lp_security() == SEC_SHARE) {
110 add_session_user(remote_machine);
113 reload_services(True);
116 claim_connection(NULL,"",MAXSTATUS,True);
120 case 0x89: /* session keepalive request
121 (some old clients produce this?) */
122 SCVAL(outbuf,0,SMBkeepalive);
126 case 0x82: /* positive session response */
127 case 0x83: /* negative session response */
128 case 0x84: /* retarget session response */
129 DEBUG(0,("Unexpected session response\n"));
132 case SMBkeepalive: /* session keepalive */
137 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
138 msg_type, msg_flags));
144 /****************************************************************************
146 ****************************************************************************/
148 int reply_tcon(connection_struct *conn,
149 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
155 uint16 vuid = SVAL(inbuf,smb_uid);
159 DATA_BLOB password_blob;
161 START_PROFILE(SMBtcon);
163 *service = *password = *dev = 0;
165 p = smb_buf(inbuf)+1;
166 p += srvstr_pull_buf(inbuf, service, p, sizeof(service), STR_TERMINATE) + 1;
167 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
169 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
171 p = strrchr_m(service,'\\');
173 pstrcpy(service, p+1);
176 password_blob = data_blob(password, pwlen+1);
178 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
180 data_blob_clear_free(&password_blob);
183 END_PROFILE(SMBtcon);
184 return ERROR_NT(nt_status);
187 outsize = set_message(outbuf,2,0,True);
188 SSVAL(outbuf,smb_vwv0,max_recv);
189 SSVAL(outbuf,smb_vwv1,conn->cnum);
190 SSVAL(outbuf,smb_tid,conn->cnum);
192 DEBUG(3,("tcon service=%s cnum=%d\n",
193 service, conn->cnum));
195 END_PROFILE(SMBtcon);
199 /****************************************************************************
200 Reply to a tcon and X.
201 ****************************************************************************/
203 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
209 uint16 vuid = SVAL(inbuf,smb_uid);
210 int passlen = SVAL(inbuf,smb_vwv3);
213 extern BOOL global_encrypted_passwords_negotiated;
214 START_PROFILE(SMBtconX);
216 *service = *devicename = 0;
218 /* we might have to close an old one */
219 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
220 close_cnum(conn,vuid);
223 if (passlen > MAX_PASS_LEN) {
224 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
227 if (global_encrypted_passwords_negotiated) {
228 password = data_blob(smb_buf(inbuf),passlen);
230 password = data_blob(smb_buf(inbuf),passlen+1);
231 /* Ensure correct termination */
232 password.data[passlen]=0;
235 p = smb_buf(inbuf) + passlen;
236 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
239 * the service name can be either: \\server\share
240 * or share directly like on the DELL PowerVault 705
243 q = strchr_m(path+2,'\\');
245 END_PROFILE(SMBtconX);
246 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
248 fstrcpy(service,q+1);
251 fstrcpy(service,path);
253 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
255 DEBUG(4,("Got device type %s\n",devicename));
257 conn = make_connection(service,password,devicename,vuid,&nt_status);
259 data_blob_clear_free(&password);
262 END_PROFILE(SMBtconX);
263 return ERROR_NT(nt_status);
266 if (Protocol < PROTOCOL_NT1) {
267 set_message(outbuf,2,0,True);
269 p += srvstr_push(outbuf, p, devicename, -1,
270 STR_TERMINATE|STR_ASCII);
271 set_message_end(outbuf,p);
273 /* NT sets the fstype of IPC$ to the null string */
274 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
276 set_message(outbuf,3,0,True);
279 p += srvstr_push(outbuf, p, devicename, -1,
280 STR_TERMINATE|STR_ASCII);
281 p += srvstr_push(outbuf, p, fsname, -1,
284 set_message_end(outbuf,p);
286 /* what does setting this bit do? It is set by NT4 and
287 may affect the ability to autorun mounted cdroms */
288 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
289 (lp_csc_policy(SNUM(conn)) << 2));
291 init_dfsroot(conn, inbuf, outbuf);
295 DEBUG(3,("tconX service=%s \n",
298 /* set the incoming and outgoing tid to the just created one */
299 SSVAL(inbuf,smb_tid,conn->cnum);
300 SSVAL(outbuf,smb_tid,conn->cnum);
302 END_PROFILE(SMBtconX);
303 return chain_reply(inbuf,outbuf,length,bufsize);
307 /****************************************************************************
308 reply to an unknown type
309 ****************************************************************************/
310 int reply_unknown(char *inbuf,char *outbuf)
313 type = CVAL(inbuf,smb_com);
315 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
316 smb_fn_name(type), type, type));
318 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
322 /****************************************************************************
324 ****************************************************************************/
325 int reply_ioctl(connection_struct *conn,
326 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
328 uint16 device = SVAL(inbuf,smb_vwv1);
329 uint16 function = SVAL(inbuf,smb_vwv2);
330 uint32 ioctl_code = (device << 16) + function;
331 int replysize, outsize;
333 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
334 START_PROFILE(SMBioctl);
336 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
340 case IOCTL_QUERY_JOB_INFO:
344 END_PROFILE(SMBioctl);
345 return(ERROR_DOS(ERRSRV,ERRnosupport));
348 outsize = set_message(outbuf,8,replysize+1,True);
349 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
350 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
351 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
352 p = smb_buf(outbuf) + 1; /* Allow for alignment */
356 case IOCTL_QUERY_JOB_INFO:
357 SSVAL(p,0,fsp->print_jobid); /* Job number */
358 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
359 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
363 END_PROFILE(SMBioctl);
367 /****************************************************************************
369 ****************************************************************************/
370 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
376 BOOL bad_path = False;
377 SMB_STRUCT_STAT sbuf;
378 START_PROFILE(SMBchkpth);
380 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
382 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
384 unix_convert(name,conn,0,&bad_path,&sbuf);
386 mode = SVAL(inbuf,smb_vwv0);
388 if (check_name(name,conn)) {
389 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
390 ok = S_ISDIR(sbuf.st_mode);
394 /* We special case this - as when a Windows machine
395 is parsing a path is steps through the components
396 one at a time - if a component fails it expects
397 ERRbadpath, not ERRbadfile.
399 if(errno == ENOENT) {
400 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
403 return(UNIXERROR(ERRDOS,ERRbadpath));
406 outsize = set_message(outbuf,0,0,True);
408 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
410 END_PROFILE(SMBchkpth);
415 /****************************************************************************
417 ****************************************************************************/
418 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
422 SMB_STRUCT_STAT sbuf;
427 BOOL bad_path = False;
429 START_PROFILE(SMBgetatr);
431 p = smb_buf(inbuf) + 1;
432 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
434 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
436 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
437 under WfWg - weird! */
440 mode = aHIDDEN | aDIR;
441 if (!CAN_WRITE(conn)) mode |= aRONLY;
448 unix_convert(fname,conn,0,&bad_path,&sbuf);
449 if (check_name(fname,conn))
451 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
453 mode = dos_mode(conn,fname,&sbuf);
455 mtime = sbuf.st_mtime;
461 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
467 set_bad_path_error(errno, bad_path);
468 END_PROFILE(SMBgetatr);
469 return(UNIXERROR(ERRDOS,ERRbadfile));
472 outsize = set_message(outbuf,10,0,True);
474 SSVAL(outbuf,smb_vwv0,mode);
475 if(lp_dos_filetime_resolution(SNUM(conn)) )
476 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
478 put_dos_date3(outbuf,smb_vwv1,mtime);
479 SIVAL(outbuf,smb_vwv3,(uint32)size);
481 if (Protocol >= PROTOCOL_NT1)
482 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
484 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
486 END_PROFILE(SMBgetatr);
491 /****************************************************************************
493 ****************************************************************************/
494 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
501 SMB_STRUCT_STAT sbuf;
502 BOOL bad_path = False;
505 START_PROFILE(SMBsetatr);
507 p = smb_buf(inbuf) + 1;
508 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
509 unix_convert(fname,conn,0,&bad_path,&sbuf);
511 mode = SVAL(inbuf,smb_vwv0);
512 mtime = make_unix_date3(inbuf+smb_vwv1);
514 if (VALID_STAT_OF_DIR(sbuf))
519 if (check_name(fname,conn))
520 ok = (file_chmod(conn,fname,mode,NULL) == 0);
522 ok = set_filetime(conn,fname,mtime);
526 set_bad_path_error(errno, bad_path);
527 END_PROFILE(SMBsetatr);
528 return(UNIXERROR(ERRDOS,ERRnoaccess));
531 outsize = set_message(outbuf,0,0,True);
533 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
535 END_PROFILE(SMBsetatr);
540 /****************************************************************************
542 ****************************************************************************/
543 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
546 SMB_BIG_UINT dfree,dsize,bsize;
547 START_PROFILE(SMBdskattr);
549 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
551 outsize = set_message(outbuf,5,0,True);
553 if (Protocol <= PROTOCOL_LANMAN2) {
554 double total_space, free_space;
555 /* we need to scale this to a number that DOS6 can handle. We
556 use floating point so we can handle large drives on systems
557 that don't have 64 bit integers
559 we end up displaying a maximum of 2G to DOS systems
561 total_space = dsize * (double)bsize;
562 free_space = dfree * (double)bsize;
564 dsize = (total_space+63*512) / (64*512);
565 dfree = (free_space+63*512) / (64*512);
567 if (dsize > 0xFFFF) dsize = 0xFFFF;
568 if (dfree > 0xFFFF) dfree = 0xFFFF;
570 SSVAL(outbuf,smb_vwv0,dsize);
571 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
572 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
573 SSVAL(outbuf,smb_vwv3,dfree);
575 SSVAL(outbuf,smb_vwv0,dsize);
576 SSVAL(outbuf,smb_vwv1,bsize/512);
577 SSVAL(outbuf,smb_vwv2,512);
578 SSVAL(outbuf,smb_vwv3,dfree);
581 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
583 END_PROFILE(SMBdskattr);
588 /****************************************************************************
590 Can be called from SMBsearch, SMBffirst or SMBfunique.
591 ****************************************************************************/
592 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
603 BOOL finished = False;
612 BOOL check_descend = False;
613 BOOL expect_close = False;
614 BOOL can_open = True;
615 BOOL bad_path = False;
616 START_PROFILE(SMBsearch);
618 *mask = *directory = *fname = 0;
620 /* If we were called as SMBffirst then we must expect close. */
621 if(CVAL(inbuf,smb_com) == SMBffirst)
624 outsize = set_message(outbuf,1,3,True);
625 maxentries = SVAL(inbuf,smb_vwv0);
626 dirtype = SVAL(inbuf,smb_vwv1);
627 p = smb_buf(inbuf) + 1;
628 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
630 status_len = SVAL(p, 0);
633 /* dirtype &= ~aDIR; */
637 SMB_STRUCT_STAT sbuf;
640 pstrcpy(directory,path);
642 unix_convert(directory,conn,0,&bad_path,&sbuf);
645 if (!check_name(directory,conn))
648 p = strrchr_m(dir2,'/');
660 p = strrchr_m(directory,'/');
666 if (strlen(directory) == 0)
667 pstrcpy(directory,"./");
668 memset((char *)status,'\0',21);
669 SCVAL(status,0,dirtype);
674 dirtype = CVAL(status,0) & 0x1F;
675 conn->dirptr = dptr_fetch(status+12,&dptr_num);
678 string_set(&conn->dirpath,dptr_path(dptr_num));
679 fstrcpy(mask, dptr_wcard(dptr_num));
684 p = smb_buf(outbuf) + 3;
690 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
695 set_bad_path_error(errno, bad_path);
696 END_PROFILE(SMBsearch);
697 return (UNIXERROR(ERRDOS,ERRnofids));
699 END_PROFILE(SMBsearch);
700 return ERROR_DOS(ERRDOS,ERRnofids);
702 dptr_set_wcard(dptr_num, strdup(mask));
705 DEBUG(4,("dptr_num is %d\n",dptr_num));
709 if ((dirtype&0x1F) == aVOLID)
712 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
713 dptr_fill(p+12,dptr_num);
714 if (dptr_zero(p+12) && (status_len==0))
718 p += DIR_STRUCT_SIZE;
722 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
723 conn->dirpath,lp_dontdescend(SNUM(conn))));
724 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
725 check_descend = True;
727 for (i=numentries;(i<maxentries) && !finished;i++)
730 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
734 make_dir_struct(p,mask,fname,size,mode,date);
735 dptr_fill(p+12,dptr_num);
738 p += DIR_STRUCT_SIZE;
747 if (numentries == 0 || !ok)
749 SCVAL(outbuf,smb_rcls,ERRDOS);
750 SSVAL(outbuf,smb_err,ERRnofiles);
751 dptr_close(&dptr_num);
754 /* If we were called as SMBffirst with smb_search_id == NULL
755 and no entries were found then return error and close dirptr
758 if(ok && expect_close && numentries == 0 && status_len == 0)
760 SCVAL(outbuf,smb_rcls,ERRDOS);
761 SSVAL(outbuf,smb_err,ERRnofiles);
762 /* Also close the dptr - we know it's gone */
763 dptr_close(&dptr_num);
766 /* If we were called as SMBfunique, then we can close the dirptr now ! */
767 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
768 dptr_close(&dptr_num);
770 SSVAL(outbuf,smb_vwv0,numentries);
771 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
772 SCVAL(smb_buf(outbuf),0,5);
773 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
775 if (Protocol >= PROTOCOL_NT1)
776 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
778 outsize += DIR_STRUCT_SIZE*numentries;
779 smb_setlen(outbuf,outsize - 4);
781 if ((! *directory) && dptr_path(dptr_num))
782 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
784 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
785 smb_fn_name(CVAL(inbuf,smb_com)),
786 mask, directory, dirtype, numentries, maxentries ) );
788 END_PROFILE(SMBsearch);
793 /****************************************************************************
794 reply to a fclose (stop directory search)
795 ****************************************************************************/
796 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
805 START_PROFILE(SMBfclose);
807 outsize = set_message(outbuf,1,0,True);
808 p = smb_buf(inbuf) + 1;
809 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
811 status_len = SVAL(p,0);
814 if (status_len == 0) {
815 END_PROFILE(SMBfclose);
816 return ERROR_DOS(ERRSRV,ERRsrverror);
821 if(dptr_fetch(status+12,&dptr_num)) {
822 /* Close the dptr - we know it's gone */
823 dptr_close(&dptr_num);
826 SSVAL(outbuf,smb_vwv0,0);
828 DEBUG(3,("search close\n"));
830 END_PROFILE(SMBfclose);
835 /****************************************************************************
837 ****************************************************************************/
839 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
849 SMB_STRUCT_STAT sbuf;
850 BOOL bad_path = False;
852 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
853 START_PROFILE(SMBopen);
855 share_mode = SVAL(inbuf,smb_vwv0);
857 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
859 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
861 unix_convert(fname,conn,0,&bad_path,&sbuf);
863 unixmode = unix_mode(conn,aARCH,fname);
865 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
866 unixmode, oplock_request,&rmode,NULL);
870 set_bad_path_error(errno, bad_path);
871 END_PROFILE(SMBopen);
872 return(UNIXERROR(ERRDOS,ERRnoaccess));
876 fmode = dos_mode(conn,fname,&sbuf);
877 mtime = sbuf.st_mtime;
880 DEBUG(3,("attempt to open a directory %s\n",fname));
881 close_file(fsp,False);
882 END_PROFILE(SMBopen);
883 return ERROR_DOS(ERRDOS,ERRnoaccess);
886 outsize = set_message(outbuf,7,0,True);
887 SSVAL(outbuf,smb_vwv0,fsp->fnum);
888 SSVAL(outbuf,smb_vwv1,fmode);
889 if(lp_dos_filetime_resolution(SNUM(conn)) )
890 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
892 put_dos_date3(outbuf,smb_vwv2,mtime);
893 SIVAL(outbuf,smb_vwv4,(uint32)size);
894 SSVAL(outbuf,smb_vwv6,rmode);
896 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
897 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
900 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
901 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
902 END_PROFILE(SMBopen);
907 /****************************************************************************
908 reply to an open and X
909 ****************************************************************************/
910 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
913 int smb_mode = SVAL(inbuf,smb_vwv3);
914 int smb_attr = SVAL(inbuf,smb_vwv5);
915 /* Breakout the oplock request bits so we can set the
916 reply bits separately. */
917 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
918 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
919 BOOL oplock_request = ex_oplock_request | core_oplock_request;
921 int open_flags = SVAL(inbuf,smb_vwv2);
922 int smb_sattr = SVAL(inbuf,smb_vwv4);
923 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
925 int smb_ofun = SVAL(inbuf,smb_vwv8);
928 int fmode=0,mtime=0,rmode=0;
929 SMB_STRUCT_STAT sbuf;
931 BOOL bad_path = False;
933 START_PROFILE(SMBopenX);
935 /* If it's an IPC, pass off the pipe handler. */
937 if (lp_nt_pipe_support()) {
938 END_PROFILE(SMBopenX);
939 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
941 END_PROFILE(SMBopenX);
942 return ERROR_DOS(ERRSRV,ERRaccess);
946 /* XXXX we need to handle passed times, sattr and flags */
947 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
949 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
951 unix_convert(fname,conn,0,&bad_path,&sbuf);
953 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
955 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
956 oplock_request, &rmode,&smb_action);
960 set_bad_path_error(errno, bad_path);
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 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
996 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
997 SCVAL(outbuf,smb_flg,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_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 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 set_bad_path_error(errno, bad_path);
1096 END_PROFILE(SMBcreate);
1097 return(UNIXERROR(ERRDOS,ERRnoaccess));
1100 outsize = set_message(outbuf,1,0,True);
1101 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1103 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1104 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1107 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1108 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1110 DEBUG( 2, ( "new file %s\n", fname ) );
1111 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1112 fname, fsp->fd, createmode, (int)unixmode ) );
1114 END_PROFILE(SMBcreate);
1119 /****************************************************************************
1120 reply to a create temporary file
1121 ****************************************************************************/
1122 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1128 BOOL bad_path = False;
1130 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1132 SMB_STRUCT_STAT sbuf;
1135 START_PROFILE(SMBctemp);
1137 createmode = SVAL(inbuf,smb_vwv0);
1138 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1139 pstrcat(fname,"\\TMXXXXXX");
1141 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1143 unix_convert(fname,conn,0,&bad_path,&sbuf);
1145 unixmode = unix_mode(conn,createmode,fname);
1147 tmpfd = smb_mkstemp(fname);
1149 END_PROFILE(SMBctemp);
1150 return(UNIXERROR(ERRDOS,ERRnoaccess));
1153 vfs_stat(conn,fname,&sbuf);
1155 /* Open file in dos compatibility share mode. */
1156 /* We should fail if file does not exist. */
1157 fsp = open_file_shared(conn,fname,&sbuf,
1158 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1159 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1160 unixmode, oplock_request, NULL, NULL);
1162 /* close fd from smb_mkstemp() */
1166 set_bad_path_error(errno, bad_path);
1167 END_PROFILE(SMBctemp);
1168 return(UNIXERROR(ERRDOS,ERRnoaccess));
1171 outsize = set_message(outbuf,1,0,True);
1172 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1174 /* the returned filename is relative to the directory */
1175 s = strrchr_m(fname, '/');
1182 p = smb_buf(outbuf);
1183 SSVALS(p, 0, -1); /* what is this? not in spec */
1184 SSVAL(p, 2, strlen(s));
1186 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1187 outsize = set_message_end(outbuf, p);
1189 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1190 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1193 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1194 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1196 DEBUG( 2, ( "created temp file %s\n", fname ) );
1197 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1198 fname, fsp->fd, createmode, (int)unixmode ) );
1200 END_PROFILE(SMBctemp);
1204 /*******************************************************************
1205 Check if a user is allowed to rename a file.
1206 ********************************************************************/
1208 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1214 if (!CAN_WRITE(conn))
1215 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1217 if (S_ISDIR(pst->st_mode))
1218 return NT_STATUS_OK;
1220 /* We need a better way to return NT status codes from open... */
1224 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1225 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1228 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1229 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1230 ret = NT_STATUS_SHARING_VIOLATION;
1235 close_file(fsp,False);
1236 return NT_STATUS_OK;
1239 /*******************************************************************
1240 Check if a user is allowed to delete a file.
1241 ********************************************************************/
1243 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1245 SMB_STRUCT_STAT sbuf;
1251 if (!CAN_WRITE(conn))
1252 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1254 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
1255 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1257 fmode = dos_mode(conn,fname,&sbuf);
1259 return NT_STATUS_FILE_IS_A_DIRECTORY;
1260 if (!lp_delete_readonly(SNUM(conn))) {
1262 return NT_STATUS_CANNOT_DELETE;
1264 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1265 return NT_STATUS_CANNOT_DELETE;
1267 /* We need a better way to return NT status codes from open... */
1271 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1272 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1275 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1276 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1277 ret = NT_STATUS_SHARING_VIOLATION;
1282 close_file(fsp,False);
1283 return NT_STATUS_OK;
1286 /****************************************************************************
1287 The guts of the unlink command, split out so it may be called by the NT SMB
1289 ****************************************************************************/
1291 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1297 NTSTATUS error = NT_STATUS_OK;
1299 BOOL bad_path = False;
1301 SMB_STRUCT_STAT sbuf;
1303 *directory = *mask = 0;
1305 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1307 p = strrchr_m(name,'/');
1309 pstrcpy(directory,".");
1313 pstrcpy(directory,name);
1318 * We should only check the mangled cache
1319 * here if unix_convert failed. This means
1320 * that the path in 'mask' doesn't exist
1321 * on the file system and so we need to look
1322 * for a possible mangle. This patch from
1323 * Tine Smukavec <valentin.smukavec@hermes.si>.
1326 if (!rc && mangle_is_mangled(mask))
1327 mangle_check_cache( mask );
1329 has_wild = ms_has_wild(mask);
1332 pstrcat(directory,"/");
1333 pstrcat(directory,mask);
1334 error = can_delete(directory,conn,dirtype);
1335 if (!NT_STATUS_IS_OK(error)) return error;
1337 if (vfs_unlink(conn,directory) == 0) {
1341 void *dirptr = NULL;
1344 if (check_name(directory,conn))
1345 dirptr = OpenDir(conn, directory, True);
1347 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1348 the pattern matches against the long name, otherwise the short name
1349 We don't implement this yet XXXX
1353 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1355 if (strequal(mask,"????????.???"))
1358 while ((dname = ReadDirName(dirptr))) {
1360 pstrcpy(fname,dname);
1362 if(!mask_match(fname, mask, case_sensitive)) continue;
1364 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1365 error = can_delete(fname,conn,dirtype);
1366 if (!NT_STATUS_IS_OK(error)) continue;
1367 if (vfs_unlink(conn,fname) == 0) count++;
1368 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1374 if (count == 0 && NT_STATUS_IS_OK(error)) {
1375 error = map_nt_error_from_unix(errno);
1381 /****************************************************************************
1383 ****************************************************************************/
1385 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1392 START_PROFILE(SMBunlink);
1394 dirtype = SVAL(inbuf,smb_vwv0);
1396 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1398 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1400 DEBUG(3,("reply_unlink : %s\n",name));
1402 status = unlink_internals(conn, dirtype, name);
1403 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1406 * Win2k needs a changenotify request response before it will
1407 * update after a rename..
1409 process_pending_change_notify_queue((time_t)0);
1411 outsize = set_message(outbuf,0,0,True);
1413 END_PROFILE(SMBunlink);
1417 /****************************************************************************
1419 ****************************************************************************/
1421 void fail_readraw(void)
1424 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1426 exit_server(errstr);
1429 /****************************************************************************
1430 Reply to a readbraw (core+ protocol).
1431 ****************************************************************************/
1433 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1435 ssize_t maxcount,mincount;
1438 char *header = outbuf;
1441 START_PROFILE(SMBreadbraw);
1444 * Special check if an oplock break has been issued
1445 * and the readraw request croses on the wire, we must
1446 * return a zero length response here.
1449 if(global_oplock_break) {
1450 _smb_setlen(header,0);
1451 if (write_data(smbd_server_fd(),header,4) != 4)
1453 DEBUG(5,("readbraw - oplock break finished\n"));
1454 END_PROFILE(SMBreadbraw);
1458 fsp = file_fsp(inbuf,smb_vwv0);
1460 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1462 * fsp could be NULL here so use the value from the packet. JRA.
1464 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1465 _smb_setlen(header,0);
1466 if (write_data(smbd_server_fd(),header,4) != 4)
1468 END_PROFILE(SMBreadbraw);
1472 CHECK_FSP(fsp,conn);
1474 flush_write_cache(fsp, READRAW_FLUSH);
1476 startpos = IVAL(inbuf,smb_vwv1);
1477 if(CVAL(inbuf,smb_wct) == 10) {
1479 * This is a large offset (64 bit) read.
1481 #ifdef LARGE_SMB_OFF_T
1483 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1485 #else /* !LARGE_SMB_OFF_T */
1488 * Ensure we haven't been sent a >32 bit offset.
1491 if(IVAL(inbuf,smb_vwv8) != 0) {
1492 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1493 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1494 _smb_setlen(header,0);
1495 if (write_data(smbd_server_fd(),header,4) != 4)
1497 END_PROFILE(SMBreadbraw);
1501 #endif /* LARGE_SMB_OFF_T */
1504 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1505 _smb_setlen(header,0);
1506 if (write_data(smbd_server_fd(),header,4) != 4)
1508 END_PROFILE(SMBreadbraw);
1512 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1513 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1515 /* ensure we don't overrun the packet size */
1516 maxcount = MIN(65535,maxcount);
1517 maxcount = MAX(mincount,maxcount);
1519 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1520 SMB_OFF_T size = fsp->size;
1521 SMB_OFF_T sizeneeded = startpos + maxcount;
1523 if (size < sizeneeded) {
1525 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1527 if (!fsp->can_write)
1531 if (startpos >= size)
1534 nread = MIN(maxcount,(size - startpos));
1537 if (nread < mincount)
1540 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1541 (int)maxcount, (int)mincount, (int)nread ) );
1544 ret = read_file(fsp,header+4,startpos,nread);
1549 _smb_setlen(header,ret);
1550 if (write_data(smbd_server_fd(),header,4+ret) != 4+ret)
1553 DEBUG(5,("readbraw finished\n"));
1554 END_PROFILE(SMBreadbraw);
1558 /****************************************************************************
1559 reply to a lockread (core+ protocol)
1560 ****************************************************************************/
1561 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1569 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1570 START_PROFILE(SMBlockread);
1572 CHECK_FSP(fsp,conn);
1575 release_level_2_oplocks_on_change(fsp);
1577 numtoread = SVAL(inbuf,smb_vwv1);
1578 startpos = IVAL(inbuf,smb_vwv2);
1580 outsize = set_message(outbuf,5,3,True);
1581 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1582 data = smb_buf(outbuf) + 3;
1585 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1586 * protocol request that predates the read/write lock concept.
1587 * Thus instead of asking for a read lock here we need to ask
1588 * for a write lock. JRA.
1591 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1592 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1594 if (NT_STATUS_V(status)) {
1595 if (lp_blocking_locks(SNUM(conn))) {
1597 * A blocking lock was requested. Package up
1598 * this smb into a queued request and push it
1599 * onto the blocking lock queue.
1601 if(push_blocking_lock_request(inbuf, length, -1, 0))
1602 END_PROFILE(SMBlockread);
1605 END_PROFILE(SMBlockread);
1606 return ERROR_NT(status);
1609 nread = read_file(fsp,data,startpos,numtoread);
1612 END_PROFILE(SMBlockread);
1613 return(UNIXERROR(ERRDOS,ERRnoaccess));
1617 SSVAL(outbuf,smb_vwv0,nread);
1618 SSVAL(outbuf,smb_vwv5,nread+3);
1619 SSVAL(smb_buf(outbuf),1,nread);
1621 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1622 fsp->fnum, (int)numtoread, (int)nread));
1624 END_PROFILE(SMBlockread);
1629 /****************************************************************************
1631 ****************************************************************************/
1633 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1640 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1641 START_PROFILE(SMBread);
1643 CHECK_FSP(fsp,conn);
1646 numtoread = SVAL(inbuf,smb_vwv1);
1647 startpos = IVAL(inbuf,smb_vwv2);
1650 outsize = set_message(outbuf,5,3,True);
1651 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1652 data = smb_buf(outbuf) + 3;
1654 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1655 END_PROFILE(SMBread);
1656 return ERROR_DOS(ERRDOS,ERRlock);
1660 nread = read_file(fsp,data,startpos,numtoread);
1663 END_PROFILE(SMBread);
1664 return(UNIXERROR(ERRDOS,ERRnoaccess));
1668 SSVAL(outbuf,smb_vwv0,nread);
1669 SSVAL(outbuf,smb_vwv5,nread+3);
1670 SCVAL(smb_buf(outbuf),0,1);
1671 SSVAL(smb_buf(outbuf),1,nread);
1673 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1674 fsp->fnum, (int)numtoread, (int)nread ) );
1676 END_PROFILE(SMBread);
1681 /****************************************************************************
1682 reply to a read and X
1683 ****************************************************************************/
1684 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1686 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1687 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
1688 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1689 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1692 START_PROFILE(SMBreadX);
1694 /* If it's an IPC, pass off the pipe handler. */
1696 END_PROFILE(SMBreadX);
1697 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1700 CHECK_FSP(fsp,conn);
1703 set_message(outbuf,12,0,True);
1704 data = smb_buf(outbuf);
1706 if(CVAL(inbuf,smb_wct) == 12) {
1707 #ifdef LARGE_SMB_OFF_T
1709 * This is a large offset (64 bit) read.
1711 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1713 #else /* !LARGE_SMB_OFF_T */
1716 * Ensure we haven't been sent a >32 bit offset.
1719 if(IVAL(inbuf,smb_vwv10) != 0) {
1720 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1721 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1722 END_PROFILE(SMBreadX);
1723 return ERROR_DOS(ERRDOS,ERRbadaccess);
1726 #endif /* LARGE_SMB_OFF_T */
1730 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1731 END_PROFILE(SMBreadX);
1732 return ERROR_DOS(ERRDOS,ERRlock);
1734 nread = read_file(fsp,data,startpos,smb_maxcnt);
1737 END_PROFILE(SMBreadX);
1738 return(UNIXERROR(ERRDOS,ERRnoaccess));
1741 SSVAL(outbuf,smb_vwv5,nread);
1742 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1743 SSVAL(smb_buf(outbuf),-2,nread);
1745 DEBUG( 3, ( "readX fnum=%d min=%d max=%d nread=%d\n",
1746 fsp->fnum, (int)smb_mincnt, (int)smb_maxcnt, (int)nread ) );
1748 END_PROFILE(SMBreadX);
1749 return chain_reply(inbuf,outbuf,length,bufsize);
1752 /****************************************************************************
1753 reply to a writebraw (core+ or LANMAN1.0 protocol)
1754 ****************************************************************************/
1756 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1759 ssize_t total_written=0;
1760 size_t numtowrite=0;
1765 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1767 START_PROFILE(SMBwritebraw);
1769 CHECK_FSP(fsp,conn);
1772 tcount = IVAL(inbuf,smb_vwv1);
1773 startpos = IVAL(inbuf,smb_vwv3);
1774 write_through = BITSETW(inbuf+smb_vwv7,0);
1776 /* We have to deal with slightly different formats depending
1777 on whether we are using the core+ or lanman1.0 protocol */
1779 if(Protocol <= PROTOCOL_COREPLUS) {
1780 numtowrite = SVAL(smb_buf(inbuf),-2);
1781 data = smb_buf(inbuf);
1783 numtowrite = SVAL(inbuf,smb_vwv10);
1784 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1787 /* force the error type */
1788 SCVAL(inbuf,smb_com,SMBwritec);
1789 SCVAL(outbuf,smb_com,SMBwritec);
1791 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1792 END_PROFILE(SMBwritebraw);
1793 return(ERROR_DOS(ERRDOS,ERRlock));
1797 nwritten = write_file(fsp,data,startpos,numtowrite);
1799 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1800 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1802 if (nwritten < numtowrite) {
1803 END_PROFILE(SMBwritebraw);
1804 return(UNIXERROR(ERRHRD,ERRdiskfull));
1807 total_written = nwritten;
1809 /* Return a message to the redirector to tell it to send more bytes */
1810 SCVAL(outbuf,smb_com,SMBwritebraw);
1811 SSVALS(outbuf,smb_vwv0,-1);
1812 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1813 if (!send_smb(smbd_server_fd(),outbuf))
1814 exit_server("reply_writebraw: send_smb failed.");
1816 /* Now read the raw data into the buffer and write it */
1817 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1818 exit_server("secondary writebraw failed");
1821 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1822 numtowrite = smb_len(inbuf);
1824 /* Set up outbuf to return the correct return */
1825 outsize = set_message(outbuf,1,0,True);
1826 SCVAL(outbuf,smb_com,SMBwritec);
1827 SSVAL(outbuf,smb_vwv0,total_written);
1829 if (numtowrite != 0) {
1831 if (numtowrite > BUFFER_SIZE) {
1832 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1833 (unsigned int)numtowrite ));
1834 exit_server("secondary writebraw failed");
1837 if (tcount > nwritten+numtowrite) {
1838 DEBUG(3,("Client overestimated the write %d %d %d\n",
1839 (int)tcount,(int)nwritten,(int)numtowrite));
1842 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1843 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1845 exit_server("secondary writebraw failed");
1848 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1850 if (nwritten < (ssize_t)numtowrite) {
1851 SCVAL(outbuf,smb_rcls,ERRHRD);
1852 SSVAL(outbuf,smb_err,ERRdiskfull);
1856 total_written += nwritten;
1859 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1860 sync_file(conn,fsp);
1862 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1863 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1865 /* we won't return a status if write through is not selected - this follows what WfWg does */
1866 END_PROFILE(SMBwritebraw);
1867 if (!write_through && total_written==tcount) {
1869 #if RABBIT_PELLET_FIX
1871 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
1872 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
1874 if (!send_keepalive(smbd_server_fd()))
1875 exit_server("reply_writebraw: send of keepalive failed");
1883 /****************************************************************************
1884 reply to a writeunlock (core+)
1885 ****************************************************************************/
1887 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
1888 int size, int dum_buffsize)
1890 ssize_t nwritten = -1;
1895 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1897 START_PROFILE(SMBwriteunlock);
1899 CHECK_FSP(fsp,conn);
1902 numtowrite = SVAL(inbuf,smb_vwv1);
1903 startpos = IVAL(inbuf,smb_vwv2);
1904 data = smb_buf(inbuf) + 3;
1906 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
1907 WRITE_LOCK,False)) {
1908 END_PROFILE(SMBwriteunlock);
1909 return ERROR_DOS(ERRDOS,ERRlock);
1912 /* The special X/Open SMB protocol handling of
1913 zero length writes is *NOT* done for
1918 nwritten = write_file(fsp,data,startpos,numtowrite);
1920 if (lp_syncalways(SNUM(conn)))
1921 sync_file(conn,fsp);
1923 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
1924 END_PROFILE(SMBwriteunlock);
1925 return(UNIXERROR(ERRDOS,ERRnoaccess));
1928 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
1929 (SMB_BIG_UINT)startpos);
1930 if (NT_STATUS_V(status)) {
1931 END_PROFILE(SMBwriteunlock);
1932 return ERROR_NT(status);
1935 outsize = set_message(outbuf,1,0,True);
1937 SSVAL(outbuf,smb_vwv0,nwritten);
1939 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
1940 fsp->fnum, (int)numtowrite, (int)nwritten));
1942 END_PROFILE(SMBwriteunlock);
1947 /****************************************************************************
1949 ****************************************************************************/
1951 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
1954 ssize_t nwritten = -1;
1957 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1959 START_PROFILE(SMBwrite);
1961 /* If it's an IPC, pass off the pipe handler. */
1963 END_PROFILE(SMBwrite);
1964 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
1967 CHECK_FSP(fsp,conn);
1970 numtowrite = SVAL(inbuf,smb_vwv1);
1971 startpos = IVAL(inbuf,smb_vwv2);
1972 data = smb_buf(inbuf) + 3;
1974 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1975 END_PROFILE(SMBwrite);
1976 return ERROR_DOS(ERRDOS,ERRlock);
1980 * X/Open SMB protocol says that if smb_vwv1 is
1981 * zero then the file size should be extended or
1982 * truncated to the size given in smb_vwv[2-3].
1985 if(numtowrite == 0) {
1987 * This is actually an allocate call, and set EOF. JRA.
1989 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
1991 END_PROFILE(SMBwrite);
1992 return ERROR_NT(NT_STATUS_DISK_FULL);
1994 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
1996 END_PROFILE(SMBwrite);
1997 return ERROR_NT(NT_STATUS_DISK_FULL);
2000 nwritten = write_file(fsp,data,startpos,numtowrite);
2002 if (lp_syncalways(SNUM(conn)))
2003 sync_file(conn,fsp);
2005 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2006 END_PROFILE(SMBwrite);
2007 return(UNIXERROR(ERRDOS,ERRnoaccess));
2010 outsize = set_message(outbuf,1,0,True);
2012 SSVAL(outbuf,smb_vwv0,nwritten);
2014 if (nwritten < (ssize_t)numtowrite) {
2015 SCVAL(outbuf,smb_rcls,ERRHRD);
2016 SSVAL(outbuf,smb_err,ERRdiskfull);
2019 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2021 END_PROFILE(SMBwrite);
2026 /****************************************************************************
2027 reply to a write and X
2028 ****************************************************************************/
2029 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2031 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2032 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2033 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2034 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2035 ssize_t nwritten = -1;
2036 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2037 unsigned int smblen = smb_len(inbuf);
2039 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2040 START_PROFILE(SMBwriteX);
2042 /* If it's an IPC, pass off the pipe handler. */
2044 END_PROFILE(SMBwriteX);
2045 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2048 CHECK_FSP(fsp,conn);
2051 /* Deal with possible LARGE_WRITEX */
2053 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2055 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2056 END_PROFILE(SMBwriteX);
2057 return ERROR_DOS(ERRDOS,ERRbadmem);
2060 data = smb_base(inbuf) + smb_doff;
2062 if(CVAL(inbuf,smb_wct) == 14) {
2063 #ifdef LARGE_SMB_OFF_T
2065 * This is a large offset (64 bit) write.
2067 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2069 #else /* !LARGE_SMB_OFF_T */
2072 * Ensure we haven't been sent a >32 bit offset.
2075 if(IVAL(inbuf,smb_vwv12) != 0) {
2076 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2077 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2078 END_PROFILE(SMBwriteX);
2079 return ERROR_DOS(ERRDOS,ERRbadaccess);
2082 #endif /* LARGE_SMB_OFF_T */
2085 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2086 END_PROFILE(SMBwriteX);
2087 return ERROR_DOS(ERRDOS,ERRlock);
2090 /* X/Open SMB protocol says that, unlike SMBwrite
2091 if the length is zero then NO truncation is
2092 done, just a write of zero. To truncate a file,
2097 nwritten = write_file(fsp,data,startpos,numtowrite);
2099 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2100 END_PROFILE(SMBwriteX);
2101 return(UNIXERROR(ERRDOS,ERRnoaccess));
2104 set_message(outbuf,6,0,True);
2106 SSVAL(outbuf,smb_vwv2,nwritten);
2108 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2110 if (nwritten < (ssize_t)numtowrite) {
2111 SCVAL(outbuf,smb_rcls,ERRHRD);
2112 SSVAL(outbuf,smb_err,ERRdiskfull);
2115 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2116 fsp->fnum, (int)numtowrite, (int)nwritten));
2118 if (lp_syncalways(SNUM(conn)) || write_through)
2119 sync_file(conn,fsp);
2121 END_PROFILE(SMBwriteX);
2122 return chain_reply(inbuf,outbuf,length,bufsize);
2126 /****************************************************************************
2128 ****************************************************************************/
2130 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2136 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2137 START_PROFILE(SMBlseek);
2139 CHECK_FSP(fsp,conn);
2141 flush_write_cache(fsp, SEEK_FLUSH);
2143 mode = SVAL(inbuf,smb_vwv1) & 3;
2144 startpos = IVALS(inbuf,smb_vwv2);
2147 case 0: umode = SEEK_SET; break;
2148 case 1: umode = SEEK_CUR; break;
2149 case 2: umode = SEEK_END; break;
2151 umode = SEEK_SET; break;
2154 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2156 * Check for the special case where a seek before the start
2157 * of the file sets the offset to zero. Added in the CIFS spec,
2161 if(errno == EINVAL) {
2162 SMB_OFF_T current_pos = startpos;
2164 if(umode == SEEK_CUR) {
2166 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2167 END_PROFILE(SMBlseek);
2168 return(UNIXERROR(ERRDOS,ERRnoaccess));
2171 current_pos += startpos;
2173 } else if (umode == SEEK_END) {
2175 SMB_STRUCT_STAT sbuf;
2177 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2178 END_PROFILE(SMBlseek);
2179 return(UNIXERROR(ERRDOS,ERRnoaccess));
2182 current_pos += sbuf.st_size;
2186 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2190 END_PROFILE(SMBlseek);
2191 return(UNIXERROR(ERRDOS,ERRnoaccess));
2197 outsize = set_message(outbuf,2,0,True);
2198 SIVAL(outbuf,smb_vwv0,res);
2200 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2201 fsp->fnum, (double)startpos, (double)res, mode));
2203 END_PROFILE(SMBlseek);
2207 /****************************************************************************
2209 ****************************************************************************/
2211 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2213 int outsize = set_message(outbuf,0,0,True);
2214 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2215 START_PROFILE(SMBflush);
2217 CHECK_FSP(fsp,conn);
2220 file_sync_all(conn);
2222 sync_file(conn,fsp);
2225 DEBUG(3,("flush\n"));
2226 END_PROFILE(SMBflush);
2231 /****************************************************************************
2233 ****************************************************************************/
2234 int reply_exit(connection_struct *conn,
2235 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2238 START_PROFILE(SMBexit);
2239 outsize = set_message(outbuf,0,0,True);
2241 DEBUG(3,("exit\n"));
2243 END_PROFILE(SMBexit);
2248 /****************************************************************************
2249 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2250 ****************************************************************************/
2251 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2256 int32 eclass = 0, err = 0;
2257 files_struct *fsp = NULL;
2258 START_PROFILE(SMBclose);
2260 outsize = set_message(outbuf,0,0,True);
2262 /* If it's an IPC, pass off to the pipe handler. */
2264 END_PROFILE(SMBclose);
2265 return reply_pipe_close(conn, inbuf,outbuf);
2268 fsp = file_fsp(inbuf,smb_vwv0);
2271 * We can only use CHECK_FSP if we know it's not a directory.
2274 if(!fsp || (fsp->conn != conn)) {
2275 END_PROFILE(SMBclose);
2276 return ERROR_DOS(ERRDOS,ERRbadfid);
2279 if(fsp->is_directory) {
2281 * Special case - close NT SMB directory handle.
2283 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2284 close_file(fsp,True);
2287 * Close ordinary file.
2292 /* Save the name for time set in close. */
2293 pstrcpy( file_name, fsp->fsp_name);
2295 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2297 conn->num_files_open));
2300 * close_file() returns the unix errno if an error
2301 * was detected on close - normally this is due to
2302 * a disk full error. If not then it was probably an I/O error.
2305 if((close_err = close_file(fsp,True)) != 0) {
2307 END_PROFILE(SMBclose);
2308 return (UNIXERROR(ERRHRD,ERRgeneral));
2312 * Now take care of any time sent in the close.
2315 mtime = make_unix_date3(inbuf+smb_vwv1);
2317 /* try and set the date */
2318 set_filetime(conn, file_name, mtime);
2322 /* We have a cached error */
2324 END_PROFILE(SMBclose);
2325 return ERROR_DOS(eclass,err);
2328 END_PROFILE(SMBclose);
2333 /****************************************************************************
2334 reply to a writeclose (Core+ protocol)
2335 ****************************************************************************/
2337 int reply_writeclose(connection_struct *conn,
2338 char *inbuf,char *outbuf, int size, int dum_buffsize)
2341 ssize_t nwritten = -1;
2347 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2348 START_PROFILE(SMBwriteclose);
2350 CHECK_FSP(fsp,conn);
2353 numtowrite = SVAL(inbuf,smb_vwv1);
2354 startpos = IVAL(inbuf,smb_vwv2);
2355 mtime = make_unix_date3(inbuf+smb_vwv4);
2356 data = smb_buf(inbuf) + 1;
2358 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2359 END_PROFILE(SMBwriteclose);
2360 return ERROR_DOS(ERRDOS,ERRlock);
2363 nwritten = write_file(fsp,data,startpos,numtowrite);
2365 set_filetime(conn, fsp->fsp_name,mtime);
2367 close_err = close_file(fsp,True);
2369 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2370 fsp->fnum, (int)numtowrite, (int)nwritten,
2371 conn->num_files_open));
2373 if (nwritten <= 0) {
2374 END_PROFILE(SMBwriteclose);
2375 return(UNIXERROR(ERRDOS,ERRnoaccess));
2378 if(close_err != 0) {
2380 END_PROFILE(SMBwriteclose);
2381 return(UNIXERROR(ERRHRD,ERRgeneral));
2384 outsize = set_message(outbuf,1,0,True);
2386 SSVAL(outbuf,smb_vwv0,nwritten);
2387 END_PROFILE(SMBwriteclose);
2392 /****************************************************************************
2394 ****************************************************************************/
2395 int reply_lock(connection_struct *conn,
2396 char *inbuf,char *outbuf, int length, int dum_buffsize)
2398 int outsize = set_message(outbuf,0,0,True);
2399 SMB_BIG_UINT count,offset;
2401 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2402 START_PROFILE(SMBlock);
2404 CHECK_FSP(fsp,conn);
2406 release_level_2_oplocks_on_change(fsp);
2408 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2409 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2411 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2412 fsp->fd, fsp->fnum, (double)offset, (double)count));
2414 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2415 if (NT_STATUS_V(status)) {
2416 if (lp_blocking_locks(SNUM(conn))) {
2418 * A blocking lock was requested. Package up
2419 * this smb into a queued request and push it
2420 * onto the blocking lock queue.
2422 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2423 END_PROFILE(SMBlock);
2427 END_PROFILE(SMBlock);
2428 return ERROR_NT(status);
2431 END_PROFILE(SMBlock);
2436 /****************************************************************************
2438 ****************************************************************************/
2439 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2442 int outsize = set_message(outbuf,0,0,True);
2443 SMB_BIG_UINT count,offset;
2445 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2446 START_PROFILE(SMBunlock);
2448 CHECK_FSP(fsp,conn);
2450 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2451 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2453 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2454 if (NT_STATUS_V(status)) {
2455 END_PROFILE(SMBunlock);
2456 return ERROR_NT(status);
2459 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2460 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2462 END_PROFILE(SMBunlock);
2467 /****************************************************************************
2469 ****************************************************************************/
2470 int reply_tdis(connection_struct *conn,
2471 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2473 int outsize = set_message(outbuf,0,0,True);
2475 START_PROFILE(SMBtdis);
2477 vuid = SVAL(inbuf,smb_uid);
2480 DEBUG(4,("Invalid connection in tdis\n"));
2481 END_PROFILE(SMBtdis);
2482 return ERROR_DOS(ERRSRV,ERRinvnid);
2487 close_cnum(conn,vuid);
2489 END_PROFILE(SMBtdis);
2495 /****************************************************************************
2497 ****************************************************************************/
2498 int reply_echo(connection_struct *conn,
2499 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2501 int smb_reverb = SVAL(inbuf,smb_vwv0);
2503 unsigned int data_len = smb_buflen(inbuf);
2504 int outsize = set_message(outbuf,1,data_len,True);
2505 START_PROFILE(SMBecho);
2507 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2509 /* copy any incoming data back out */
2511 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2513 if (smb_reverb > 100) {
2514 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2518 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2519 SSVAL(outbuf,smb_vwv0,seq_num);
2521 smb_setlen(outbuf,outsize - 4);
2523 if (!send_smb(smbd_server_fd(),outbuf))
2524 exit_server("reply_echo: send_smb failed.");
2527 DEBUG(3,("echo %d times\n", smb_reverb));
2531 END_PROFILE(SMBecho);
2536 /****************************************************************************
2537 reply to a printopen
2538 ****************************************************************************/
2539 int reply_printopen(connection_struct *conn,
2540 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2544 START_PROFILE(SMBsplopen);
2546 if (!CAN_PRINT(conn)) {
2547 END_PROFILE(SMBsplopen);
2548 return ERROR_DOS(ERRDOS,ERRnoaccess);
2551 /* Open for exclusive use, write only. */
2552 fsp = print_fsp_open(conn, NULL);
2555 END_PROFILE(SMBsplopen);
2556 return(UNIXERROR(ERRDOS,ERRnoaccess));
2559 outsize = set_message(outbuf,1,0,True);
2560 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2562 DEBUG(3,("openprint fd=%d fnum=%d\n",
2563 fsp->fd, fsp->fnum));
2565 END_PROFILE(SMBsplopen);
2570 /****************************************************************************
2571 reply to a printclose
2572 ****************************************************************************/
2573 int reply_printclose(connection_struct *conn,
2574 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2576 int outsize = set_message(outbuf,0,0,True);
2577 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2579 START_PROFILE(SMBsplclose);
2581 CHECK_FSP(fsp,conn);
2583 if (!CAN_PRINT(conn)) {
2584 END_PROFILE(SMBsplclose);
2585 return ERROR_DOS(ERRDOS,ERRnoaccess);
2588 DEBUG(3,("printclose fd=%d fnum=%d\n",
2589 fsp->fd,fsp->fnum));
2591 close_err = close_file(fsp,True);
2593 if(close_err != 0) {
2595 END_PROFILE(SMBsplclose);
2596 return(UNIXERROR(ERRHRD,ERRgeneral));
2599 END_PROFILE(SMBsplclose);
2604 /****************************************************************************
2605 reply to a printqueue
2606 ****************************************************************************/
2607 int reply_printqueue(connection_struct *conn,
2608 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2610 int outsize = set_message(outbuf,2,3,True);
2611 int max_count = SVAL(inbuf,smb_vwv0);
2612 int start_index = SVAL(inbuf,smb_vwv1);
2613 START_PROFILE(SMBsplretq);
2615 /* we used to allow the client to get the cnum wrong, but that
2616 is really quite gross and only worked when there was only
2617 one printer - I think we should now only accept it if they
2618 get it right (tridge) */
2619 if (!CAN_PRINT(conn)) {
2620 END_PROFILE(SMBsplretq);
2621 return ERROR_DOS(ERRDOS,ERRnoaccess);
2624 SSVAL(outbuf,smb_vwv0,0);
2625 SSVAL(outbuf,smb_vwv1,0);
2626 SCVAL(smb_buf(outbuf),0,1);
2627 SSVAL(smb_buf(outbuf),1,0);
2629 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2630 start_index, max_count));
2633 print_queue_struct *queue = NULL;
2634 print_status_struct status;
2635 char *p = smb_buf(outbuf) + 3;
2636 int count = print_queue_status(SNUM(conn), &queue, &status);
2637 int num_to_get = ABS(max_count);
2638 int first = (max_count>0?start_index:start_index+max_count+1);
2644 num_to_get = MIN(num_to_get,count-first);
2647 for (i=first;i<first+num_to_get;i++) {
2648 put_dos_date2(p,0,queue[i].time);
2649 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2650 SSVAL(p,5, queue[i].job);
2651 SIVAL(p,7,queue[i].size);
2653 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2658 outsize = set_message(outbuf,2,28*count+3,False);
2659 SSVAL(outbuf,smb_vwv0,count);
2660 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2661 SCVAL(smb_buf(outbuf),0,1);
2662 SSVAL(smb_buf(outbuf),1,28*count);
2667 DEBUG(3,("%d entries returned in queue\n",count));
2670 END_PROFILE(SMBsplretq);
2675 /****************************************************************************
2676 reply to a printwrite
2677 ****************************************************************************/
2678 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2681 int outsize = set_message(outbuf,0,0,True);
2683 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2684 START_PROFILE(SMBsplwr);
2686 if (!CAN_PRINT(conn)) {
2687 END_PROFILE(SMBsplwr);
2688 return ERROR_DOS(ERRDOS,ERRnoaccess);
2691 CHECK_FSP(fsp,conn);
2694 numtowrite = SVAL(smb_buf(inbuf),1);
2695 data = smb_buf(inbuf) + 3;
2697 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2698 END_PROFILE(SMBsplwr);
2699 return(UNIXERROR(ERRDOS,ERRnoaccess));
2702 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2704 END_PROFILE(SMBsplwr);
2709 /****************************************************************************
2710 The guts of the mkdir command, split out so it may be called by the NT SMB
2712 ****************************************************************************/
2713 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2715 BOOL bad_path = False;
2716 SMB_STRUCT_STAT sbuf;
2719 unix_convert(directory,conn,0,&bad_path,&sbuf);
2721 if (check_name(directory, conn))
2722 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2725 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
2726 if (!NT_STATUS_IS_OK(nterr))
2728 return map_nt_error_from_unix(errno);
2731 return NT_STATUS_OK;
2734 /****************************************************************************
2736 ****************************************************************************/
2738 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2743 START_PROFILE(SMBmkdir);
2745 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2747 status = mkdir_internal(conn, directory);
2748 if (!NT_STATUS_IS_OK(status))
2749 return ERROR_NT(status);
2751 outsize = set_message(outbuf,0,0,True);
2753 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2755 END_PROFILE(SMBmkdir);
2759 /****************************************************************************
2760 Static function used by reply_rmdir to delete an entire directory
2761 tree recursively. Return False on ok, True on fail.
2762 ****************************************************************************/
2764 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2768 void *dirptr = OpenDir(conn, directory, False);
2773 while((dname = ReadDirName(dirptr))) {
2777 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2780 /* Construct the full name. */
2781 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2787 pstrcpy(fullname, directory);
2788 pstrcat(fullname, "/");
2789 pstrcat(fullname, dname);
2791 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
2796 if(st.st_mode & S_IFDIR) {
2797 if(recursive_rmdir(conn, fullname)!=0) {
2801 if(vfs_rmdir(conn,fullname) != 0) {
2805 } else if(vfs_unlink(conn,fullname) != 0) {
2814 /****************************************************************************
2815 The internals of the rmdir code - called elsewhere.
2816 ****************************************************************************/
2818 BOOL rmdir_internals(connection_struct *conn, char *directory)
2822 ok = (vfs_rmdir(conn,directory) == 0);
2823 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2825 * Check to see if the only thing in this directory are
2826 * vetoed files/directories. If so then delete them and
2827 * retry. If we fail to delete any of them (and we *don't*
2828 * do a recursive delete) then fail the rmdir.
2830 BOOL all_veto_files = True;
2832 void *dirptr = OpenDir(conn, directory, False);
2834 if(dirptr != NULL) {
2835 int dirpos = TellDir(dirptr);
2836 while ((dname = ReadDirName(dirptr))) {
2837 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2839 if(!IS_VETO_PATH(conn, dname)) {
2840 all_veto_files = False;
2845 if(all_veto_files) {
2846 SeekDir(dirptr,dirpos);
2847 while ((dname = ReadDirName(dirptr))) {
2851 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2854 /* Construct the full name. */
2855 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2860 pstrcpy(fullname, directory);
2861 pstrcat(fullname, "/");
2862 pstrcat(fullname, dname);
2864 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
2866 if(st.st_mode & S_IFDIR) {
2867 if(lp_recursive_veto_delete(SNUM(conn))) {
2868 if(recursive_rmdir(conn, fullname) != 0)
2871 if(vfs_rmdir(conn,fullname) != 0)
2873 } else if(vfs_unlink(conn,fullname) != 0)
2877 /* Retry the rmdir */
2878 ok = (vfs_rmdir(conn,directory) == 0);
2888 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
2893 /****************************************************************************
2895 ****************************************************************************/
2897 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2902 BOOL bad_path = False;
2903 SMB_STRUCT_STAT sbuf;
2904 START_PROFILE(SMBrmdir);
2906 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2908 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
2910 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
2912 if (check_name(directory,conn))
2914 dptr_closepath(directory,SVAL(inbuf,smb_pid));
2915 ok = rmdir_internals(conn, directory);
2920 set_bad_path_error(errno, bad_path);
2921 END_PROFILE(SMBrmdir);
2922 return(UNIXERROR(ERRDOS,ERRbadpath));
2925 outsize = set_message(outbuf,0,0,True);
2927 DEBUG( 3, ( "rmdir %s\n", directory ) );
2929 END_PROFILE(SMBrmdir);
2934 /*******************************************************************
2935 resolve wildcards in a filename rename
2936 ********************************************************************/
2937 static BOOL resolve_wildcards(char *name1,char *name2)
2939 fstring root1,root2;
2943 name1 = strrchr_m(name1,'/');
2944 name2 = strrchr_m(name2,'/');
2946 if (!name1 || !name2) return(False);
2948 fstrcpy(root1,name1);
2949 fstrcpy(root2,name2);
2950 p = strrchr_m(root1,'.');
2957 p = strrchr_m(root2,'.');
2989 pstrcpy(name2,root2);
2992 pstrcat(name2,ext2);
2998 /****************************************************************************
2999 The guts of the rename command, split out so it may be called by the NT SMB
3001 ****************************************************************************/
3003 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3007 pstring newname_last_component;
3010 BOOL bad_path1 = False;
3011 BOOL bad_path2 = False;
3013 NTSTATUS error = NT_STATUS_OK;
3015 SMB_STRUCT_STAT sbuf1, sbuf2;
3017 *directory = *mask = 0;
3019 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3020 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3023 * Split the old name into directory and last component
3024 * strings. Note that unix_convert may have stripped off a
3025 * leading ./ from both name and newname if the rename is
3026 * at the root of the share. We need to make sure either both
3027 * name and newname contain a / character or neither of them do
3028 * as this is checked in resolve_wildcards().
3031 p = strrchr_m(name,'/');
3033 pstrcpy(directory,".");
3037 pstrcpy(directory,name);
3039 *p = '/'; /* Replace needed for exceptional test below. */
3043 * We should only check the mangled cache
3044 * here if unix_convert failed. This means
3045 * that the path in 'mask' doesn't exist
3046 * on the file system and so we need to look
3047 * for a possible mangle. This patch from
3048 * Tine Smukavec <valentin.smukavec@hermes.si>.
3051 if (!rc && mangle_is_mangled(mask))
3052 mangle_check_cache( mask );
3054 has_wild = ms_has_wild(mask);
3058 * No wildcards - just process the one file.
3060 BOOL is_short_name = mangle_is_8_3(name, True);
3062 /* Add a terminating '/' to the directory name. */
3063 pstrcat(directory,"/");
3064 pstrcat(directory,mask);
3066 /* Ensure newname contains a '/' also */
3067 if(strrchr_m(newname,'/') == 0) {
3070 pstrcpy(tmpstr, "./");
3071 pstrcat(tmpstr, newname);
3072 pstrcpy(newname, tmpstr);
3075 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3076 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3077 case_sensitive, case_preserve, short_case_preserve, directory,
3078 newname, newname_last_component, is_short_name));
3081 * Check for special case with case preserving and not
3082 * case sensitive, if directory and newname are identical,
3083 * and the old last component differs from the original
3084 * last component only by case, then we should allow
3085 * the rename (user is trying to change the case of the
3088 if((case_sensitive == False) &&
3089 (((case_preserve == True) &&
3090 (is_short_name == False)) ||
3091 ((short_case_preserve == True) &&
3092 (is_short_name == True))) &&
3093 strcsequal(directory, newname)) {
3094 pstring newname_modified_last_component;
3097 * Get the last component of the modified name.
3098 * Note that we guarantee that newname contains a '/'
3101 p = strrchr_m(newname,'/');
3102 pstrcpy(newname_modified_last_component,p+1);
3104 if(strcsequal(newname_modified_last_component,
3105 newname_last_component) == False) {
3107 * Replace the modified last component with
3110 pstrcpy(p+1, newname_last_component);
3114 resolve_wildcards(directory,newname);
3117 * The source object must exist.
3120 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3121 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3122 directory,newname));
3124 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3126 * Must return different errors depending on whether the parent
3127 * directory existed or not.
3130 p = strrchr_m(directory, '/');
3132 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3134 if (vfs_object_exist(conn, directory, NULL))
3135 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3136 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3138 error = map_nt_error_from_unix(errno);
3139 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3140 nt_errstr(error), directory,newname));
3145 error = can_rename(directory,conn,&sbuf1);
3147 if (!NT_STATUS_IS_OK(error)) {
3148 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3149 nt_errstr(error), directory,newname));
3154 * If the src and dest names are identical - including case,
3155 * don't do the rename, just return success.
3158 if (strcsequal(directory, newname)) {
3159 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3160 return NT_STATUS_OK;
3163 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3164 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3165 directory,newname));
3166 return NT_STATUS_OBJECT_NAME_COLLISION;
3169 if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
3170 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3171 directory,newname));
3172 return NT_STATUS_OK;
3175 if (errno == ENOTDIR || errno == EISDIR)
3176 error = NT_STATUS_OBJECT_NAME_COLLISION;
3178 error = map_nt_error_from_unix(errno);
3180 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3181 nt_errstr(error), directory,newname));
3186 * Wildcards - process each file that matches.
3188 void *dirptr = NULL;
3192 if (check_name(directory,conn))
3193 dirptr = OpenDir(conn, directory, True);
3196 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3198 if (strequal(mask,"????????.???"))
3201 while ((dname = ReadDirName(dirptr))) {
3204 pstrcpy(fname,dname);
3206 if(!mask_match(fname, mask, case_sensitive))
3209 error = NT_STATUS_ACCESS_DENIED;
3210 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3211 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3212 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3213 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3216 error = can_rename(fname,conn,&sbuf1);
3217 if (!NT_STATUS_IS_OK(error)) {
3218 DEBUG(6,("rename %s refused\n", fname));
3221 pstrcpy(destname,newname);
3223 if (!resolve_wildcards(fname,destname)) {
3224 DEBUG(6,("resolve_wildcards %s %s failed\n",
3229 if (!replace_if_exists &&
3230 vfs_file_exist(conn,destname, NULL)) {
3231 DEBUG(6,("file_exist %s\n", destname));
3232 error = NT_STATUS_OBJECT_NAME_COLLISION;
3236 if (!conn->vfs_ops.rename(conn,fname,destname))
3238 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3244 if (count == 0 && NT_STATUS_IS_OK(error)) {
3245 error = map_nt_error_from_unix(errno);
3251 /****************************************************************************
3253 ****************************************************************************/
3255 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3264 START_PROFILE(SMBmv);
3266 p = smb_buf(inbuf) + 1;
3267 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3269 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3271 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3272 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3274 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3276 status = rename_internals(conn, name, newname, False);
3277 if (!NT_STATUS_IS_OK(status)) {
3278 return ERROR_NT(status);
3282 * Win2k needs a changenotify request response before it will
3283 * update after a rename..
3285 process_pending_change_notify_queue((time_t)0);
3286 outsize = set_message(outbuf,0,0,True);
3292 /*******************************************************************
3293 Copy a file as part of a reply_copy.
3294 ******************************************************************/
3296 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3297 int count,BOOL target_is_directory, int *err_ret)
3300 SMB_STRUCT_STAT src_sbuf, sbuf2;
3302 files_struct *fsp1,*fsp2;
3307 pstrcpy(dest,dest1);
3308 if (target_is_directory) {
3309 char *p = strrchr_m(src,'/');
3318 if (!vfs_file_exist(conn,src,&src_sbuf))
3321 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3322 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3327 if (!target_is_directory && count)
3328 ofun = FILE_EXISTS_OPEN;
3330 if (vfs_stat(conn,dest,&sbuf2) == -1)
3331 ZERO_STRUCTP(&sbuf2);
3333 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3334 ofun,src_sbuf.st_mode,0,&Access,&action);
3337 close_file(fsp1,False);
3341 if ((ofun&3) == 1) {
3342 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3343 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3345 * Stop the copy from occurring.
3348 src_sbuf.st_size = 0;
3352 if (src_sbuf.st_size)
3353 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3355 close_file(fsp1,False);
3357 /* Ensure the modtime is set correctly on the destination file. */
3358 fsp2->pending_modtime = src_sbuf.st_mtime;
3361 * As we are opening fsp1 read-only we only expect
3362 * an error on close on fsp2 if we are out of space.
3363 * Thus we don't look at the error return from the
3366 *err_ret = close_file(fsp2,False);
3368 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3371 /****************************************************************************
3372 reply to a file copy.
3373 ****************************************************************************/
3374 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3379 pstring mask,newname;
3382 int error = ERRnoaccess;
3386 int tid2 = SVAL(inbuf,smb_vwv0);
3387 int ofun = SVAL(inbuf,smb_vwv1);
3388 int flags = SVAL(inbuf,smb_vwv2);
3389 BOOL target_is_directory=False;
3390 BOOL bad_path1 = False;
3391 BOOL bad_path2 = False;
3393 SMB_STRUCT_STAT sbuf1, sbuf2;
3394 START_PROFILE(SMBcopy);
3396 *directory = *mask = 0;
3399 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3400 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3402 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3404 if (tid2 != conn->cnum) {
3405 /* can't currently handle inter share copies XXXX */
3406 DEBUG(3,("Rejecting inter-share copy\n"));
3407 END_PROFILE(SMBcopy);
3408 return ERROR_DOS(ERRSRV,ERRinvdevice);
3411 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3412 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3414 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3415 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3417 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3419 if ((flags&1) && target_is_directory) {
3420 END_PROFILE(SMBcopy);
3421 return ERROR_DOS(ERRDOS,ERRbadfile);
3424 if ((flags&2) && !target_is_directory) {
3425 END_PROFILE(SMBcopy);
3426 return ERROR_DOS(ERRDOS,ERRbadpath);
3429 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3430 /* wants a tree copy! XXXX */
3431 DEBUG(3,("Rejecting tree copy\n"));
3432 END_PROFILE(SMBcopy);
3433 return ERROR_DOS(ERRSRV,ERRerror);
3436 p = strrchr_m(name,'/');
3438 pstrcpy(directory,"./");
3442 pstrcpy(directory,name);
3447 * We should only check the mangled cache
3448 * here if unix_convert failed. This means
3449 * that the path in 'mask' doesn't exist
3450 * on the file system and so we need to look
3451 * for a possible mangle. This patch from
3452 * Tine Smukavec <valentin.smukavec@hermes.si>.
3455 if (!rc && mangle_is_mangled(mask))
3456 mangle_check_cache( mask );
3458 has_wild = ms_has_wild(mask);
3461 pstrcat(directory,"/");
3462 pstrcat(directory,mask);
3463 if (resolve_wildcards(directory,newname) &&
3464 copy_file(directory,newname,conn,ofun,
3465 count,target_is_directory,&err)) count++;
3468 END_PROFILE(SMBcopy);
3469 return(UNIXERROR(ERRHRD,ERRgeneral));
3471 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3473 void *dirptr = NULL;
3477 if (check_name(directory,conn))
3478 dirptr = OpenDir(conn, directory, True);
3483 if (strequal(mask,"????????.???"))
3486 while ((dname = ReadDirName(dirptr))) {
3488 pstrcpy(fname,dname);
3490 if(!mask_match(fname, mask, case_sensitive))
3493 error = ERRnoaccess;
3494 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3495 pstrcpy(destname,newname);
3496 if (resolve_wildcards(fname,destname) &&
3497 copy_file(fname,destname,conn,ofun,
3498 count,target_is_directory,&err)) count++;
3499 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3507 /* Error on close... */
3509 END_PROFILE(SMBcopy);
3510 return(UNIXERROR(ERRHRD,ERRgeneral));
3514 END_PROFILE(SMBcopy);
3515 return ERROR_DOS(ERRDOS,error);
3518 if((errno == ENOENT) && (bad_path1 || bad_path2))
3520 unix_ERR_class = ERRDOS;
3521 unix_ERR_code = ERRbadpath;
3523 END_PROFILE(SMBcopy);
3524 return(UNIXERROR(ERRDOS,error));
3528 outsize = set_message(outbuf,1,0,True);
3529 SSVAL(outbuf,smb_vwv0,count);
3531 END_PROFILE(SMBcopy);
3535 /****************************************************************************
3537 ****************************************************************************/
3538 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3544 START_PROFILE(pathworks_setdir);
3547 if (!CAN_SETDIR(snum)) {
3548 END_PROFILE(pathworks_setdir);
3549 return ERROR_DOS(ERRDOS,ERRnoaccess);
3552 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3554 if (strlen(newdir) == 0) {
3557 ok = vfs_directory_exist(conn,newdir,NULL);
3559 string_set(&conn->connectpath,newdir);
3564 END_PROFILE(pathworks_setdir);
3565 return ERROR_DOS(ERRDOS,ERRbadpath);
3568 outsize = set_message(outbuf,0,0,True);
3569 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3571 DEBUG(3,("setdir %s\n", newdir));
3573 END_PROFILE(pathworks_setdir);
3577 /****************************************************************************
3578 Get a lock pid, dealing with large count requests.
3579 ****************************************************************************/
3581 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3583 if(!large_file_format)
3584 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3586 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3589 /****************************************************************************
3590 Get a lock count, dealing with large count requests.
3591 ****************************************************************************/
3593 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3595 SMB_BIG_UINT count = 0;
3597 if(!large_file_format) {
3598 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3601 #if defined(HAVE_LONGLONG)
3602 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3603 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3604 #else /* HAVE_LONGLONG */
3607 * NT4.x seems to be broken in that it sends large file (64 bit)
3608 * lockingX calls even if the CAP_LARGE_FILES was *not*
3609 * negotiated. For boxes without large unsigned ints truncate the
3610 * lock count by dropping the top 32 bits.
3613 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3614 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3615 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3616 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3617 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3620 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3621 #endif /* HAVE_LONGLONG */
3627 #if !defined(HAVE_LONGLONG)
3628 /****************************************************************************
3629 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3630 ****************************************************************************/
3631 static uint32 map_lock_offset(uint32 high, uint32 low)
3635 uint32 highcopy = high;
3638 * Try and find out how many significant bits there are in high.
3641 for(i = 0; highcopy; i++)
3645 * We use 31 bits not 32 here as POSIX
3646 * lock offsets may not be negative.
3649 mask = (~0) << (31 - i);
3652 return 0; /* Fail. */
3658 #endif /* !defined(HAVE_LONGLONG) */
3660 /****************************************************************************
3661 Get a lock offset, dealing with large offset requests.
3662 ****************************************************************************/
3664 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3666 SMB_BIG_UINT offset = 0;
3670 if(!large_file_format) {
3671 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3674 #if defined(HAVE_LONGLONG)
3675 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3676 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3677 #else /* HAVE_LONGLONG */
3680 * NT4.x seems to be broken in that it sends large file (64 bit)
3681 * lockingX calls even if the CAP_LARGE_FILES was *not*
3682 * negotiated. For boxes without large unsigned ints mangle the
3683 * lock offset by mapping the top 32 bits onto the lower 32.
3686 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3687 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3688 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3691 if((new_low = map_lock_offset(high, low)) == 0) {
3693 return (SMB_BIG_UINT)-1;
3696 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3697 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3698 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3699 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3702 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3703 #endif /* HAVE_LONGLONG */
3709 /****************************************************************************
3710 reply to a lockingX request
3711 ****************************************************************************/
3713 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3715 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3716 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3717 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3718 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3719 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3720 SMB_BIG_UINT count = 0, offset = 0;
3722 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3725 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3729 START_PROFILE(SMBlockingX);
3731 CHECK_FSP(fsp,conn);
3733 data = smb_buf(inbuf);
3735 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3736 /* we don't support these - and CANCEL_LOCK makes w2k
3737 and XP reboot so I don't really want to be
3738 compatible! (tridge) */
3739 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3742 /* Check if this is an oplock break on a file
3743 we have granted an oplock on.
3745 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3746 /* Client can insist on breaking to none. */
3747 BOOL break_to_none = (oplocklevel == 0);
3749 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3750 (unsigned int)oplocklevel, fsp->fnum ));
3753 * Make sure we have granted an exclusive or batch oplock on this file.
3756 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3757 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3758 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3760 /* if this is a pure oplock break request then don't send a reply */
3761 if (num_locks == 0 && num_ulocks == 0) {
3762 END_PROFILE(SMBlockingX);
3765 END_PROFILE(SMBlockingX);
3766 return ERROR_DOS(ERRDOS,ERRlock);
3770 if (remove_oplock(fsp, break_to_none) == False) {
3771 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3775 /* if this is a pure oplock break request then don't send a reply */
3776 if (num_locks == 0 && num_ulocks == 0) {
3777 /* Sanity check - ensure a pure oplock break is not a
3779 if(CVAL(inbuf,smb_vwv0) != 0xff)
3780 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3781 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3782 END_PROFILE(SMBlockingX);
3788 * We do this check *after* we have checked this is not a oplock break
3789 * response message. JRA.
3792 release_level_2_oplocks_on_change(fsp);
3794 /* Data now points at the beginning of the list
3795 of smb_unlkrng structs */
3796 for(i = 0; i < (int)num_ulocks; i++) {
3797 lock_pid = get_lock_pid( data, i, large_file_format);
3798 count = get_lock_count( data, i, large_file_format);
3799 offset = get_lock_offset( data, i, large_file_format, &err);
3802 * There is no error code marked "stupid client bug".... :-).
3805 END_PROFILE(SMBlockingX);
3806 return ERROR_DOS(ERRDOS,ERRnoaccess);
3809 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3810 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3812 status = do_unlock(fsp,conn,lock_pid,count,offset);
3813 if (NT_STATUS_V(status)) {
3814 END_PROFILE(SMBlockingX);
3815 return ERROR_NT(status);
3819 /* Setup the timeout in seconds. */
3821 lock_timeout = ((lock_timeout == -1) ? -1 : lock_timeout/1000);
3823 /* Now do any requested locks */
3824 data += ((large_file_format ? 20 : 10)*num_ulocks);
3826 /* Data now points at the beginning of the list
3827 of smb_lkrng structs */
3829 for(i = 0; i < (int)num_locks; i++) {
3830 lock_pid = get_lock_pid( data, i, large_file_format);
3831 count = get_lock_count( data, i, large_file_format);
3832 offset = get_lock_offset( data, i, large_file_format, &err);
3835 * There is no error code marked "stupid client bug".... :-).
3838 END_PROFILE(SMBlockingX);
3839 return ERROR_DOS(ERRDOS,ERRnoaccess);
3842 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3843 (double)offset, (double)count, (unsigned int)lock_pid,
3844 fsp->fsp_name, (int)lock_timeout ));
3846 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
3847 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3848 if (NT_STATUS_V(status)) {
3849 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn))) {
3851 * A blocking lock was requested. Package up
3852 * this smb into a queued request and push it
3853 * onto the blocking lock queue.
3855 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
3856 END_PROFILE(SMBlockingX);
3864 /* If any of the above locks failed, then we must unlock
3865 all of the previous locks (X/Open spec). */
3866 if (i != num_locks && num_locks != 0) {
3868 * Ensure we don't do a remove on the lock that just failed,
3869 * as under POSIX rules, if we have a lock already there, we
3870 * will delete it (and we shouldn't) .....
3872 for(i--; i >= 0; i--) {
3873 lock_pid = get_lock_pid( data, i, large_file_format);
3874 count = get_lock_count( data, i, large_file_format);
3875 offset = get_lock_offset( data, i, large_file_format, &err);
3878 * There is no error code marked "stupid client bug".... :-).
3881 END_PROFILE(SMBlockingX);
3882 return ERROR_DOS(ERRDOS,ERRnoaccess);
3885 do_unlock(fsp,conn,lock_pid,count,offset);
3887 END_PROFILE(SMBlockingX);
3888 return ERROR_NT(status);
3891 set_message(outbuf,2,0,True);
3893 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3894 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3896 END_PROFILE(SMBlockingX);
3897 return chain_reply(inbuf,outbuf,length,bufsize);
3900 /****************************************************************************
3901 Reply to a SMBreadbmpx (read block multiplex) request.
3902 ****************************************************************************/
3904 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3915 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3916 START_PROFILE(SMBreadBmpx);
3918 /* this function doesn't seem to work - disable by default */
3919 if (!lp_readbmpx()) {
3920 END_PROFILE(SMBreadBmpx);
3921 return ERROR_DOS(ERRSRV,ERRuseSTD);
3924 outsize = set_message(outbuf,8,0,True);
3926 CHECK_FSP(fsp,conn);
3929 startpos = IVAL(inbuf,smb_vwv1);
3930 maxcount = SVAL(inbuf,smb_vwv3);
3932 data = smb_buf(outbuf);
3933 pad = ((long)data)%4;
3938 max_per_packet = bufsize-(outsize+pad);
3942 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
3943 END_PROFILE(SMBreadBmpx);
3944 return ERROR_DOS(ERRDOS,ERRlock);
3948 size_t N = MIN(max_per_packet,tcount-total_read);
3950 nread = read_file(fsp,data,startpos,N);
3955 if (nread < (ssize_t)N)
3956 tcount = total_read + nread;
3958 set_message(outbuf,8,nread,False);
3959 SIVAL(outbuf,smb_vwv0,startpos);
3960 SSVAL(outbuf,smb_vwv2,tcount);
3961 SSVAL(outbuf,smb_vwv6,nread);
3962 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
3964 if (!send_smb(smbd_server_fd(),outbuf))
3965 exit_server("reply_readbmpx: send_smb failed.");
3967 total_read += nread;
3969 } while (total_read < (ssize_t)tcount);
3971 END_PROFILE(SMBreadBmpx);
3975 /****************************************************************************
3976 Reply to a SMBsetattrE.
3977 ****************************************************************************/
3979 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
3981 struct utimbuf unix_times;
3983 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
3984 START_PROFILE(SMBsetattrE);
3986 outsize = set_message(outbuf,0,0,True);
3988 if(!fsp || (fsp->conn != conn)) {
3989 END_PROFILE(SMBgetattrE);
3990 return ERROR_DOS(ERRDOS,ERRbadfid);
3994 * Convert the DOS times into unix times. Ignore create
3995 * time as UNIX can't set this.
3998 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
3999 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4002 * Patch from Ray Frush <frush@engr.colostate.edu>
4003 * Sometimes times are sent as zero - ignore them.
4006 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4007 /* Ignore request */
4008 if( DEBUGLVL( 3 ) ) {
4009 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4010 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4012 END_PROFILE(SMBsetattrE);
4014 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4015 /* set modify time = to access time if modify time was 0 */
4016 unix_times.modtime = unix_times.actime;
4019 /* Set the date on this file */
4020 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4021 END_PROFILE(SMBsetattrE);
4022 return ERROR_DOS(ERRDOS,ERRnoaccess);
4025 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4026 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4028 END_PROFILE(SMBsetattrE);
4033 /* Back from the dead for OS/2..... JRA. */
4035 /****************************************************************************
4036 Reply to a SMBwritebmpx (write block multiplex primary) request.
4037 ****************************************************************************/
4039 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4042 ssize_t nwritten = -1;
4049 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4050 START_PROFILE(SMBwriteBmpx);
4052 CHECK_FSP(fsp,conn);
4056 tcount = SVAL(inbuf,smb_vwv1);
4057 startpos = IVAL(inbuf,smb_vwv3);
4058 write_through = BITSETW(inbuf+smb_vwv7,0);
4059 numtowrite = SVAL(inbuf,smb_vwv10);
4060 smb_doff = SVAL(inbuf,smb_vwv11);
4062 data = smb_base(inbuf) + smb_doff;
4064 /* If this fails we need to send an SMBwriteC response,
4065 not an SMBwritebmpx - set this up now so we don't forget */
4066 SCVAL(outbuf,smb_com,SMBwritec);
4068 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4069 END_PROFILE(SMBwriteBmpx);
4070 return(ERROR_DOS(ERRDOS,ERRlock));
4073 nwritten = write_file(fsp,data,startpos,numtowrite);
4075 if(lp_syncalways(SNUM(conn)) || write_through)
4076 sync_file(conn,fsp);
4078 if(nwritten < (ssize_t)numtowrite) {
4079 END_PROFILE(SMBwriteBmpx);
4080 return(UNIXERROR(ERRHRD,ERRdiskfull));
4083 /* If the maximum to be written to this file
4084 is greater than what we just wrote then set
4085 up a secondary struct to be attached to this
4086 fd, we will use this to cache error messages etc. */
4088 if((ssize_t)tcount > nwritten) {
4089 write_bmpx_struct *wbms;
4090 if(fsp->wbmpx_ptr != NULL)
4091 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4093 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4095 DEBUG(0,("Out of memory in reply_readmpx\n"));
4096 END_PROFILE(SMBwriteBmpx);
4097 return(ERROR_DOS(ERRSRV,ERRnoresource));
4099 wbms->wr_mode = write_through;
4100 wbms->wr_discard = False; /* No errors yet */
4101 wbms->wr_total_written = nwritten;
4102 wbms->wr_errclass = 0;
4104 fsp->wbmpx_ptr = wbms;
4107 /* We are returning successfully, set the message type back to
4109 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4111 outsize = set_message(outbuf,1,0,True);
4113 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4115 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4116 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4118 if (write_through && tcount==nwritten) {
4119 /* We need to send both a primary and a secondary response */
4120 smb_setlen(outbuf,outsize - 4);
4121 if (!send_smb(smbd_server_fd(),outbuf))
4122 exit_server("reply_writebmpx: send_smb failed.");
4124 /* Now the secondary */
4125 outsize = set_message(outbuf,1,0,True);
4126 SCVAL(outbuf,smb_com,SMBwritec);
4127 SSVAL(outbuf,smb_vwv0,nwritten);
4130 END_PROFILE(SMBwriteBmpx);
4134 /****************************************************************************
4135 Reply to a SMBwritebs (write block multiplex secondary) request.
4136 ****************************************************************************/
4138 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4141 ssize_t nwritten = -1;
4148 write_bmpx_struct *wbms;
4149 BOOL send_response = False;
4150 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4151 START_PROFILE(SMBwriteBs);
4153 CHECK_FSP(fsp,conn);
4156 tcount = SVAL(inbuf,smb_vwv1);
4157 startpos = IVAL(inbuf,smb_vwv2);
4158 numtowrite = SVAL(inbuf,smb_vwv6);
4159 smb_doff = SVAL(inbuf,smb_vwv7);
4161 data = smb_base(inbuf) + smb_doff;
4163 /* We need to send an SMBwriteC response, not an SMBwritebs */
4164 SCVAL(outbuf,smb_com,SMBwritec);
4166 /* This fd should have an auxiliary struct attached,
4167 check that it does */
4168 wbms = fsp->wbmpx_ptr;
4170 END_PROFILE(SMBwriteBs);
4174 /* If write through is set we can return errors, else we must cache them */
4175 write_through = wbms->wr_mode;
4177 /* Check for an earlier error */
4178 if(wbms->wr_discard) {
4179 END_PROFILE(SMBwriteBs);
4180 return -1; /* Just discard the packet */
4183 nwritten = write_file(fsp,data,startpos,numtowrite);
4185 if(lp_syncalways(SNUM(conn)) || write_through)
4186 sync_file(conn,fsp);
4188 if (nwritten < (ssize_t)numtowrite) {
4190 /* We are returning an error - we can delete the aux struct */
4193 fsp->wbmpx_ptr = NULL;
4194 END_PROFILE(SMBwriteBs);
4195 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4197 END_PROFILE(SMBwriteBs);
4198 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4201 /* Increment the total written, if this matches tcount
4202 we can discard the auxiliary struct (hurrah !) and return a writeC */
4203 wbms->wr_total_written += nwritten;
4204 if(wbms->wr_total_written >= tcount) {
4205 if (write_through) {
4206 outsize = set_message(outbuf,1,0,True);
4207 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4208 send_response = True;
4212 fsp->wbmpx_ptr = NULL;
4216 END_PROFILE(SMBwriteBs);
4220 END_PROFILE(SMBwriteBs);
4224 /****************************************************************************
4225 Reply to a SMBgetattrE.
4226 ****************************************************************************/
4228 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4230 SMB_STRUCT_STAT sbuf;
4233 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4234 START_PROFILE(SMBgetattrE);
4236 outsize = set_message(outbuf,11,0,True);
4238 if(!fsp || (fsp->conn != conn)) {
4239 END_PROFILE(SMBgetattrE);
4240 return ERROR_DOS(ERRDOS,ERRbadfid);
4243 /* Do an fstat on this file */
4244 if(fsp_stat(fsp, &sbuf)) {
4245 END_PROFILE(SMBgetattrE);
4246 return(UNIXERROR(ERRDOS,ERRnoaccess));
4249 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4252 * Convert the times into dos times. Set create
4253 * date to be last modify date as UNIX doesn't save
4257 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4258 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4259 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4262 SIVAL(outbuf,smb_vwv6,0);
4263 SIVAL(outbuf,smb_vwv8,0);
4265 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4266 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4268 SSVAL(outbuf,smb_vwv10, mode);
4270 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4272 END_PROFILE(SMBgetattrE);