SMBlockingX timeouts are in units of 2 milliseconds, not 1
[Samba/bb.git] / source / smbd / reply.c
blobbe51a328911e3c0ab859f2d67fb01e27eb9cab1f
1 /*
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
26 #include "includes.h"
28 /* look in server.c for some explanation of these variables */
29 extern int Protocol;
30 extern int max_send;
31 extern int max_recv;
32 extern char magic_char;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
36 extern int global_oplock_break;
37 unsigned int smb_echo_count = 0;
39 extern BOOL global_encrypted_passwords_negotiated;
41 /****************************************************************************
42 Reply to an special message.
43 ****************************************************************************/
45 int reply_special(char *inbuf,char *outbuf)
47 int outsize = 4;
48 int msg_type = CVAL(inbuf,0);
49 int msg_flags = CVAL(inbuf,1);
50 pstring name1,name2;
52 int len;
53 char name_type = 0;
55 static BOOL already_got_session = False;
57 *name1 = *name2 = 0;
59 memset(outbuf,'\0',smb_size);
61 smb_setlen(outbuf,0);
63 switch (msg_type) {
64 case 0x81: /* session request */
66 if (already_got_session) {
67 exit_server("multiple session request not permitted");
70 SCVAL(outbuf,0,0x82);
71 SCVAL(outbuf,3,0);
72 if (name_len(inbuf+4) > 50 ||
73 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
74 DEBUG(0,("Invalid name length in session request\n"));
75 return(0);
77 name_extract(inbuf,4,name1);
78 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
79 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
80 name1,name2));
82 name1[15] = 0;
84 len = strlen(name2);
85 if (len == 16) {
86 name_type = name2[15];
87 name2[15] = 0;
90 set_local_machine_name(name1, True);
91 set_remote_machine_name(name2, True);
93 DEBUG(2,("netbios connect: local=%s remote=%s\n",
94 get_local_machine_name(), get_remote_machine_name() ));
96 if (name_type == 'R') {
97 /* We are being asked for a pathworks session ---
98 no thanks! */
99 SCVAL(outbuf, 0,0x83);
100 break;
103 /* only add the client's machine name to the list
104 of possibly valid usernames if we are operating
105 in share mode security */
106 if (lp_security() == SEC_SHARE) {
107 add_session_user(get_remote_machine_name());
110 reload_services(True);
111 reopen_logs();
113 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
115 already_got_session = True;
116 break;
118 case 0x89: /* session keepalive request
119 (some old clients produce this?) */
120 SCVAL(outbuf,0,SMBkeepalive);
121 SCVAL(outbuf,3,0);
122 break;
124 case 0x82: /* positive session response */
125 case 0x83: /* negative session response */
126 case 0x84: /* retarget session response */
127 DEBUG(0,("Unexpected session response\n"));
128 break;
130 case SMBkeepalive: /* session keepalive */
131 default:
132 return(0);
135 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
136 msg_type, msg_flags));
138 return(outsize);
141 /****************************************************************************
142 Reply to a tcon.
143 ****************************************************************************/
145 int reply_tcon(connection_struct *conn,
146 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
148 const char *service;
149 pstring service_buf;
150 pstring password;
151 pstring dev;
152 int outsize = 0;
153 uint16 vuid = SVAL(inbuf,smb_uid);
154 int pwlen=0;
155 NTSTATUS nt_status;
156 char *p;
157 DATA_BLOB password_blob;
159 START_PROFILE(SMBtcon);
161 *service_buf = *password = *dev = 0;
163 p = smb_buf(inbuf)+1;
164 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
165 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
166 p += pwlen;
167 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
169 p = strrchr_m(service_buf,'\\');
170 if (p) {
171 service = p+1;
172 } else {
173 service = service_buf;
176 password_blob = data_blob(password, pwlen+1);
178 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
180 data_blob_clear_free(&password_blob);
182 if (!conn) {
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);
196 return(outsize);
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)
205 fstring service;
206 DATA_BLOB password;
208 /* what the cleint thinks the device is */
209 fstring client_devicetype;
210 /* what the server tells the client the share represents */
211 const char *server_devicetype;
212 NTSTATUS nt_status;
213 uint16 vuid = SVAL(inbuf,smb_uid);
214 int passlen = SVAL(inbuf,smb_vwv3);
215 pstring path;
216 char *p, *q;
217 extern BOOL global_encrypted_passwords_negotiated;
219 START_PROFILE(SMBtconX);
221 *service = *client_devicetype = 0;
223 /* we might have to close an old one */
224 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
225 close_cnum(conn,vuid);
228 if (passlen > MAX_PASS_LEN) {
229 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
232 if (global_encrypted_passwords_negotiated) {
233 password = data_blob(smb_buf(inbuf),passlen);
234 } else {
235 password = data_blob(smb_buf(inbuf),passlen+1);
236 /* Ensure correct termination */
237 password.data[passlen]=0;
240 p = smb_buf(inbuf) + passlen;
241 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
244 * the service name can be either: \\server\share
245 * or share directly like on the DELL PowerVault 705
247 if (*path=='\\') {
248 q = strchr_m(path+2,'\\');
249 if (!q) {
250 END_PROFILE(SMBtconX);
251 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
253 fstrcpy(service,q+1);
255 else
256 fstrcpy(service,path);
258 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
260 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
262 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
264 data_blob_clear_free(&password);
266 if (!conn) {
267 END_PROFILE(SMBtconX);
268 return ERROR_NT(nt_status);
271 if ( IS_IPC(conn) )
272 server_devicetype = "IPC";
273 else if ( IS_PRINT(conn) )
274 server_devicetype = "LPT1:";
275 else
276 server_devicetype = "A:";
278 if (Protocol < PROTOCOL_NT1) {
279 set_message(outbuf,2,0,True);
280 p = smb_buf(outbuf);
281 p += srvstr_push(outbuf, p, server_devicetype, -1,
282 STR_TERMINATE|STR_ASCII);
283 set_message_end(outbuf,p);
284 } else {
285 /* NT sets the fstype of IPC$ to the null string */
286 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
288 set_message(outbuf,3,0,True);
290 p = smb_buf(outbuf);
291 p += srvstr_push(outbuf, p, server_devicetype, -1,
292 STR_TERMINATE|STR_ASCII);
293 p += srvstr_push(outbuf, p, fstype, -1,
294 STR_TERMINATE);
296 set_message_end(outbuf,p);
298 /* what does setting this bit do? It is set by NT4 and
299 may affect the ability to autorun mounted cdroms */
300 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
301 (lp_csc_policy(SNUM(conn)) << 2));
303 init_dfsroot(conn, inbuf, outbuf);
307 DEBUG(3,("tconX service=%s \n",
308 service));
310 /* set the incoming and outgoing tid to the just created one */
311 SSVAL(inbuf,smb_tid,conn->cnum);
312 SSVAL(outbuf,smb_tid,conn->cnum);
314 END_PROFILE(SMBtconX);
315 return chain_reply(inbuf,outbuf,length,bufsize);
318 /****************************************************************************
319 Reply to an unknown type.
320 ****************************************************************************/
322 int reply_unknown(char *inbuf,char *outbuf)
324 int type;
325 type = CVAL(inbuf,smb_com);
327 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
328 smb_fn_name(type), type, type));
330 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
333 /****************************************************************************
334 Reply to an ioctl.
335 ****************************************************************************/
337 int reply_ioctl(connection_struct *conn,
338 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
340 uint16 device = SVAL(inbuf,smb_vwv1);
341 uint16 function = SVAL(inbuf,smb_vwv2);
342 uint32 ioctl_code = (device << 16) + function;
343 int replysize, outsize;
344 char *p;
345 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
346 START_PROFILE(SMBioctl);
348 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
350 switch (ioctl_code) {
351 case IOCTL_QUERY_JOB_INFO:
352 replysize = 32;
353 break;
354 default:
355 END_PROFILE(SMBioctl);
356 return(ERROR_DOS(ERRSRV,ERRnosupport));
359 outsize = set_message(outbuf,8,replysize+1,True);
360 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
361 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
362 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
363 p = smb_buf(outbuf) + 1; /* Allow for alignment */
365 switch (ioctl_code) {
366 case IOCTL_QUERY_JOB_INFO:
368 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
369 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
370 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
371 break;
375 END_PROFILE(SMBioctl);
376 return outsize;
379 /****************************************************************************
380 Reply to a chkpth.
381 ****************************************************************************/
383 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
385 int outsize = 0;
386 int mode;
387 pstring name;
388 BOOL ok = False;
389 BOOL bad_path = False;
390 SMB_STRUCT_STAT sbuf;
391 START_PROFILE(SMBchkpth);
393 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
395 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
397 unix_convert(name,conn,0,&bad_path,&sbuf);
399 mode = SVAL(inbuf,smb_vwv0);
401 if (check_name(name,conn)) {
402 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
403 if (!(ok = S_ISDIR(sbuf.st_mode)))
404 errno = ENOTDIR;
407 if (!ok) {
408 /* We special case this - as when a Windows machine
409 is parsing a path is steps through the components
410 one at a time - if a component fails it expects
411 ERRbadpath, not ERRbadfile.
413 if(errno == ENOENT)
414 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
416 return(UNIXERROR(ERRDOS,ERRbadpath));
419 outsize = set_message(outbuf,0,0,True);
421 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
423 END_PROFILE(SMBchkpth);
424 return(outsize);
427 /****************************************************************************
428 Reply to a getatr.
429 ****************************************************************************/
431 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
433 pstring fname;
434 int outsize = 0;
435 SMB_STRUCT_STAT sbuf;
436 BOOL ok = False;
437 int mode=0;
438 SMB_OFF_T size=0;
439 time_t mtime=0;
440 BOOL bad_path = False;
441 char *p;
442 START_PROFILE(SMBgetatr);
444 p = smb_buf(inbuf) + 1;
445 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
447 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
449 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
450 under WfWg - weird! */
451 if (! (*fname)) {
452 mode = aHIDDEN | aDIR;
453 if (!CAN_WRITE(conn))
454 mode |= aRONLY;
455 size = 0;
456 mtime = 0;
457 ok = True;
458 } else {
459 unix_convert(fname,conn,0,&bad_path,&sbuf);
460 if (check_name(fname,conn)) {
461 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
462 mode = dos_mode(conn,fname,&sbuf);
463 size = sbuf.st_size;
464 mtime = sbuf.st_mtime;
465 if (mode & aDIR)
466 size = 0;
467 ok = True;
468 } else {
469 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
474 if (!ok) {
475 set_bad_path_error(errno, bad_path);
476 END_PROFILE(SMBgetatr);
477 return(UNIXERROR(ERRDOS,ERRbadfile));
480 outsize = set_message(outbuf,10,0,True);
482 SSVAL(outbuf,smb_vwv0,mode);
483 if(lp_dos_filetime_resolution(SNUM(conn)) )
484 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
485 else
486 put_dos_date3(outbuf,smb_vwv1,mtime);
487 SIVAL(outbuf,smb_vwv3,(uint32)size);
489 if (Protocol >= PROTOCOL_NT1)
490 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
492 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
494 END_PROFILE(SMBgetatr);
495 return(outsize);
498 /****************************************************************************
499 Reply to a setatr.
500 ****************************************************************************/
502 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
504 pstring fname;
505 int outsize = 0;
506 BOOL ok=False;
507 int mode;
508 time_t mtime;
509 SMB_STRUCT_STAT sbuf;
510 BOOL bad_path = False;
511 char *p;
513 START_PROFILE(SMBsetatr);
515 p = smb_buf(inbuf) + 1;
516 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
517 unix_convert(fname,conn,0,&bad_path,&sbuf);
519 mode = SVAL(inbuf,smb_vwv0);
520 mtime = make_unix_date3(inbuf+smb_vwv1);
522 if (VALID_STAT_OF_DIR(sbuf))
523 mode |= aDIR;
524 else
525 mode &= ~aDIR;
527 if (check_name(fname,conn))
528 ok = (file_chmod(conn,fname,mode,NULL) == 0);
529 if (ok)
530 ok = set_filetime(conn,fname,mtime);
532 if (!ok) {
533 set_bad_path_error(errno, bad_path);
534 END_PROFILE(SMBsetatr);
535 return(UNIXERROR(ERRDOS,ERRnoaccess));
538 outsize = set_message(outbuf,0,0,True);
540 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
542 END_PROFILE(SMBsetatr);
543 return(outsize);
546 /****************************************************************************
547 Reply to a dskattr.
548 ****************************************************************************/
550 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
552 int outsize = 0;
553 SMB_BIG_UINT dfree,dsize,bsize;
554 START_PROFILE(SMBdskattr);
556 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
558 outsize = set_message(outbuf,5,0,True);
560 if (Protocol <= PROTOCOL_LANMAN2) {
561 double total_space, free_space;
562 /* we need to scale this to a number that DOS6 can handle. We
563 use floating point so we can handle large drives on systems
564 that don't have 64 bit integers
566 we end up displaying a maximum of 2G to DOS systems
568 total_space = dsize * (double)bsize;
569 free_space = dfree * (double)bsize;
571 dsize = (total_space+63*512) / (64*512);
572 dfree = (free_space+63*512) / (64*512);
574 if (dsize > 0xFFFF) dsize = 0xFFFF;
575 if (dfree > 0xFFFF) dfree = 0xFFFF;
577 SSVAL(outbuf,smb_vwv0,dsize);
578 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
579 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
580 SSVAL(outbuf,smb_vwv3,dfree);
581 } else {
582 SSVAL(outbuf,smb_vwv0,dsize);
583 SSVAL(outbuf,smb_vwv1,bsize/512);
584 SSVAL(outbuf,smb_vwv2,512);
585 SSVAL(outbuf,smb_vwv3,dfree);
588 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
590 END_PROFILE(SMBdskattr);
591 return(outsize);
594 /****************************************************************************
595 Reply to a search.
596 Can be called from SMBsearch, SMBffirst or SMBfunique.
597 ****************************************************************************/
599 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
601 pstring mask;
602 pstring directory;
603 pstring fname;
604 SMB_OFF_T size;
605 int mode;
606 time_t date;
607 int dirtype;
608 int outsize = 0;
609 int numentries = 0;
610 BOOL finished = False;
611 int maxentries;
612 int i;
613 char *p;
614 BOOL ok = False;
615 int status_len;
616 pstring path;
617 char status[21];
618 int dptr_num= -1;
619 BOOL check_descend = False;
620 BOOL expect_close = False;
621 BOOL can_open = True;
622 BOOL bad_path = False;
623 START_PROFILE(SMBsearch);
625 *mask = *directory = *fname = 0;
627 /* If we were called as SMBffirst then we must expect close. */
628 if(CVAL(inbuf,smb_com) == SMBffirst)
629 expect_close = True;
631 outsize = set_message(outbuf,1,3,True);
632 maxentries = SVAL(inbuf,smb_vwv0);
633 dirtype = SVAL(inbuf,smb_vwv1);
634 p = smb_buf(inbuf) + 1;
635 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
636 p++;
637 status_len = SVAL(p, 0);
638 p += 2;
640 /* dirtype &= ~aDIR; */
642 if (status_len == 0) {
643 SMB_STRUCT_STAT sbuf;
644 pstring dir2;
646 pstrcpy(directory,path);
647 pstrcpy(dir2,path);
648 unix_convert(directory,conn,0,&bad_path,&sbuf);
649 unix_format(dir2);
651 if (!check_name(directory,conn))
652 can_open = False;
654 p = strrchr_m(dir2,'/');
655 if (p == NULL) {
656 pstrcpy(mask,dir2);
657 *dir2 = 0;
658 } else {
659 *p = 0;
660 pstrcpy(mask,p+1);
663 p = strrchr_m(directory,'/');
664 if (!p)
665 *directory = 0;
666 else
667 *p = 0;
669 if (strlen(directory) == 0)
670 pstrcpy(directory,".");
671 memset((char *)status,'\0',21);
672 SCVAL(status,0,(dirtype & 0x1F));
673 } else {
674 int status_dirtype;
676 memcpy(status,p,21);
677 status_dirtype = CVAL(status,0) & 0x1F;
678 if (status_dirtype != (dirtype & 0x1F))
679 dirtype = status_dirtype;
681 conn->dirptr = dptr_fetch(status+12,&dptr_num);
682 if (!conn->dirptr)
683 goto SearchEmpty;
684 string_set(&conn->dirpath,dptr_path(dptr_num));
685 pstrcpy(mask, dptr_wcard(dptr_num));
688 if (can_open) {
689 p = smb_buf(outbuf) + 3;
690 ok = True;
692 if (status_len == 0) {
693 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
694 if (dptr_num < 0) {
695 if(dptr_num == -2) {
696 set_bad_path_error(errno, bad_path);
697 END_PROFILE(SMBsearch);
698 return (UNIXERROR(ERRDOS,ERRnofids));
700 END_PROFILE(SMBsearch);
701 return ERROR_DOS(ERRDOS,ERRnofids);
703 dptr_set_wcard(dptr_num, strdup(mask));
704 dptr_set_attr(dptr_num, dirtype);
705 } else {
706 dirtype = dptr_attr(dptr_num);
709 DEBUG(4,("dptr_num is %d\n",dptr_num));
711 if (ok) {
712 if ((dirtype&0x1F) == aVOLID) {
713 memcpy(p,status,21);
714 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
715 dptr_fill(p+12,dptr_num);
716 if (dptr_zero(p+12) && (status_len==0))
717 numentries = 1;
718 else
719 numentries = 0;
720 p += DIR_STRUCT_SIZE;
721 } else {
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++) {
728 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
729 if (!finished) {
730 memcpy(p,status,21);
731 make_dir_struct(p,mask,fname,size,mode,date);
732 dptr_fill(p+12,dptr_num);
733 numentries++;
735 p += DIR_STRUCT_SIZE;
738 } /* if (ok ) */
742 SearchEmpty:
744 if (numentries == 0 || !ok) {
745 SCVAL(outbuf,smb_rcls,ERRDOS);
746 SSVAL(outbuf,smb_err,ERRnofiles);
747 dptr_close(&dptr_num);
750 /* If we were called as SMBffirst with smb_search_id == NULL
751 and no entries were found then return error and close dirptr
752 (X/Open spec) */
754 if(ok && expect_close && numentries == 0 && status_len == 0) {
755 SCVAL(outbuf,smb_rcls,ERRDOS);
756 SSVAL(outbuf,smb_err,ERRnofiles);
757 /* Also close the dptr - we know it's gone */
758 dptr_close(&dptr_num);
761 /* If we were called as SMBfunique, then we can close the dirptr now ! */
762 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
763 dptr_close(&dptr_num);
765 SSVAL(outbuf,smb_vwv0,numentries);
766 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
767 SCVAL(smb_buf(outbuf),0,5);
768 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
770 if (Protocol >= PROTOCOL_NT1)
771 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
773 outsize += DIR_STRUCT_SIZE*numentries;
774 smb_setlen(outbuf,outsize - 4);
776 if ((! *directory) && dptr_path(dptr_num))
777 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
779 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
780 smb_fn_name(CVAL(inbuf,smb_com)),
781 mask, directory, dirtype, numentries, maxentries ) );
783 END_PROFILE(SMBsearch);
784 return(outsize);
787 /****************************************************************************
788 Reply to a fclose (stop directory search).
789 ****************************************************************************/
791 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
793 int outsize = 0;
794 int status_len;
795 pstring path;
796 char status[21];
797 int dptr_num= -2;
798 char *p;
800 START_PROFILE(SMBfclose);
802 outsize = set_message(outbuf,1,0,True);
803 p = smb_buf(inbuf) + 1;
804 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
805 p++;
806 status_len = SVAL(p,0);
807 p += 2;
809 if (status_len == 0) {
810 END_PROFILE(SMBfclose);
811 return ERROR_DOS(ERRSRV,ERRsrverror);
814 memcpy(status,p,21);
816 if(dptr_fetch(status+12,&dptr_num)) {
817 /* Close the dptr - we know it's gone */
818 dptr_close(&dptr_num);
821 SSVAL(outbuf,smb_vwv0,0);
823 DEBUG(3,("search close\n"));
825 END_PROFILE(SMBfclose);
826 return(outsize);
829 /****************************************************************************
830 Reply to an open.
831 ****************************************************************************/
833 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
835 pstring fname;
836 int outsize = 0;
837 int fmode=0;
838 int share_mode;
839 SMB_OFF_T size = 0;
840 time_t mtime=0;
841 mode_t unixmode;
842 int rmode=0;
843 SMB_STRUCT_STAT sbuf;
844 BOOL bad_path = False;
845 files_struct *fsp;
846 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
847 START_PROFILE(SMBopen);
849 share_mode = SVAL(inbuf,smb_vwv0);
851 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
853 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
855 unix_convert(fname,conn,0,&bad_path,&sbuf);
857 unixmode = unix_mode(conn,aARCH,fname);
859 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
860 unixmode, oplock_request,&rmode,NULL);
862 if (!fsp) {
863 set_bad_path_error(errno, bad_path);
864 END_PROFILE(SMBopen);
865 return(UNIXERROR(ERRDOS,ERRnoaccess));
868 size = sbuf.st_size;
869 fmode = dos_mode(conn,fname,&sbuf);
870 mtime = sbuf.st_mtime;
872 if (fmode & aDIR) {
873 DEBUG(3,("attempt to open a directory %s\n",fname));
874 close_file(fsp,False);
875 END_PROFILE(SMBopen);
876 return ERROR_DOS(ERRDOS,ERRnoaccess);
879 outsize = set_message(outbuf,7,0,True);
880 SSVAL(outbuf,smb_vwv0,fsp->fnum);
881 SSVAL(outbuf,smb_vwv1,fmode);
882 if(lp_dos_filetime_resolution(SNUM(conn)) )
883 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
884 else
885 put_dos_date3(outbuf,smb_vwv2,mtime);
886 SIVAL(outbuf,smb_vwv4,(uint32)size);
887 SSVAL(outbuf,smb_vwv6,rmode);
889 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
890 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
892 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
893 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
894 END_PROFILE(SMBopen);
895 return(outsize);
898 /****************************************************************************
899 Reply to an open and X.
900 ****************************************************************************/
902 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
904 pstring fname;
905 int smb_mode = SVAL(inbuf,smb_vwv3);
906 int smb_attr = SVAL(inbuf,smb_vwv5);
907 /* Breakout the oplock request bits so we can set the
908 reply bits separately. */
909 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
910 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
911 BOOL oplock_request = ex_oplock_request | core_oplock_request;
912 #if 0
913 int open_flags = SVAL(inbuf,smb_vwv2);
914 int smb_sattr = SVAL(inbuf,smb_vwv4);
915 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
916 #endif
917 int smb_ofun = SVAL(inbuf,smb_vwv8);
918 mode_t unixmode;
919 SMB_OFF_T size=0;
920 int fmode=0,mtime=0,rmode=0;
921 SMB_STRUCT_STAT sbuf;
922 int smb_action = 0;
923 BOOL bad_path = False;
924 files_struct *fsp;
925 START_PROFILE(SMBopenX);
927 /* If it's an IPC, pass off the pipe handler. */
928 if (IS_IPC(conn)) {
929 if (lp_nt_pipe_support()) {
930 END_PROFILE(SMBopenX);
931 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
932 } else {
933 END_PROFILE(SMBopenX);
934 return ERROR_DOS(ERRSRV,ERRaccess);
938 /* XXXX we need to handle passed times, sattr and flags */
939 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
941 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
943 unix_convert(fname,conn,0,&bad_path,&sbuf);
945 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
947 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
948 oplock_request, &rmode,&smb_action);
950 if (!fsp) {
951 set_bad_path_error(errno, bad_path);
952 END_PROFILE(SMBopenX);
953 return(UNIXERROR(ERRDOS,ERRnoaccess));
956 size = sbuf.st_size;
957 fmode = dos_mode(conn,fname,&sbuf);
958 mtime = sbuf.st_mtime;
959 if (fmode & aDIR) {
960 close_file(fsp,False);
961 END_PROFILE(SMBopenX);
962 return ERROR_DOS(ERRDOS,ERRnoaccess);
965 /* If the caller set the extended oplock request bit
966 and we granted one (by whatever means) - set the
967 correct bit for extended oplock reply.
970 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
971 smb_action |= EXTENDED_OPLOCK_GRANTED;
973 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
974 smb_action |= EXTENDED_OPLOCK_GRANTED;
976 /* If the caller set the core oplock request bit
977 and we granted one (by whatever means) - set the
978 correct bit for core oplock reply.
981 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
982 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
984 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
985 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
987 set_message(outbuf,15,0,True);
988 SSVAL(outbuf,smb_vwv2,fsp->fnum);
989 SSVAL(outbuf,smb_vwv3,fmode);
990 if(lp_dos_filetime_resolution(SNUM(conn)) )
991 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
992 else
993 put_dos_date3(outbuf,smb_vwv4,mtime);
994 SIVAL(outbuf,smb_vwv6,(uint32)size);
995 SSVAL(outbuf,smb_vwv8,rmode);
996 SSVAL(outbuf,smb_vwv11,smb_action);
998 END_PROFILE(SMBopenX);
999 return chain_reply(inbuf,outbuf,length,bufsize);
1002 /****************************************************************************
1003 Reply to a SMBulogoffX.
1004 ****************************************************************************/
1006 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1008 uint16 vuid = SVAL(inbuf,smb_uid);
1009 user_struct *vuser = get_valid_user_struct(vuid);
1010 START_PROFILE(SMBulogoffX);
1012 if(vuser == 0)
1013 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1015 /* in user level security we are supposed to close any files
1016 open by this user */
1017 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1018 file_close_user(vuid);
1020 invalidate_vuid(vuid);
1022 set_message(outbuf,2,0,True);
1024 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1026 END_PROFILE(SMBulogoffX);
1027 return chain_reply(inbuf,outbuf,length,bufsize);
1030 /****************************************************************************
1031 Reply to a mknew or a create.
1032 ****************************************************************************/
1034 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1036 pstring fname;
1037 int com;
1038 int outsize = 0;
1039 int createmode;
1040 mode_t unixmode;
1041 int ofun = 0;
1042 BOOL bad_path = False;
1043 files_struct *fsp;
1044 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1045 SMB_STRUCT_STAT sbuf;
1046 START_PROFILE(SMBcreate);
1048 com = SVAL(inbuf,smb_com);
1050 createmode = SVAL(inbuf,smb_vwv0);
1051 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
1053 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1055 unix_convert(fname,conn,0,&bad_path,&sbuf);
1057 if (createmode & aVOLID)
1058 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1060 unixmode = unix_mode(conn,createmode,fname);
1062 if(com == SMBmknew) {
1063 /* We should fail if file exists. */
1064 ofun = FILE_CREATE_IF_NOT_EXIST;
1065 } else {
1066 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1067 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1070 /* Open file in dos compatibility share mode. */
1071 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1072 ofun, unixmode, oplock_request, NULL, NULL);
1074 if (!fsp) {
1075 set_bad_path_error(errno, bad_path);
1076 END_PROFILE(SMBcreate);
1077 return(UNIXERROR(ERRDOS,ERRnoaccess));
1080 outsize = set_message(outbuf,1,0,True);
1081 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1083 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1084 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1086 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1087 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1089 DEBUG( 2, ( "new file %s\n", fname ) );
1090 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1092 END_PROFILE(SMBcreate);
1093 return(outsize);
1096 /****************************************************************************
1097 Reply to a create temporary file.
1098 ****************************************************************************/
1100 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1102 pstring fname;
1103 int outsize = 0;
1104 int createmode;
1105 mode_t unixmode;
1106 BOOL bad_path = False;
1107 files_struct *fsp;
1108 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1109 int tmpfd;
1110 SMB_STRUCT_STAT sbuf;
1111 char *p, *s;
1113 START_PROFILE(SMBctemp);
1115 createmode = SVAL(inbuf,smb_vwv0);
1116 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1117 pstrcat(fname,"\\TMXXXXXX");
1119 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1121 unix_convert(fname,conn,0,&bad_path,&sbuf);
1123 unixmode = unix_mode(conn,createmode,fname);
1125 tmpfd = smb_mkstemp(fname);
1126 if (tmpfd == -1) {
1127 END_PROFILE(SMBctemp);
1128 return(UNIXERROR(ERRDOS,ERRnoaccess));
1131 SMB_VFS_STAT(conn,fname,&sbuf);
1133 /* Open file in dos compatibility share mode. */
1134 /* We should fail if file does not exist. */
1135 fsp = open_file_shared(conn,fname,&sbuf,
1136 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1137 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1138 unixmode, oplock_request, NULL, NULL);
1140 /* close fd from smb_mkstemp() */
1141 close(tmpfd);
1143 if (!fsp) {
1144 set_bad_path_error(errno, bad_path);
1145 END_PROFILE(SMBctemp);
1146 return(UNIXERROR(ERRDOS,ERRnoaccess));
1149 outsize = set_message(outbuf,1,0,True);
1150 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1152 /* the returned filename is relative to the directory */
1153 s = strrchr_m(fname, '/');
1154 if (!s)
1155 s = fname;
1156 else
1157 s++;
1159 p = smb_buf(outbuf);
1160 SSVALS(p, 0, -1); /* what is this? not in spec */
1161 SSVAL(p, 2, strlen(s));
1162 p += 4;
1163 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1164 outsize = set_message_end(outbuf, p);
1166 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1167 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1169 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1170 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1172 DEBUG( 2, ( "created temp file %s\n", fname ) );
1173 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1174 fname, fsp->fd, createmode, (int)unixmode ) );
1176 END_PROFILE(SMBctemp);
1177 return(outsize);
1180 /*******************************************************************
1181 Check if a user is allowed to rename a file.
1182 ********************************************************************/
1184 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1186 int smb_action;
1187 int access_mode;
1188 files_struct *fsp;
1190 if (!CAN_WRITE(conn))
1191 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1193 if (S_ISDIR(pst->st_mode))
1194 return NT_STATUS_OK;
1196 /* We need a better way to return NT status codes from open... */
1197 unix_ERR_class = 0;
1198 unix_ERR_code = 0;
1200 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1201 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1203 if (!fsp) {
1204 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1205 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1206 ret = NT_STATUS_SHARING_VIOLATION;
1207 unix_ERR_class = 0;
1208 unix_ERR_code = 0;
1209 return ret;
1211 close_file(fsp,False);
1212 return NT_STATUS_OK;
1215 /*******************************************************************
1216 Check if a user is allowed to delete a file.
1217 ********************************************************************/
1219 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1221 SMB_STRUCT_STAT sbuf;
1222 int fmode;
1223 int smb_action;
1224 int access_mode;
1225 files_struct *fsp;
1227 if (!CAN_WRITE(conn))
1228 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1230 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0)
1231 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1233 fmode = dos_mode(conn,fname,&sbuf);
1234 if (fmode & aDIR)
1235 return NT_STATUS_FILE_IS_A_DIRECTORY;
1236 if (!lp_delete_readonly(SNUM(conn))) {
1237 if (fmode & aRONLY)
1238 return NT_STATUS_CANNOT_DELETE;
1240 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1241 return NT_STATUS_CANNOT_DELETE;
1243 /* We need a better way to return NT status codes from open... */
1244 unix_ERR_class = 0;
1245 unix_ERR_code = 0;
1247 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1248 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1250 if (!fsp) {
1251 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1252 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1253 ret = unix_ERR_ntstatus;
1254 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1255 ret = NT_STATUS_SHARING_VIOLATION;
1256 unix_ERR_class = 0;
1257 unix_ERR_code = 0;
1258 unix_ERR_ntstatus = NT_STATUS_OK;
1259 return ret;
1261 close_file(fsp,False);
1262 return NT_STATUS_OK;
1265 /****************************************************************************
1266 The guts of the unlink command, split out so it may be called by the NT SMB
1267 code.
1268 ****************************************************************************/
1270 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1272 pstring directory;
1273 pstring mask;
1274 char *p;
1275 int count=0;
1276 NTSTATUS error = NT_STATUS_OK;
1277 BOOL has_wild;
1278 BOOL bad_path = False;
1279 BOOL rc = True;
1280 SMB_STRUCT_STAT sbuf;
1282 *directory = *mask = 0;
1284 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1286 p = strrchr_m(name,'/');
1287 if (!p) {
1288 pstrcpy(directory,".");
1289 pstrcpy(mask,name);
1290 } else {
1291 *p = 0;
1292 pstrcpy(directory,name);
1293 pstrcpy(mask,p+1);
1297 * We should only check the mangled cache
1298 * here if unix_convert failed. This means
1299 * that the path in 'mask' doesn't exist
1300 * on the file system and so we need to look
1301 * for a possible mangle. This patch from
1302 * Tine Smukavec <valentin.smukavec@hermes.si>.
1305 if (!rc && mangle_is_mangled(mask))
1306 mangle_check_cache( mask );
1308 has_wild = ms_has_wild(mask);
1310 if (!has_wild) {
1311 pstrcat(directory,"/");
1312 pstrcat(directory,mask);
1313 error = can_delete(directory,conn,dirtype);
1314 if (!NT_STATUS_IS_OK(error)) return error;
1316 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1317 count++;
1319 } else {
1320 void *dirptr = NULL;
1321 const char *dname;
1323 if (check_name(directory,conn))
1324 dirptr = OpenDir(conn, directory, True);
1326 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1327 the pattern matches against the long name, otherwise the short name
1328 We don't implement this yet XXXX
1331 if (dirptr) {
1332 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1334 if (strequal(mask,"????????.???"))
1335 pstrcpy(mask,"*");
1337 while ((dname = ReadDirName(dirptr))) {
1338 pstring fname;
1339 pstrcpy(fname,dname);
1341 if(!mask_match(fname, mask, case_sensitive)) continue;
1343 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1344 error = can_delete(fname,conn,dirtype);
1345 if (!NT_STATUS_IS_OK(error)) continue;
1346 if (SMB_VFS_UNLINK(conn,fname) == 0) count++;
1347 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1349 CloseDir(dirptr);
1353 if (count == 0 && NT_STATUS_IS_OK(error)) {
1354 error = map_nt_error_from_unix(errno);
1357 return error;
1360 /****************************************************************************
1361 Reply to a unlink
1362 ****************************************************************************/
1364 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1365 int dum_buffsize)
1367 int outsize = 0;
1368 pstring name;
1369 int dirtype;
1370 NTSTATUS status;
1371 START_PROFILE(SMBunlink);
1373 dirtype = SVAL(inbuf,smb_vwv0);
1375 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1377 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1379 DEBUG(3,("reply_unlink : %s\n",name));
1381 status = unlink_internals(conn, dirtype, name);
1382 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1385 * Win2k needs a changenotify request response before it will
1386 * update after a rename..
1388 process_pending_change_notify_queue((time_t)0);
1390 outsize = set_message(outbuf,0,0,True);
1392 END_PROFILE(SMBunlink);
1393 return outsize;
1396 /****************************************************************************
1397 Fail for readbraw.
1398 ****************************************************************************/
1400 void fail_readraw(void)
1402 pstring errstr;
1403 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1404 strerror(errno) );
1405 exit_server(errstr);
1408 /****************************************************************************
1409 Use sendfile in readbraw.
1410 ****************************************************************************/
1412 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1413 ssize_t mincount, char *outbuf)
1415 ssize_t ret=0;
1417 #if defined(WITH_SENDFILE)
1419 * We can only use sendfile on a non-chained packet and on a file
1420 * that is exclusively oplocked. reply_readbraw has already checked the length.
1423 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1424 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1425 DATA_BLOB header;
1427 _smb_setlen(outbuf,nread);
1428 header.data = outbuf;
1429 header.length = 4;
1430 header.free = NULL;
1432 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1434 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1435 * return ENOSYS then pretend we just got a normal read.
1437 if (errno == ENOSYS)
1438 goto normal_read;
1440 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1441 fsp->fsp_name, strerror(errno) ));
1442 exit_server("send_file_readbraw sendfile failed");
1447 normal_read:
1448 #endif
1450 if (nread > 0) {
1451 ret = read_file(fsp,outbuf+4,startpos,nread);
1452 if (ret < mincount)
1453 ret = 0;
1456 _smb_setlen(outbuf,ret);
1457 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1458 fail_readraw();
1461 /****************************************************************************
1462 Reply to a readbraw (core+ protocol).
1463 ****************************************************************************/
1465 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1467 extern struct current_user current_user;
1468 ssize_t maxcount,mincount;
1469 size_t nread = 0;
1470 SMB_OFF_T startpos;
1471 char *header = outbuf;
1472 files_struct *fsp;
1473 START_PROFILE(SMBreadbraw);
1476 * Special check if an oplock break has been issued
1477 * and the readraw request croses on the wire, we must
1478 * return a zero length response here.
1481 if(global_oplock_break) {
1482 _smb_setlen(header,0);
1483 if (write_data(smbd_server_fd(),header,4) != 4)
1484 fail_readraw();
1485 DEBUG(5,("readbraw - oplock break finished\n"));
1486 END_PROFILE(SMBreadbraw);
1487 return -1;
1490 fsp = file_fsp(inbuf,smb_vwv0);
1492 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1494 * fsp could be NULL here so use the value from the packet. JRA.
1496 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1497 _smb_setlen(header,0);
1498 if (write_data(smbd_server_fd(),header,4) != 4)
1499 fail_readraw();
1500 END_PROFILE(SMBreadbraw);
1501 return(-1);
1504 CHECK_FSP(fsp,conn);
1506 flush_write_cache(fsp, READRAW_FLUSH);
1508 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1509 if(CVAL(inbuf,smb_wct) == 10) {
1511 * This is a large offset (64 bit) read.
1513 #ifdef LARGE_SMB_OFF_T
1515 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1517 #else /* !LARGE_SMB_OFF_T */
1520 * Ensure we haven't been sent a >32 bit offset.
1523 if(IVAL(inbuf,smb_vwv8) != 0) {
1524 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1525 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1526 _smb_setlen(header,0);
1527 if (write_data(smbd_server_fd(),header,4) != 4)
1528 fail_readraw();
1529 END_PROFILE(SMBreadbraw);
1530 return(-1);
1533 #endif /* LARGE_SMB_OFF_T */
1535 if(startpos < 0) {
1536 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1537 _smb_setlen(header,0);
1538 if (write_data(smbd_server_fd(),header,4) != 4)
1539 fail_readraw();
1540 END_PROFILE(SMBreadbraw);
1541 return(-1);
1544 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1545 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1547 /* ensure we don't overrun the packet size */
1548 maxcount = MIN(65535,maxcount);
1549 maxcount = MAX(mincount,maxcount);
1551 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1552 SMB_OFF_T size = fsp->size;
1553 SMB_OFF_T sizeneeded = startpos + maxcount;
1555 if (size < sizeneeded) {
1556 SMB_STRUCT_STAT st;
1557 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1558 size = st.st_size;
1559 if (!fsp->can_write)
1560 fsp->size = size;
1563 if (startpos >= size)
1564 nread = 0;
1565 else
1566 nread = MIN(maxcount,(size - startpos));
1569 if (nread < mincount)
1570 nread = 0;
1572 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1573 (int)maxcount, (int)mincount, (int)nread ) );
1575 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1577 DEBUG(5,("readbraw finished\n"));
1578 END_PROFILE(SMBreadbraw);
1579 return -1;
1582 /****************************************************************************
1583 Reply to a lockread (core+ protocol).
1584 ****************************************************************************/
1586 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1588 ssize_t nread = -1;
1589 char *data;
1590 int outsize = 0;
1591 SMB_OFF_T startpos;
1592 size_t numtoread;
1593 NTSTATUS status;
1594 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1595 START_PROFILE(SMBlockread);
1597 CHECK_FSP(fsp,conn);
1598 CHECK_READ(fsp);
1600 release_level_2_oplocks_on_change(fsp);
1602 numtoread = SVAL(inbuf,smb_vwv1);
1603 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1605 outsize = set_message(outbuf,5,3,True);
1606 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1607 data = smb_buf(outbuf) + 3;
1610 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1611 * protocol request that predates the read/write lock concept.
1612 * Thus instead of asking for a read lock here we need to ask
1613 * for a write lock. JRA.
1616 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1617 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1619 if (NT_STATUS_V(status)) {
1620 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
1622 * A blocking lock was requested. Package up
1623 * this smb into a queued request and push it
1624 * onto the blocking lock queue.
1626 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1627 (SMB_BIG_UINT)numtoread)) {
1628 END_PROFILE(SMBlockread);
1629 return -1;
1632 END_PROFILE(SMBlockread);
1633 return ERROR_NT(status);
1636 nread = read_file(fsp,data,startpos,numtoread);
1638 if (nread < 0) {
1639 END_PROFILE(SMBlockread);
1640 return(UNIXERROR(ERRDOS,ERRnoaccess));
1643 outsize += nread;
1644 SSVAL(outbuf,smb_vwv0,nread);
1645 SSVAL(outbuf,smb_vwv5,nread+3);
1646 SSVAL(smb_buf(outbuf),1,nread);
1648 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1649 fsp->fnum, (int)numtoread, (int)nread));
1651 END_PROFILE(SMBlockread);
1652 return(outsize);
1655 /****************************************************************************
1656 Reply to a read.
1657 ****************************************************************************/
1659 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1661 size_t numtoread;
1662 ssize_t nread = 0;
1663 char *data;
1664 SMB_OFF_T startpos;
1665 int outsize = 0;
1666 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1667 START_PROFILE(SMBread);
1669 CHECK_FSP(fsp,conn);
1670 CHECK_READ(fsp);
1672 numtoread = SVAL(inbuf,smb_vwv1);
1673 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1675 outsize = set_message(outbuf,5,3,True);
1676 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1677 data = smb_buf(outbuf) + 3;
1679 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1680 END_PROFILE(SMBread);
1681 return ERROR_DOS(ERRDOS,ERRlock);
1684 if (numtoread > 0)
1685 nread = read_file(fsp,data,startpos,numtoread);
1687 if (nread < 0) {
1688 END_PROFILE(SMBread);
1689 return(UNIXERROR(ERRDOS,ERRnoaccess));
1692 outsize += nread;
1693 SSVAL(outbuf,smb_vwv0,nread);
1694 SSVAL(outbuf,smb_vwv5,nread+3);
1695 SCVAL(smb_buf(outbuf),0,1);
1696 SSVAL(smb_buf(outbuf),1,nread);
1698 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1699 fsp->fnum, (int)numtoread, (int)nread ) );
1701 END_PROFILE(SMBread);
1702 return(outsize);
1705 /****************************************************************************
1706 Reply to a read and X - possibly using sendfile.
1707 ****************************************************************************/
1709 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1710 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1712 ssize_t nread = -1;
1713 char *data = smb_buf(outbuf);
1715 #if defined(WITH_SENDFILE)
1717 * We can only use sendfile on a non-chained packet and on a file
1718 * that is exclusively oplocked.
1721 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1722 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1723 SMB_STRUCT_STAT sbuf;
1724 DATA_BLOB header;
1726 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
1727 return(UNIXERROR(ERRDOS,ERRnoaccess));
1729 if (startpos > sbuf.st_size)
1730 goto normal_read;
1732 if (smb_maxcnt > (sbuf.st_size - startpos))
1733 smb_maxcnt = (sbuf.st_size - startpos);
1735 if (smb_maxcnt == 0)
1736 goto normal_read;
1739 * Set up the packet header before send. We
1740 * assume here the sendfile will work (get the
1741 * correct amount of data).
1744 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1745 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1746 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1747 SCVAL(outbuf,smb_vwv0,0xFF);
1748 set_message(outbuf,12,smb_maxcnt,False);
1749 header.data = outbuf;
1750 header.length = data - outbuf;
1751 header.free = NULL;
1753 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1755 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1756 * return ENOSYS then pretend we just got a normal read.
1758 if (errno == ENOSYS)
1759 goto normal_read;
1761 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1762 fsp->fsp_name, strerror(errno) ));
1763 exit_server("send_file_readX sendfile failed");
1766 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1767 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1768 return -1;
1771 normal_read:
1773 #endif
1775 nread = read_file(fsp,data,startpos,smb_maxcnt);
1777 if (nread < 0) {
1778 END_PROFILE(SMBreadX);
1779 return(UNIXERROR(ERRDOS,ERRnoaccess));
1782 SSVAL(outbuf,smb_vwv5,nread);
1783 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1784 SSVAL(smb_buf(outbuf),-2,nread);
1786 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1787 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1789 return nread;
1792 /****************************************************************************
1793 Reply to a read and X.
1794 ****************************************************************************/
1796 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1798 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1799 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1800 ssize_t nread = -1;
1801 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1802 #if 0
1803 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1804 #endif
1806 START_PROFILE(SMBreadX);
1808 /* If it's an IPC, pass off the pipe handler. */
1809 if (IS_IPC(conn)) {
1810 END_PROFILE(SMBreadX);
1811 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1814 CHECK_FSP(fsp,conn);
1815 CHECK_READ(fsp);
1817 set_message(outbuf,12,0,True);
1819 if(CVAL(inbuf,smb_wct) == 12) {
1820 #ifdef LARGE_SMB_OFF_T
1822 * This is a large offset (64 bit) read.
1824 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1826 #else /* !LARGE_SMB_OFF_T */
1829 * Ensure we haven't been sent a >32 bit offset.
1832 if(IVAL(inbuf,smb_vwv10) != 0) {
1833 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1834 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1835 END_PROFILE(SMBreadX);
1836 return ERROR_DOS(ERRDOS,ERRbadaccess);
1839 #endif /* LARGE_SMB_OFF_T */
1843 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1844 END_PROFILE(SMBreadX);
1845 return ERROR_DOS(ERRDOS,ERRlock);
1848 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
1849 if (nread != -1)
1850 nread = chain_reply(inbuf,outbuf,length,bufsize);
1852 END_PROFILE(SMBreadX);
1853 return nread;
1856 /****************************************************************************
1857 Reply to a writebraw (core+ or LANMAN1.0 protocol).
1858 ****************************************************************************/
1860 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1862 ssize_t nwritten=0;
1863 ssize_t total_written=0;
1864 size_t numtowrite=0;
1865 size_t tcount;
1866 SMB_OFF_T startpos;
1867 char *data=NULL;
1868 BOOL write_through;
1869 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1870 int outsize = 0;
1871 START_PROFILE(SMBwritebraw);
1873 CHECK_FSP(fsp,conn);
1874 CHECK_WRITE(fsp);
1876 tcount = IVAL(inbuf,smb_vwv1);
1877 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1878 write_through = BITSETW(inbuf+smb_vwv7,0);
1880 /* We have to deal with slightly different formats depending
1881 on whether we are using the core+ or lanman1.0 protocol */
1883 if(Protocol <= PROTOCOL_COREPLUS) {
1884 numtowrite = SVAL(smb_buf(inbuf),-2);
1885 data = smb_buf(inbuf);
1886 } else {
1887 numtowrite = SVAL(inbuf,smb_vwv10);
1888 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1891 /* force the error type */
1892 SCVAL(inbuf,smb_com,SMBwritec);
1893 SCVAL(outbuf,smb_com,SMBwritec);
1895 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1896 END_PROFILE(SMBwritebraw);
1897 return(ERROR_DOS(ERRDOS,ERRlock));
1900 if (numtowrite>0)
1901 nwritten = write_file(fsp,data,startpos,numtowrite);
1903 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1904 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1906 if (nwritten < (ssize_t)numtowrite) {
1907 END_PROFILE(SMBwritebraw);
1908 return(UNIXERROR(ERRHRD,ERRdiskfull));
1911 total_written = nwritten;
1913 /* Return a message to the redirector to tell it to send more bytes */
1914 SCVAL(outbuf,smb_com,SMBwritebraw);
1915 SSVALS(outbuf,smb_vwv0,-1);
1916 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1917 if (!send_smb(smbd_server_fd(),outbuf))
1918 exit_server("reply_writebraw: send_smb failed.");
1920 /* Now read the raw data into the buffer and write it */
1921 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1922 exit_server("secondary writebraw failed");
1925 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1926 numtowrite = smb_len(inbuf);
1928 /* Set up outbuf to return the correct return */
1929 outsize = set_message(outbuf,1,0,True);
1930 SCVAL(outbuf,smb_com,SMBwritec);
1931 SSVAL(outbuf,smb_vwv0,total_written);
1933 if (numtowrite != 0) {
1935 if (numtowrite > BUFFER_SIZE) {
1936 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1937 (unsigned int)numtowrite ));
1938 exit_server("secondary writebraw failed");
1941 if (tcount > nwritten+numtowrite) {
1942 DEBUG(3,("Client overestimated the write %d %d %d\n",
1943 (int)tcount,(int)nwritten,(int)numtowrite));
1946 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1947 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1948 strerror(errno) ));
1949 exit_server("secondary writebraw failed");
1952 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1954 if (nwritten < (ssize_t)numtowrite) {
1955 SCVAL(outbuf,smb_rcls,ERRHRD);
1956 SSVAL(outbuf,smb_err,ERRdiskfull);
1959 if (nwritten > 0)
1960 total_written += nwritten;
1963 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1964 sync_file(conn,fsp);
1966 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1967 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1969 /* we won't return a status if write through is not selected - this follows what WfWg does */
1970 END_PROFILE(SMBwritebraw);
1971 if (!write_through && total_written==tcount) {
1973 #if RABBIT_PELLET_FIX
1975 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
1976 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
1978 if (!send_keepalive(smbd_server_fd()))
1979 exit_server("reply_writebraw: send of keepalive failed");
1980 #endif
1981 return(-1);
1984 return(outsize);
1987 /****************************************************************************
1988 Reply to a writeunlock (core+).
1989 ****************************************************************************/
1991 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
1992 int size, int dum_buffsize)
1994 ssize_t nwritten = -1;
1995 size_t numtowrite;
1996 SMB_OFF_T startpos;
1997 char *data;
1998 NTSTATUS status;
1999 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2000 int outsize = 0;
2001 START_PROFILE(SMBwriteunlock);
2003 CHECK_FSP(fsp,conn);
2004 CHECK_WRITE(fsp);
2006 numtowrite = SVAL(inbuf,smb_vwv1);
2007 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2008 data = smb_buf(inbuf) + 3;
2010 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2011 WRITE_LOCK,False)) {
2012 END_PROFILE(SMBwriteunlock);
2013 return ERROR_DOS(ERRDOS,ERRlock);
2016 /* The special X/Open SMB protocol handling of
2017 zero length writes is *NOT* done for
2018 this call */
2019 if(numtowrite == 0)
2020 nwritten = 0;
2021 else
2022 nwritten = write_file(fsp,data,startpos,numtowrite);
2024 if (lp_syncalways(SNUM(conn)))
2025 sync_file(conn,fsp);
2027 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2028 END_PROFILE(SMBwriteunlock);
2029 return(UNIXERROR(ERRHRD,ERRdiskfull));
2032 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2033 (SMB_BIG_UINT)startpos);
2034 if (NT_STATUS_V(status)) {
2035 END_PROFILE(SMBwriteunlock);
2036 return ERROR_NT(status);
2039 outsize = set_message(outbuf,1,0,True);
2041 SSVAL(outbuf,smb_vwv0,nwritten);
2043 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2044 fsp->fnum, (int)numtowrite, (int)nwritten));
2046 END_PROFILE(SMBwriteunlock);
2047 return outsize;
2050 /****************************************************************************
2051 Reply to a write.
2052 ****************************************************************************/
2054 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2056 size_t numtowrite;
2057 ssize_t nwritten = -1;
2058 SMB_OFF_T startpos;
2059 char *data;
2060 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2061 int outsize = 0;
2062 START_PROFILE(SMBwrite);
2064 /* If it's an IPC, pass off the pipe handler. */
2065 if (IS_IPC(conn)) {
2066 END_PROFILE(SMBwrite);
2067 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2070 CHECK_FSP(fsp,conn);
2071 CHECK_WRITE(fsp);
2073 numtowrite = SVAL(inbuf,smb_vwv1);
2074 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2075 data = smb_buf(inbuf) + 3;
2077 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2078 END_PROFILE(SMBwrite);
2079 return ERROR_DOS(ERRDOS,ERRlock);
2083 * X/Open SMB protocol says that if smb_vwv1 is
2084 * zero then the file size should be extended or
2085 * truncated to the size given in smb_vwv[2-3].
2088 if(numtowrite == 0) {
2090 * This is actually an allocate call, and set EOF. JRA.
2092 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2093 if (nwritten < 0) {
2094 END_PROFILE(SMBwrite);
2095 return ERROR_NT(NT_STATUS_DISK_FULL);
2097 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2098 if (nwritten < 0) {
2099 END_PROFILE(SMBwrite);
2100 return ERROR_NT(NT_STATUS_DISK_FULL);
2102 } else
2103 nwritten = write_file(fsp,data,startpos,numtowrite);
2105 if (lp_syncalways(SNUM(conn)))
2106 sync_file(conn,fsp);
2108 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2109 END_PROFILE(SMBwrite);
2110 return(UNIXERROR(ERRHRD,ERRdiskfull));
2113 outsize = set_message(outbuf,1,0,True);
2115 SSVAL(outbuf,smb_vwv0,nwritten);
2117 if (nwritten < (ssize_t)numtowrite) {
2118 SCVAL(outbuf,smb_rcls,ERRHRD);
2119 SSVAL(outbuf,smb_err,ERRdiskfull);
2122 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2124 END_PROFILE(SMBwrite);
2125 return(outsize);
2128 /****************************************************************************
2129 Reply to a write and X.
2130 ****************************************************************************/
2132 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2134 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2135 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2136 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2137 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2138 ssize_t nwritten = -1;
2139 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2140 unsigned int smblen = smb_len(inbuf);
2141 char *data;
2142 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2143 START_PROFILE(SMBwriteX);
2145 /* If it's an IPC, pass off the pipe handler. */
2146 if (IS_IPC(conn)) {
2147 END_PROFILE(SMBwriteX);
2148 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2151 CHECK_FSP(fsp,conn);
2152 CHECK_WRITE(fsp);
2154 /* Deal with possible LARGE_WRITEX */
2155 if (large_writeX)
2156 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2158 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2159 END_PROFILE(SMBwriteX);
2160 return ERROR_DOS(ERRDOS,ERRbadmem);
2163 data = smb_base(inbuf) + smb_doff;
2165 if(CVAL(inbuf,smb_wct) == 14) {
2166 #ifdef LARGE_SMB_OFF_T
2168 * This is a large offset (64 bit) write.
2170 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2172 #else /* !LARGE_SMB_OFF_T */
2175 * Ensure we haven't been sent a >32 bit offset.
2178 if(IVAL(inbuf,smb_vwv12) != 0) {
2179 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2180 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2181 END_PROFILE(SMBwriteX);
2182 return ERROR_DOS(ERRDOS,ERRbadaccess);
2185 #endif /* LARGE_SMB_OFF_T */
2188 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2189 END_PROFILE(SMBwriteX);
2190 return ERROR_DOS(ERRDOS,ERRlock);
2193 /* X/Open SMB protocol says that, unlike SMBwrite
2194 if the length is zero then NO truncation is
2195 done, just a write of zero. To truncate a file,
2196 use SMBwrite. */
2198 if(numtowrite == 0)
2199 nwritten = 0;
2200 else
2201 nwritten = write_file(fsp,data,startpos,numtowrite);
2203 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2204 END_PROFILE(SMBwriteX);
2205 return(UNIXERROR(ERRHRD,ERRdiskfull));
2208 set_message(outbuf,6,0,True);
2210 SSVAL(outbuf,smb_vwv2,nwritten);
2211 if (large_writeX)
2212 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2214 if (nwritten < (ssize_t)numtowrite) {
2215 SCVAL(outbuf,smb_rcls,ERRHRD);
2216 SSVAL(outbuf,smb_err,ERRdiskfull);
2219 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2220 fsp->fnum, (int)numtowrite, (int)nwritten));
2222 if (lp_syncalways(SNUM(conn)) || write_through)
2223 sync_file(conn,fsp);
2225 END_PROFILE(SMBwriteX);
2226 return chain_reply(inbuf,outbuf,length,bufsize);
2229 /****************************************************************************
2230 Reply to a lseek.
2231 ****************************************************************************/
2233 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2235 SMB_OFF_T startpos;
2236 SMB_OFF_T res= -1;
2237 int mode,umode;
2238 int outsize = 0;
2239 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2240 START_PROFILE(SMBlseek);
2242 CHECK_FSP(fsp,conn);
2244 flush_write_cache(fsp, SEEK_FLUSH);
2246 mode = SVAL(inbuf,smb_vwv1) & 3;
2247 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2248 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2250 switch (mode) {
2251 case 0:
2252 umode = SEEK_SET;
2253 break;
2254 case 1:
2255 umode = SEEK_CUR;
2256 break;
2257 case 2:
2258 umode = SEEK_END;
2259 break;
2260 default:
2261 umode = SEEK_SET;
2262 break;
2265 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2267 * Check for the special case where a seek before the start
2268 * of the file sets the offset to zero. Added in the CIFS spec,
2269 * section 4.2.7.
2272 if(errno == EINVAL) {
2273 SMB_OFF_T current_pos = startpos;
2275 if(umode == SEEK_CUR) {
2277 if((current_pos = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2278 END_PROFILE(SMBlseek);
2279 return(UNIXERROR(ERRDOS,ERRnoaccess));
2282 current_pos += startpos;
2284 } else if (umode == SEEK_END) {
2286 SMB_STRUCT_STAT sbuf;
2288 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2289 END_PROFILE(SMBlseek);
2290 return(UNIXERROR(ERRDOS,ERRnoaccess));
2293 current_pos += sbuf.st_size;
2296 if(current_pos < 0)
2297 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2300 if(res == -1) {
2301 END_PROFILE(SMBlseek);
2302 return(UNIXERROR(ERRDOS,ERRnoaccess));
2306 fsp->pos = res;
2308 outsize = set_message(outbuf,2,0,True);
2309 SIVAL(outbuf,smb_vwv0,res);
2311 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2312 fsp->fnum, (double)startpos, (double)res, mode));
2314 END_PROFILE(SMBlseek);
2315 return(outsize);
2318 /****************************************************************************
2319 Reply to a flush.
2320 ****************************************************************************/
2322 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2324 int outsize = set_message(outbuf,0,0,True);
2325 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2326 START_PROFILE(SMBflush);
2328 CHECK_FSP(fsp,conn);
2330 if (!fsp) {
2331 file_sync_all(conn);
2332 } else {
2333 sync_file(conn,fsp);
2336 DEBUG(3,("flush\n"));
2337 END_PROFILE(SMBflush);
2338 return(outsize);
2341 /****************************************************************************
2342 Reply to a exit.
2343 ****************************************************************************/
2345 int reply_exit(connection_struct *conn,
2346 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2348 int outsize;
2349 START_PROFILE(SMBexit);
2350 outsize = set_message(outbuf,0,0,True);
2352 DEBUG(3,("exit\n"));
2354 END_PROFILE(SMBexit);
2355 return(outsize);
2358 /****************************************************************************
2359 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2360 ****************************************************************************/
2362 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2363 int dum_buffsize)
2365 extern struct current_user current_user;
2366 int outsize = 0;
2367 time_t mtime;
2368 int32 eclass = 0, err = 0;
2369 files_struct *fsp = NULL;
2370 START_PROFILE(SMBclose);
2372 outsize = set_message(outbuf,0,0,True);
2374 /* If it's an IPC, pass off to the pipe handler. */
2375 if (IS_IPC(conn)) {
2376 END_PROFILE(SMBclose);
2377 return reply_pipe_close(conn, inbuf,outbuf);
2380 fsp = file_fsp(inbuf,smb_vwv0);
2383 * We can only use CHECK_FSP if we know it's not a directory.
2386 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2387 END_PROFILE(SMBclose);
2388 return ERROR_DOS(ERRDOS,ERRbadfid);
2391 if(fsp->is_directory) {
2393 * Special case - close NT SMB directory handle.
2395 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2396 close_file(fsp,True);
2397 } else {
2399 * Close ordinary file.
2401 int close_err;
2402 pstring file_name;
2404 /* Save the name for time set in close. */
2405 pstrcpy( file_name, fsp->fsp_name);
2407 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2408 fsp->fd, fsp->fnum,
2409 conn->num_files_open));
2412 * close_file() returns the unix errno if an error
2413 * was detected on close - normally this is due to
2414 * a disk full error. If not then it was probably an I/O error.
2417 if((close_err = close_file(fsp,True)) != 0) {
2418 errno = close_err;
2419 END_PROFILE(SMBclose);
2420 return (UNIXERROR(ERRHRD,ERRgeneral));
2424 * Now take care of any time sent in the close.
2427 mtime = make_unix_date3(inbuf+smb_vwv1);
2429 /* try and set the date */
2430 set_filetime(conn, file_name, mtime);
2434 /* We have a cached error */
2435 if(eclass || err) {
2436 END_PROFILE(SMBclose);
2437 return ERROR_DOS(eclass,err);
2440 END_PROFILE(SMBclose);
2441 return(outsize);
2444 /****************************************************************************
2445 Reply to a writeclose (Core+ protocol).
2446 ****************************************************************************/
2448 int reply_writeclose(connection_struct *conn,
2449 char *inbuf,char *outbuf, int size, int dum_buffsize)
2451 size_t numtowrite;
2452 ssize_t nwritten = -1;
2453 int outsize = 0;
2454 int close_err = 0;
2455 SMB_OFF_T startpos;
2456 char *data;
2457 time_t mtime;
2458 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2459 START_PROFILE(SMBwriteclose);
2461 CHECK_FSP(fsp,conn);
2462 CHECK_WRITE(fsp);
2464 numtowrite = SVAL(inbuf,smb_vwv1);
2465 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2466 mtime = make_unix_date3(inbuf+smb_vwv4);
2467 data = smb_buf(inbuf) + 1;
2469 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2470 END_PROFILE(SMBwriteclose);
2471 return ERROR_DOS(ERRDOS,ERRlock);
2474 nwritten = write_file(fsp,data,startpos,numtowrite);
2476 set_filetime(conn, fsp->fsp_name,mtime);
2478 close_err = close_file(fsp,True);
2480 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2481 fsp->fnum, (int)numtowrite, (int)nwritten,
2482 conn->num_files_open));
2484 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2485 END_PROFILE(SMBwriteclose);
2486 return(UNIXERROR(ERRHRD,ERRdiskfull));
2489 if(close_err != 0) {
2490 errno = close_err;
2491 END_PROFILE(SMBwriteclose);
2492 return(UNIXERROR(ERRHRD,ERRgeneral));
2495 outsize = set_message(outbuf,1,0,True);
2497 SSVAL(outbuf,smb_vwv0,nwritten);
2498 END_PROFILE(SMBwriteclose);
2499 return(outsize);
2502 /****************************************************************************
2503 Reply to a lock.
2504 ****************************************************************************/
2506 int reply_lock(connection_struct *conn,
2507 char *inbuf,char *outbuf, int length, int dum_buffsize)
2509 int outsize = set_message(outbuf,0,0,True);
2510 SMB_BIG_UINT count,offset;
2511 NTSTATUS status;
2512 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2513 START_PROFILE(SMBlock);
2515 CHECK_FSP(fsp,conn);
2517 release_level_2_oplocks_on_change(fsp);
2519 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2520 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2522 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2523 fsp->fd, fsp->fnum, (double)offset, (double)count));
2525 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2526 if (NT_STATUS_V(status)) {
2527 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2529 * A blocking lock was requested. Package up
2530 * this smb into a queued request and push it
2531 * onto the blocking lock queue.
2533 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2534 END_PROFILE(SMBlock);
2535 return -1;
2538 END_PROFILE(SMBlock);
2539 return ERROR_NT(status);
2542 END_PROFILE(SMBlock);
2543 return(outsize);
2546 /****************************************************************************
2547 Reply to a unlock.
2548 ****************************************************************************/
2550 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2551 int dum_buffsize)
2553 int outsize = set_message(outbuf,0,0,True);
2554 SMB_BIG_UINT count,offset;
2555 NTSTATUS status;
2556 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2557 START_PROFILE(SMBunlock);
2559 CHECK_FSP(fsp,conn);
2561 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2562 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2564 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2565 if (NT_STATUS_V(status)) {
2566 END_PROFILE(SMBunlock);
2567 return ERROR_NT(status);
2570 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2571 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2573 END_PROFILE(SMBunlock);
2574 return(outsize);
2577 /****************************************************************************
2578 Reply to a tdis.
2579 ****************************************************************************/
2581 int reply_tdis(connection_struct *conn,
2582 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2584 int outsize = set_message(outbuf,0,0,True);
2585 uint16 vuid;
2586 START_PROFILE(SMBtdis);
2588 vuid = SVAL(inbuf,smb_uid);
2590 if (!conn) {
2591 DEBUG(4,("Invalid connection in tdis\n"));
2592 END_PROFILE(SMBtdis);
2593 return ERROR_DOS(ERRSRV,ERRinvnid);
2596 conn->used = False;
2598 close_cnum(conn,vuid);
2600 END_PROFILE(SMBtdis);
2601 return outsize;
2604 /****************************************************************************
2605 Reply to a echo.
2606 ****************************************************************************/
2608 int reply_echo(connection_struct *conn,
2609 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2611 int smb_reverb = SVAL(inbuf,smb_vwv0);
2612 int seq_num;
2613 unsigned int data_len = smb_buflen(inbuf);
2614 int outsize = set_message(outbuf,1,data_len,True);
2615 START_PROFILE(SMBecho);
2617 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2619 /* copy any incoming data back out */
2620 if (data_len > 0)
2621 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2623 if (smb_reverb > 100) {
2624 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2625 smb_reverb = 100;
2628 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2629 SSVAL(outbuf,smb_vwv0,seq_num);
2631 smb_setlen(outbuf,outsize - 4);
2633 if (!send_smb(smbd_server_fd(),outbuf))
2634 exit_server("reply_echo: send_smb failed.");
2637 DEBUG(3,("echo %d times\n", smb_reverb));
2639 smb_echo_count++;
2641 END_PROFILE(SMBecho);
2642 return -1;
2645 /****************************************************************************
2646 Reply to a printopen.
2647 ****************************************************************************/
2649 int reply_printopen(connection_struct *conn,
2650 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2652 int outsize = 0;
2653 files_struct *fsp;
2654 START_PROFILE(SMBsplopen);
2656 if (!CAN_PRINT(conn)) {
2657 END_PROFILE(SMBsplopen);
2658 return ERROR_DOS(ERRDOS,ERRnoaccess);
2661 /* Open for exclusive use, write only. */
2662 fsp = print_fsp_open(conn, NULL);
2664 if (!fsp) {
2665 END_PROFILE(SMBsplopen);
2666 return(UNIXERROR(ERRDOS,ERRnoaccess));
2669 outsize = set_message(outbuf,1,0,True);
2670 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2672 DEBUG(3,("openprint fd=%d fnum=%d\n",
2673 fsp->fd, fsp->fnum));
2675 END_PROFILE(SMBsplopen);
2676 return(outsize);
2679 /****************************************************************************
2680 Reply to a printclose.
2681 ****************************************************************************/
2683 int reply_printclose(connection_struct *conn,
2684 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2686 int outsize = set_message(outbuf,0,0,True);
2687 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2688 int close_err = 0;
2689 START_PROFILE(SMBsplclose);
2691 CHECK_FSP(fsp,conn);
2693 if (!CAN_PRINT(conn)) {
2694 END_PROFILE(SMBsplclose);
2695 return ERROR_DOS(ERRDOS,ERRnoaccess);
2698 DEBUG(3,("printclose fd=%d fnum=%d\n",
2699 fsp->fd,fsp->fnum));
2701 close_err = close_file(fsp,True);
2703 if(close_err != 0) {
2704 errno = close_err;
2705 END_PROFILE(SMBsplclose);
2706 return(UNIXERROR(ERRHRD,ERRgeneral));
2709 END_PROFILE(SMBsplclose);
2710 return(outsize);
2713 /****************************************************************************
2714 Reply to a printqueue.
2715 ****************************************************************************/
2717 int reply_printqueue(connection_struct *conn,
2718 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2720 int outsize = set_message(outbuf,2,3,True);
2721 int max_count = SVAL(inbuf,smb_vwv0);
2722 int start_index = SVAL(inbuf,smb_vwv1);
2723 START_PROFILE(SMBsplretq);
2725 /* we used to allow the client to get the cnum wrong, but that
2726 is really quite gross and only worked when there was only
2727 one printer - I think we should now only accept it if they
2728 get it right (tridge) */
2729 if (!CAN_PRINT(conn)) {
2730 END_PROFILE(SMBsplretq);
2731 return ERROR_DOS(ERRDOS,ERRnoaccess);
2734 SSVAL(outbuf,smb_vwv0,0);
2735 SSVAL(outbuf,smb_vwv1,0);
2736 SCVAL(smb_buf(outbuf),0,1);
2737 SSVAL(smb_buf(outbuf),1,0);
2739 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2740 start_index, max_count));
2743 print_queue_struct *queue = NULL;
2744 print_status_struct status;
2745 char *p = smb_buf(outbuf) + 3;
2746 int count = print_queue_status(SNUM(conn), &queue, &status);
2747 int num_to_get = ABS(max_count);
2748 int first = (max_count>0?start_index:start_index+max_count+1);
2749 int i;
2751 if (first >= count)
2752 num_to_get = 0;
2753 else
2754 num_to_get = MIN(num_to_get,count-first);
2757 for (i=first;i<first+num_to_get;i++) {
2758 put_dos_date2(p,0,queue[i].time);
2759 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2760 SSVAL(p,5, queue[i].job);
2761 SIVAL(p,7,queue[i].size);
2762 SCVAL(p,11,0);
2763 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2764 p += 28;
2767 if (count > 0) {
2768 outsize = set_message(outbuf,2,28*count+3,False);
2769 SSVAL(outbuf,smb_vwv0,count);
2770 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2771 SCVAL(smb_buf(outbuf),0,1);
2772 SSVAL(smb_buf(outbuf),1,28*count);
2775 SAFE_FREE(queue);
2777 DEBUG(3,("%d entries returned in queue\n",count));
2780 END_PROFILE(SMBsplretq);
2781 return(outsize);
2784 /****************************************************************************
2785 Reply to a printwrite.
2786 ****************************************************************************/
2788 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2790 int numtowrite;
2791 int outsize = set_message(outbuf,0,0,True);
2792 char *data;
2793 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2795 START_PROFILE(SMBsplwr);
2797 if (!CAN_PRINT(conn)) {
2798 END_PROFILE(SMBsplwr);
2799 return ERROR_DOS(ERRDOS,ERRnoaccess);
2802 CHECK_FSP(fsp,conn);
2803 CHECK_WRITE(fsp);
2805 numtowrite = SVAL(smb_buf(inbuf),1);
2806 data = smb_buf(inbuf) + 3;
2808 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2809 END_PROFILE(SMBsplwr);
2810 return(UNIXERROR(ERRHRD,ERRdiskfull));
2813 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2815 END_PROFILE(SMBsplwr);
2816 return(outsize);
2819 /****************************************************************************
2820 The guts of the mkdir command, split out so it may be called by the NT SMB
2821 code.
2822 ****************************************************************************/
2824 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2826 BOOL bad_path = False;
2827 SMB_STRUCT_STAT sbuf;
2828 int ret= -1;
2830 unix_convert(directory,conn,0,&bad_path,&sbuf);
2832 if (check_name(directory, conn))
2833 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
2835 if (ret == -1) {
2836 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
2837 if (!NT_STATUS_IS_OK(nterr))
2838 return nterr;
2839 return map_nt_error_from_unix(errno);
2842 return NT_STATUS_OK;
2845 /****************************************************************************
2846 Reply to a mkdir.
2847 ****************************************************************************/
2849 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2851 pstring directory;
2852 int outsize;
2853 NTSTATUS status;
2854 START_PROFILE(SMBmkdir);
2856 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2858 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
2860 status = mkdir_internal(conn, directory);
2861 if (!NT_STATUS_IS_OK(status))
2862 return ERROR_NT(status);
2864 outsize = set_message(outbuf,0,0,True);
2866 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2868 END_PROFILE(SMBmkdir);
2869 return(outsize);
2872 /****************************************************************************
2873 Static function used by reply_rmdir to delete an entire directory
2874 tree recursively. Return False on ok, True on fail.
2875 ****************************************************************************/
2877 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2879 const char *dname = NULL;
2880 BOOL ret = False;
2881 void *dirptr = OpenDir(conn, directory, False);
2883 if(dirptr == NULL)
2884 return True;
2886 while((dname = ReadDirName(dirptr))) {
2887 pstring fullname;
2888 SMB_STRUCT_STAT st;
2890 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2891 continue;
2893 /* Construct the full name. */
2894 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2895 errno = ENOMEM;
2896 ret = True;
2897 break;
2900 pstrcpy(fullname, directory);
2901 pstrcat(fullname, "/");
2902 pstrcat(fullname, dname);
2904 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
2905 ret = True;
2906 break;
2909 if(st.st_mode & S_IFDIR) {
2910 if(recursive_rmdir(conn, fullname)!=0) {
2911 ret = True;
2912 break;
2914 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
2915 ret = True;
2916 break;
2918 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
2919 ret = True;
2920 break;
2923 CloseDir(dirptr);
2924 return ret;
2927 /****************************************************************************
2928 The internals of the rmdir code - called elsewhere.
2929 ****************************************************************************/
2931 BOOL rmdir_internals(connection_struct *conn, char *directory)
2933 BOOL ok;
2935 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
2936 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2938 * Check to see if the only thing in this directory are
2939 * vetoed files/directories. If so then delete them and
2940 * retry. If we fail to delete any of them (and we *don't*
2941 * do a recursive delete) then fail the rmdir.
2943 BOOL all_veto_files = True;
2944 const char *dname;
2945 void *dirptr = OpenDir(conn, directory, False);
2947 if(dirptr != NULL) {
2948 int dirpos = TellDir(dirptr);
2949 while ((dname = ReadDirName(dirptr))) {
2950 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2951 continue;
2952 if(!IS_VETO_PATH(conn, dname)) {
2953 all_veto_files = False;
2954 break;
2958 if(all_veto_files) {
2959 SeekDir(dirptr,dirpos);
2960 while ((dname = ReadDirName(dirptr))) {
2961 pstring fullname;
2962 SMB_STRUCT_STAT st;
2964 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2965 continue;
2967 /* Construct the full name. */
2968 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2969 errno = ENOMEM;
2970 break;
2973 pstrcpy(fullname, directory);
2974 pstrcat(fullname, "/");
2975 pstrcat(fullname, dname);
2977 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
2978 break;
2979 if(st.st_mode & S_IFDIR) {
2980 if(lp_recursive_veto_delete(SNUM(conn))) {
2981 if(recursive_rmdir(conn, fullname) != 0)
2982 break;
2984 if(SMB_VFS_RMDIR(conn,fullname) != 0)
2985 break;
2986 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
2987 break;
2989 CloseDir(dirptr);
2990 /* Retry the rmdir */
2991 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
2992 } else {
2993 CloseDir(dirptr);
2995 } else {
2996 errno = ENOTEMPTY;
3000 if (!ok)
3001 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3003 return ok;
3006 /****************************************************************************
3007 Reply to a rmdir.
3008 ****************************************************************************/
3010 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3012 pstring directory;
3013 int outsize = 0;
3014 BOOL ok = False;
3015 BOOL bad_path = False;
3016 SMB_STRUCT_STAT sbuf;
3017 START_PROFILE(SMBrmdir);
3019 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
3021 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3023 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3025 if (check_name(directory,conn)) {
3026 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3027 ok = rmdir_internals(conn, directory);
3030 if (!ok) {
3031 set_bad_path_error(errno, bad_path);
3032 END_PROFILE(SMBrmdir);
3033 return(UNIXERROR(ERRDOS,ERRbadpath));
3036 outsize = set_message(outbuf,0,0,True);
3038 DEBUG( 3, ( "rmdir %s\n", directory ) );
3040 END_PROFILE(SMBrmdir);
3041 return(outsize);
3044 /*******************************************************************
3045 Resolve wildcards in a filename rename.
3046 ********************************************************************/
3048 static BOOL resolve_wildcards(const char *name1, char *name2)
3050 fstring root1,root2;
3051 fstring ext1,ext2;
3052 char *p,*p2, *pname1, *pname2;
3053 int available_space;
3056 pname1 = strrchr_m(name1,'/');
3057 pname2 = strrchr_m(name2,'/');
3059 if (!pname1 || !pname2)
3060 return(False);
3062 fstrcpy(root1,pname1);
3063 fstrcpy(root2,pname2);
3064 p = strrchr_m(root1,'.');
3065 if (p) {
3066 *p = 0;
3067 fstrcpy(ext1,p+1);
3068 } else {
3069 fstrcpy(ext1,"");
3071 p = strrchr_m(root2,'.');
3072 if (p) {
3073 *p = 0;
3074 fstrcpy(ext2,p+1);
3075 } else {
3076 fstrcpy(ext2,"");
3079 p = root1;
3080 p2 = root2;
3081 while (*p2) {
3082 if (*p2 == '?') {
3083 *p2 = *p;
3084 p2++;
3085 } else {
3086 p2++;
3088 if (*p)
3089 p++;
3092 p = ext1;
3093 p2 = ext2;
3094 while (*p2) {
3095 if (*p2 == '?') {
3096 *p2 = *p;
3097 p2++;
3098 } else {
3099 p2++;
3101 if (*p)
3102 p++;
3105 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3107 if (ext2[0]) {
3108 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3109 } else {
3110 pstrcpy_base(pname2, root2, name2);
3113 return(True);
3116 /****************************************************************************
3117 The guts of the rename command, split out so it may be called by the NT SMB
3118 code.
3119 ****************************************************************************/
3121 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3123 pstring directory;
3124 pstring mask;
3125 pstring newname_last_component;
3126 char *p;
3127 BOOL has_wild;
3128 BOOL bad_path1 = False;
3129 BOOL bad_path2 = False;
3130 int count=0;
3131 NTSTATUS error = NT_STATUS_OK;
3132 BOOL rc = True;
3133 SMB_STRUCT_STAT sbuf1, sbuf2;
3135 *directory = *mask = 0;
3137 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3138 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3141 * Split the old name into directory and last component
3142 * strings. Note that unix_convert may have stripped off a
3143 * leading ./ from both name and newname if the rename is
3144 * at the root of the share. We need to make sure either both
3145 * name and newname contain a / character or neither of them do
3146 * as this is checked in resolve_wildcards().
3149 p = strrchr_m(name,'/');
3150 if (!p) {
3151 pstrcpy(directory,".");
3152 pstrcpy(mask,name);
3153 } else {
3154 *p = 0;
3155 pstrcpy(directory,name);
3156 pstrcpy(mask,p+1);
3157 *p = '/'; /* Replace needed for exceptional test below. */
3161 * We should only check the mangled cache
3162 * here if unix_convert failed. This means
3163 * that the path in 'mask' doesn't exist
3164 * on the file system and so we need to look
3165 * for a possible mangle. This patch from
3166 * Tine Smukavec <valentin.smukavec@hermes.si>.
3169 if (!rc && mangle_is_mangled(mask))
3170 mangle_check_cache( mask );
3172 has_wild = ms_has_wild(mask);
3174 if (!has_wild) {
3176 * No wildcards - just process the one file.
3178 BOOL is_short_name = mangle_is_8_3(name, True);
3180 /* Add a terminating '/' to the directory name. */
3181 pstrcat(directory,"/");
3182 pstrcat(directory,mask);
3184 /* Ensure newname contains a '/' also */
3185 if(strrchr_m(newname,'/') == 0) {
3186 pstring tmpstr;
3188 pstrcpy(tmpstr, "./");
3189 pstrcat(tmpstr, newname);
3190 pstrcpy(newname, tmpstr);
3193 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3194 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3195 case_sensitive, case_preserve, short_case_preserve, directory,
3196 newname, newname_last_component, is_short_name));
3199 * Check for special case with case preserving and not
3200 * case sensitive, if directory and newname are identical,
3201 * and the old last component differs from the original
3202 * last component only by case, then we should allow
3203 * the rename (user is trying to change the case of the
3204 * filename).
3206 if((case_sensitive == False) &&
3207 (((case_preserve == True) &&
3208 (is_short_name == False)) ||
3209 ((short_case_preserve == True) &&
3210 (is_short_name == True))) &&
3211 strcsequal(directory, newname)) {
3212 pstring newname_modified_last_component;
3215 * Get the last component of the modified name.
3216 * Note that we guarantee that newname contains a '/'
3217 * character above.
3219 p = strrchr_m(newname,'/');
3220 pstrcpy(newname_modified_last_component,p+1);
3222 if(strcsequal(newname_modified_last_component,
3223 newname_last_component) == False) {
3225 * Replace the modified last component with
3226 * the original.
3228 pstrcpy(p+1, newname_last_component);
3232 resolve_wildcards(directory,newname);
3235 * The source object must exist.
3238 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3239 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3240 directory,newname));
3242 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3244 * Must return different errors depending on whether the parent
3245 * directory existed or not.
3248 p = strrchr_m(directory, '/');
3249 if (!p)
3250 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3251 *p = '\0';
3252 if (vfs_object_exist(conn, directory, NULL))
3253 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3254 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3256 error = map_nt_error_from_unix(errno);
3257 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3258 nt_errstr(error), directory,newname));
3260 return error;
3263 error = can_rename(directory,conn,&sbuf1);
3265 if (!NT_STATUS_IS_OK(error)) {
3266 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3267 nt_errstr(error), directory,newname));
3268 return error;
3272 * If the src and dest names are identical - including case,
3273 * don't do the rename, just return success.
3276 if (strcsequal(directory, newname)) {
3277 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3278 return NT_STATUS_OK;
3281 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3282 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3283 directory,newname));
3284 return NT_STATUS_OBJECT_NAME_COLLISION;
3287 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3288 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3289 directory,newname));
3290 return NT_STATUS_OK;
3293 if (errno == ENOTDIR || errno == EISDIR)
3294 error = NT_STATUS_OBJECT_NAME_COLLISION;
3295 else
3296 error = map_nt_error_from_unix(errno);
3298 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3299 nt_errstr(error), directory,newname));
3301 return error;
3302 } else {
3304 * Wildcards - process each file that matches.
3306 void *dirptr = NULL;
3307 const char *dname;
3308 pstring destname;
3310 if (check_name(directory,conn))
3311 dirptr = OpenDir(conn, directory, True);
3313 if (dirptr) {
3314 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3316 if (strequal(mask,"????????.???"))
3317 pstrcpy(mask,"*");
3319 while ((dname = ReadDirName(dirptr))) {
3320 pstring fname;
3322 pstrcpy(fname,dname);
3324 if(!mask_match(fname, mask, case_sensitive))
3325 continue;
3327 error = NT_STATUS_ACCESS_DENIED;
3328 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3329 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3330 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3331 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3332 continue;
3334 error = can_rename(fname,conn,&sbuf1);
3335 if (!NT_STATUS_IS_OK(error)) {
3336 DEBUG(6,("rename %s refused\n", fname));
3337 continue;
3339 pstrcpy(destname,newname);
3341 if (!resolve_wildcards(fname,destname)) {
3342 DEBUG(6,("resolve_wildcards %s %s failed\n",
3343 fname, destname));
3344 continue;
3347 if (!replace_if_exists &&
3348 vfs_file_exist(conn,destname, NULL)) {
3349 DEBUG(6,("file_exist %s\n", destname));
3350 error = NT_STATUS_OBJECT_NAME_COLLISION;
3351 continue;
3354 if (!SMB_VFS_RENAME(conn,fname,destname))
3355 count++;
3356 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3358 CloseDir(dirptr);
3362 if (count == 0 && NT_STATUS_IS_OK(error)) {
3363 error = map_nt_error_from_unix(errno);
3366 return error;
3369 /****************************************************************************
3370 Reply to a mv.
3371 ****************************************************************************/
3373 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3374 int dum_buffsize)
3376 int outsize = 0;
3377 pstring name;
3378 pstring newname;
3379 char *p;
3380 NTSTATUS status;
3382 START_PROFILE(SMBmv);
3384 p = smb_buf(inbuf) + 1;
3385 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3386 p++;
3387 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3389 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3390 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3392 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3394 status = rename_internals(conn, name, newname, False);
3395 if (!NT_STATUS_IS_OK(status)) {
3396 return ERROR_NT(status);
3400 * Win2k needs a changenotify request response before it will
3401 * update after a rename..
3403 process_pending_change_notify_queue((time_t)0);
3404 outsize = set_message(outbuf,0,0,True);
3406 END_PROFILE(SMBmv);
3407 return(outsize);
3410 /*******************************************************************
3411 Copy a file as part of a reply_copy.
3412 ******************************************************************/
3414 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3415 int count,BOOL target_is_directory, int *err_ret)
3417 int Access,action;
3418 SMB_STRUCT_STAT src_sbuf, sbuf2;
3419 SMB_OFF_T ret=-1;
3420 files_struct *fsp1,*fsp2;
3421 pstring dest;
3423 *err_ret = 0;
3425 pstrcpy(dest,dest1);
3426 if (target_is_directory) {
3427 char *p = strrchr_m(src,'/');
3428 if (p)
3429 p++;
3430 else
3431 p = src;
3432 pstrcat(dest,"/");
3433 pstrcat(dest,p);
3436 if (!vfs_file_exist(conn,src,&src_sbuf))
3437 return(False);
3439 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3440 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3442 if (!fsp1)
3443 return(False);
3445 if (!target_is_directory && count)
3446 ofun = FILE_EXISTS_OPEN;
3448 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3449 ZERO_STRUCTP(&sbuf2);
3451 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3452 ofun,src_sbuf.st_mode,0,&Access,&action);
3454 if (!fsp2) {
3455 close_file(fsp1,False);
3456 return(False);
3459 if ((ofun&3) == 1) {
3460 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3461 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3463 * Stop the copy from occurring.
3465 ret = -1;
3466 src_sbuf.st_size = 0;
3470 if (src_sbuf.st_size)
3471 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3473 close_file(fsp1,False);
3475 /* Ensure the modtime is set correctly on the destination file. */
3476 fsp2->pending_modtime = src_sbuf.st_mtime;
3479 * As we are opening fsp1 read-only we only expect
3480 * an error on close on fsp2 if we are out of space.
3481 * Thus we don't look at the error return from the
3482 * close of fsp1.
3484 *err_ret = close_file(fsp2,False);
3486 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3489 /****************************************************************************
3490 Reply to a file copy.
3491 ****************************************************************************/
3493 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3495 int outsize = 0;
3496 pstring name;
3497 pstring directory;
3498 pstring mask,newname;
3499 char *p;
3500 int count=0;
3501 int error = ERRnoaccess;
3502 int err = 0;
3503 BOOL has_wild;
3504 BOOL exists=False;
3505 int tid2 = SVAL(inbuf,smb_vwv0);
3506 int ofun = SVAL(inbuf,smb_vwv1);
3507 int flags = SVAL(inbuf,smb_vwv2);
3508 BOOL target_is_directory=False;
3509 BOOL bad_path1 = False;
3510 BOOL bad_path2 = False;
3511 BOOL rc = True;
3512 SMB_STRUCT_STAT sbuf1, sbuf2;
3514 START_PROFILE(SMBcopy);
3516 *directory = *mask = 0;
3518 p = smb_buf(inbuf);
3519 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3520 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3522 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3524 if (tid2 != conn->cnum) {
3525 /* can't currently handle inter share copies XXXX */
3526 DEBUG(3,("Rejecting inter-share copy\n"));
3527 END_PROFILE(SMBcopy);
3528 return ERROR_DOS(ERRSRV,ERRinvdevice);
3531 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3532 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3534 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3535 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3537 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3539 if ((flags&1) && target_is_directory) {
3540 END_PROFILE(SMBcopy);
3541 return ERROR_DOS(ERRDOS,ERRbadfile);
3544 if ((flags&2) && !target_is_directory) {
3545 END_PROFILE(SMBcopy);
3546 return ERROR_DOS(ERRDOS,ERRbadpath);
3549 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3550 /* wants a tree copy! XXXX */
3551 DEBUG(3,("Rejecting tree copy\n"));
3552 END_PROFILE(SMBcopy);
3553 return ERROR_DOS(ERRSRV,ERRerror);
3556 p = strrchr_m(name,'/');
3557 if (!p) {
3558 pstrcpy(directory,"./");
3559 pstrcpy(mask,name);
3560 } else {
3561 *p = 0;
3562 pstrcpy(directory,name);
3563 pstrcpy(mask,p+1);
3567 * We should only check the mangled cache
3568 * here if unix_convert failed. This means
3569 * that the path in 'mask' doesn't exist
3570 * on the file system and so we need to look
3571 * for a possible mangle. This patch from
3572 * Tine Smukavec <valentin.smukavec@hermes.si>.
3575 if (!rc && mangle_is_mangled(mask))
3576 mangle_check_cache( mask );
3578 has_wild = ms_has_wild(mask);
3580 if (!has_wild) {
3581 pstrcat(directory,"/");
3582 pstrcat(directory,mask);
3583 if (resolve_wildcards(directory,newname) &&
3584 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3585 count++;
3586 if(!count && err) {
3587 errno = err;
3588 END_PROFILE(SMBcopy);
3589 return(UNIXERROR(ERRHRD,ERRgeneral));
3591 if (!count) {
3592 exists = vfs_file_exist(conn,directory,NULL);
3594 } else {
3595 void *dirptr = NULL;
3596 const char *dname;
3597 pstring destname;
3599 if (check_name(directory,conn))
3600 dirptr = OpenDir(conn, directory, True);
3602 if (dirptr) {
3603 error = ERRbadfile;
3605 if (strequal(mask,"????????.???"))
3606 pstrcpy(mask,"*");
3608 while ((dname = ReadDirName(dirptr))) {
3609 pstring fname;
3610 pstrcpy(fname,dname);
3612 if(!mask_match(fname, mask, case_sensitive))
3613 continue;
3615 error = ERRnoaccess;
3616 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3617 pstrcpy(destname,newname);
3618 if (resolve_wildcards(fname,destname) &&
3619 copy_file(fname,destname,conn,ofun,
3620 count,target_is_directory,&err))
3621 count++;
3622 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3624 CloseDir(dirptr);
3628 if (count == 0) {
3629 if(err) {
3630 /* Error on close... */
3631 errno = err;
3632 END_PROFILE(SMBcopy);
3633 return(UNIXERROR(ERRHRD,ERRgeneral));
3636 if (exists) {
3637 END_PROFILE(SMBcopy);
3638 return ERROR_DOS(ERRDOS,error);
3639 } else {
3640 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3641 unix_ERR_class = ERRDOS;
3642 unix_ERR_code = ERRbadpath;
3644 END_PROFILE(SMBcopy);
3645 return(UNIXERROR(ERRDOS,error));
3649 outsize = set_message(outbuf,1,0,True);
3650 SSVAL(outbuf,smb_vwv0,count);
3652 END_PROFILE(SMBcopy);
3653 return(outsize);
3656 /****************************************************************************
3657 Reply to a setdir.
3658 ****************************************************************************/
3660 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3662 int snum;
3663 int outsize = 0;
3664 BOOL ok = False;
3665 pstring newdir;
3667 START_PROFILE(pathworks_setdir);
3669 snum = SNUM(conn);
3670 if (!CAN_SETDIR(snum)) {
3671 END_PROFILE(pathworks_setdir);
3672 return ERROR_DOS(ERRDOS,ERRnoaccess);
3675 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3677 if (strlen(newdir) == 0) {
3678 ok = True;
3679 } else {
3680 ok = vfs_directory_exist(conn,newdir,NULL);
3681 if (ok)
3682 string_set(&conn->connectpath,newdir);
3685 if (!ok) {
3686 END_PROFILE(pathworks_setdir);
3687 return ERROR_DOS(ERRDOS,ERRbadpath);
3690 outsize = set_message(outbuf,0,0,True);
3691 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3693 DEBUG(3,("setdir %s\n", newdir));
3695 END_PROFILE(pathworks_setdir);
3696 return(outsize);
3699 /****************************************************************************
3700 Get a lock pid, dealing with large count requests.
3701 ****************************************************************************/
3703 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3705 if(!large_file_format)
3706 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3707 else
3708 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3711 /****************************************************************************
3712 Get a lock count, dealing with large count requests.
3713 ****************************************************************************/
3715 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3717 SMB_BIG_UINT count = 0;
3719 if(!large_file_format) {
3720 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3721 } else {
3723 #if defined(HAVE_LONGLONG)
3724 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3725 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3726 #else /* HAVE_LONGLONG */
3729 * NT4.x seems to be broken in that it sends large file (64 bit)
3730 * lockingX calls even if the CAP_LARGE_FILES was *not*
3731 * negotiated. For boxes without large unsigned ints truncate the
3732 * lock count by dropping the top 32 bits.
3735 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3736 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3737 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3738 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3739 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3742 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3743 #endif /* HAVE_LONGLONG */
3746 return count;
3749 #if !defined(HAVE_LONGLONG)
3750 /****************************************************************************
3751 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3752 ****************************************************************************/
3754 static uint32 map_lock_offset(uint32 high, uint32 low)
3756 unsigned int i;
3757 uint32 mask = 0;
3758 uint32 highcopy = high;
3761 * Try and find out how many significant bits there are in high.
3764 for(i = 0; highcopy; i++)
3765 highcopy >>= 1;
3768 * We use 31 bits not 32 here as POSIX
3769 * lock offsets may not be negative.
3772 mask = (~0) << (31 - i);
3774 if(low & mask)
3775 return 0; /* Fail. */
3777 high <<= (31 - i);
3779 return (high|low);
3781 #endif /* !defined(HAVE_LONGLONG) */
3783 /****************************************************************************
3784 Get a lock offset, dealing with large offset requests.
3785 ****************************************************************************/
3787 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3789 SMB_BIG_UINT offset = 0;
3791 *err = False;
3793 if(!large_file_format) {
3794 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3795 } else {
3797 #if defined(HAVE_LONGLONG)
3798 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3799 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3800 #else /* HAVE_LONGLONG */
3803 * NT4.x seems to be broken in that it sends large file (64 bit)
3804 * lockingX calls even if the CAP_LARGE_FILES was *not*
3805 * negotiated. For boxes without large unsigned ints mangle the
3806 * lock offset by mapping the top 32 bits onto the lower 32.
3809 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3810 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3811 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3812 uint32 new_low = 0;
3814 if((new_low = map_lock_offset(high, low)) == 0) {
3815 *err = True;
3816 return (SMB_BIG_UINT)-1;
3819 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3820 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3821 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3822 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3825 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3826 #endif /* HAVE_LONGLONG */
3829 return offset;
3832 /****************************************************************************
3833 Reply to a lockingX request.
3834 ****************************************************************************/
3836 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3838 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3839 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3840 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3841 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3842 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3843 SMB_BIG_UINT count = 0, offset = 0;
3844 uint16 lock_pid;
3845 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3846 int i;
3847 char *data;
3848 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3849 BOOL err;
3850 NTSTATUS status;
3852 START_PROFILE(SMBlockingX);
3854 CHECK_FSP(fsp,conn);
3856 data = smb_buf(inbuf);
3858 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3859 /* we don't support these - and CANCEL_LOCK makes w2k
3860 and XP reboot so I don't really want to be
3861 compatible! (tridge) */
3862 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3865 /* Check if this is an oplock break on a file
3866 we have granted an oplock on.
3868 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3869 /* Client can insist on breaking to none. */
3870 BOOL break_to_none = (oplocklevel == 0);
3872 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3873 (unsigned int)oplocklevel, fsp->fnum ));
3876 * Make sure we have granted an exclusive or batch oplock on this file.
3879 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3880 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3881 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3883 /* if this is a pure oplock break request then don't send a reply */
3884 if (num_locks == 0 && num_ulocks == 0) {
3885 END_PROFILE(SMBlockingX);
3886 return -1;
3887 } else {
3888 END_PROFILE(SMBlockingX);
3889 return ERROR_DOS(ERRDOS,ERRlock);
3893 if (remove_oplock(fsp, break_to_none) == False) {
3894 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3895 fsp->fsp_name ));
3898 /* if this is a pure oplock break request then don't send a reply */
3899 if (num_locks == 0 && num_ulocks == 0) {
3900 /* Sanity check - ensure a pure oplock break is not a
3901 chained request. */
3902 if(CVAL(inbuf,smb_vwv0) != 0xff)
3903 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3904 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3905 END_PROFILE(SMBlockingX);
3906 return -1;
3911 * We do this check *after* we have checked this is not a oplock break
3912 * response message. JRA.
3915 release_level_2_oplocks_on_change(fsp);
3917 /* Data now points at the beginning of the list
3918 of smb_unlkrng structs */
3919 for(i = 0; i < (int)num_ulocks; i++) {
3920 lock_pid = get_lock_pid( data, i, large_file_format);
3921 count = get_lock_count( data, i, large_file_format);
3922 offset = get_lock_offset( data, i, large_file_format, &err);
3925 * There is no error code marked "stupid client bug".... :-).
3927 if(err) {
3928 END_PROFILE(SMBlockingX);
3929 return ERROR_DOS(ERRDOS,ERRnoaccess);
3932 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3933 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3935 status = do_unlock(fsp,conn,lock_pid,count,offset);
3936 if (NT_STATUS_V(status)) {
3937 END_PROFILE(SMBlockingX);
3938 return ERROR_NT(status);
3942 /* Setup the timeout in seconds. */
3944 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500);
3946 /* Now do any requested locks */
3947 data += ((large_file_format ? 20 : 10)*num_ulocks);
3949 /* Data now points at the beginning of the list
3950 of smb_lkrng structs */
3952 for(i = 0; i < (int)num_locks; i++) {
3953 lock_pid = get_lock_pid( data, i, large_file_format);
3954 count = get_lock_count( data, i, large_file_format);
3955 offset = get_lock_offset( data, i, large_file_format, &err);
3958 * There is no error code marked "stupid client bug".... :-).
3960 if(err) {
3961 END_PROFILE(SMBlockingX);
3962 return ERROR_DOS(ERRDOS,ERRnoaccess);
3965 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3966 (double)offset, (double)count, (unsigned int)lock_pid,
3967 fsp->fsp_name, (int)lock_timeout ));
3969 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
3970 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3971 if (NT_STATUS_V(status)) {
3972 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
3974 * A blocking lock was requested. Package up
3975 * this smb into a queued request and push it
3976 * onto the blocking lock queue.
3978 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
3979 END_PROFILE(SMBlockingX);
3980 return -1;
3983 break;
3987 /* If any of the above locks failed, then we must unlock
3988 all of the previous locks (X/Open spec). */
3989 if (i != num_locks && num_locks != 0) {
3991 * Ensure we don't do a remove on the lock that just failed,
3992 * as under POSIX rules, if we have a lock already there, we
3993 * will delete it (and we shouldn't) .....
3995 for(i--; i >= 0; i--) {
3996 lock_pid = get_lock_pid( data, i, large_file_format);
3997 count = get_lock_count( data, i, large_file_format);
3998 offset = get_lock_offset( data, i, large_file_format, &err);
4001 * There is no error code marked "stupid client bug".... :-).
4003 if(err) {
4004 END_PROFILE(SMBlockingX);
4005 return ERROR_DOS(ERRDOS,ERRnoaccess);
4008 do_unlock(fsp,conn,lock_pid,count,offset);
4010 END_PROFILE(SMBlockingX);
4011 return ERROR_NT(status);
4014 set_message(outbuf,2,0,True);
4016 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4017 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4019 END_PROFILE(SMBlockingX);
4020 return chain_reply(inbuf,outbuf,length,bufsize);
4023 /****************************************************************************
4024 Reply to a SMBreadbmpx (read block multiplex) request.
4025 ****************************************************************************/
4027 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4029 ssize_t nread = -1;
4030 ssize_t total_read;
4031 char *data;
4032 SMB_OFF_T startpos;
4033 int outsize;
4034 size_t maxcount;
4035 int max_per_packet;
4036 size_t tcount;
4037 int pad;
4038 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4039 START_PROFILE(SMBreadBmpx);
4041 /* this function doesn't seem to work - disable by default */
4042 if (!lp_readbmpx()) {
4043 END_PROFILE(SMBreadBmpx);
4044 return ERROR_DOS(ERRSRV,ERRuseSTD);
4047 outsize = set_message(outbuf,8,0,True);
4049 CHECK_FSP(fsp,conn);
4050 CHECK_READ(fsp);
4052 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4053 maxcount = SVAL(inbuf,smb_vwv3);
4055 data = smb_buf(outbuf);
4056 pad = ((long)data)%4;
4057 if (pad)
4058 pad = 4 - pad;
4059 data += pad;
4061 max_per_packet = bufsize-(outsize+pad);
4062 tcount = maxcount;
4063 total_read = 0;
4065 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4066 END_PROFILE(SMBreadBmpx);
4067 return ERROR_DOS(ERRDOS,ERRlock);
4070 do {
4071 size_t N = MIN(max_per_packet,tcount-total_read);
4073 nread = read_file(fsp,data,startpos,N);
4075 if (nread <= 0)
4076 nread = 0;
4078 if (nread < (ssize_t)N)
4079 tcount = total_read + nread;
4081 set_message(outbuf,8,nread,False);
4082 SIVAL(outbuf,smb_vwv0,startpos);
4083 SSVAL(outbuf,smb_vwv2,tcount);
4084 SSVAL(outbuf,smb_vwv6,nread);
4085 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4087 if (!send_smb(smbd_server_fd(),outbuf))
4088 exit_server("reply_readbmpx: send_smb failed.");
4090 total_read += nread;
4091 startpos += nread;
4092 } while (total_read < (ssize_t)tcount);
4094 END_PROFILE(SMBreadBmpx);
4095 return(-1);
4098 /****************************************************************************
4099 Reply to a SMBsetattrE.
4100 ****************************************************************************/
4102 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4104 struct utimbuf unix_times;
4105 int outsize = 0;
4106 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4107 START_PROFILE(SMBsetattrE);
4109 outsize = set_message(outbuf,0,0,True);
4111 if(!fsp || (fsp->conn != conn)) {
4112 END_PROFILE(SMBgetattrE);
4113 return ERROR_DOS(ERRDOS,ERRbadfid);
4117 * Convert the DOS times into unix times. Ignore create
4118 * time as UNIX can't set this.
4121 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4122 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4125 * Patch from Ray Frush <frush@engr.colostate.edu>
4126 * Sometimes times are sent as zero - ignore them.
4129 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4130 /* Ignore request */
4131 if( DEBUGLVL( 3 ) ) {
4132 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4133 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4135 END_PROFILE(SMBsetattrE);
4136 return(outsize);
4137 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4138 /* set modify time = to access time if modify time was 0 */
4139 unix_times.modtime = unix_times.actime;
4142 /* Set the date on this file */
4143 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4144 END_PROFILE(SMBsetattrE);
4145 return ERROR_DOS(ERRDOS,ERRnoaccess);
4148 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4149 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4151 END_PROFILE(SMBsetattrE);
4152 return(outsize);
4156 /* Back from the dead for OS/2..... JRA. */
4158 /****************************************************************************
4159 Reply to a SMBwritebmpx (write block multiplex primary) request.
4160 ****************************************************************************/
4162 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4164 size_t numtowrite;
4165 ssize_t nwritten = -1;
4166 int outsize = 0;
4167 SMB_OFF_T startpos;
4168 size_t tcount;
4169 BOOL write_through;
4170 int smb_doff;
4171 char *data;
4172 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4173 START_PROFILE(SMBwriteBmpx);
4175 CHECK_FSP(fsp,conn);
4176 CHECK_WRITE(fsp);
4177 CHECK_ERROR(fsp);
4179 tcount = SVAL(inbuf,smb_vwv1);
4180 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4181 write_through = BITSETW(inbuf+smb_vwv7,0);
4182 numtowrite = SVAL(inbuf,smb_vwv10);
4183 smb_doff = SVAL(inbuf,smb_vwv11);
4185 data = smb_base(inbuf) + smb_doff;
4187 /* If this fails we need to send an SMBwriteC response,
4188 not an SMBwritebmpx - set this up now so we don't forget */
4189 SCVAL(outbuf,smb_com,SMBwritec);
4191 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4192 END_PROFILE(SMBwriteBmpx);
4193 return(ERROR_DOS(ERRDOS,ERRlock));
4196 nwritten = write_file(fsp,data,startpos,numtowrite);
4198 if(lp_syncalways(SNUM(conn)) || write_through)
4199 sync_file(conn,fsp);
4201 if(nwritten < (ssize_t)numtowrite) {
4202 END_PROFILE(SMBwriteBmpx);
4203 return(UNIXERROR(ERRHRD,ERRdiskfull));
4206 /* If the maximum to be written to this file
4207 is greater than what we just wrote then set
4208 up a secondary struct to be attached to this
4209 fd, we will use this to cache error messages etc. */
4211 if((ssize_t)tcount > nwritten) {
4212 write_bmpx_struct *wbms;
4213 if(fsp->wbmpx_ptr != NULL)
4214 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4215 else
4216 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4217 if(!wbms) {
4218 DEBUG(0,("Out of memory in reply_readmpx\n"));
4219 END_PROFILE(SMBwriteBmpx);
4220 return(ERROR_DOS(ERRSRV,ERRnoresource));
4222 wbms->wr_mode = write_through;
4223 wbms->wr_discard = False; /* No errors yet */
4224 wbms->wr_total_written = nwritten;
4225 wbms->wr_errclass = 0;
4226 wbms->wr_error = 0;
4227 fsp->wbmpx_ptr = wbms;
4230 /* We are returning successfully, set the message type back to
4231 SMBwritebmpx */
4232 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4234 outsize = set_message(outbuf,1,0,True);
4236 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4238 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4239 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4241 if (write_through && tcount==nwritten) {
4242 /* We need to send both a primary and a secondary response */
4243 smb_setlen(outbuf,outsize - 4);
4244 if (!send_smb(smbd_server_fd(),outbuf))
4245 exit_server("reply_writebmpx: send_smb failed.");
4247 /* Now the secondary */
4248 outsize = set_message(outbuf,1,0,True);
4249 SCVAL(outbuf,smb_com,SMBwritec);
4250 SSVAL(outbuf,smb_vwv0,nwritten);
4253 END_PROFILE(SMBwriteBmpx);
4254 return(outsize);
4257 /****************************************************************************
4258 Reply to a SMBwritebs (write block multiplex secondary) request.
4259 ****************************************************************************/
4261 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4263 size_t numtowrite;
4264 ssize_t nwritten = -1;
4265 int outsize = 0;
4266 SMB_OFF_T startpos;
4267 size_t tcount;
4268 BOOL write_through;
4269 int smb_doff;
4270 char *data;
4271 write_bmpx_struct *wbms;
4272 BOOL send_response = False;
4273 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4274 START_PROFILE(SMBwriteBs);
4276 CHECK_FSP(fsp,conn);
4277 CHECK_WRITE(fsp);
4279 tcount = SVAL(inbuf,smb_vwv1);
4280 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4281 numtowrite = SVAL(inbuf,smb_vwv6);
4282 smb_doff = SVAL(inbuf,smb_vwv7);
4284 data = smb_base(inbuf) + smb_doff;
4286 /* We need to send an SMBwriteC response, not an SMBwritebs */
4287 SCVAL(outbuf,smb_com,SMBwritec);
4289 /* This fd should have an auxiliary struct attached,
4290 check that it does */
4291 wbms = fsp->wbmpx_ptr;
4292 if(!wbms) {
4293 END_PROFILE(SMBwriteBs);
4294 return(-1);
4297 /* If write through is set we can return errors, else we must cache them */
4298 write_through = wbms->wr_mode;
4300 /* Check for an earlier error */
4301 if(wbms->wr_discard) {
4302 END_PROFILE(SMBwriteBs);
4303 return -1; /* Just discard the packet */
4306 nwritten = write_file(fsp,data,startpos,numtowrite);
4308 if(lp_syncalways(SNUM(conn)) || write_through)
4309 sync_file(conn,fsp);
4311 if (nwritten < (ssize_t)numtowrite) {
4312 if(write_through) {
4313 /* We are returning an error - we can delete the aux struct */
4314 if (wbms)
4315 free((char *)wbms);
4316 fsp->wbmpx_ptr = NULL;
4317 END_PROFILE(SMBwriteBs);
4318 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4320 END_PROFILE(SMBwriteBs);
4321 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4324 /* Increment the total written, if this matches tcount
4325 we can discard the auxiliary struct (hurrah !) and return a writeC */
4326 wbms->wr_total_written += nwritten;
4327 if(wbms->wr_total_written >= tcount) {
4328 if (write_through) {
4329 outsize = set_message(outbuf,1,0,True);
4330 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4331 send_response = True;
4334 free((char *)wbms);
4335 fsp->wbmpx_ptr = NULL;
4338 if(send_response) {
4339 END_PROFILE(SMBwriteBs);
4340 return(outsize);
4343 END_PROFILE(SMBwriteBs);
4344 return(-1);
4347 /****************************************************************************
4348 Reply to a SMBgetattrE.
4349 ****************************************************************************/
4351 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4353 SMB_STRUCT_STAT sbuf;
4354 int outsize = 0;
4355 int mode;
4356 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4357 START_PROFILE(SMBgetattrE);
4359 outsize = set_message(outbuf,11,0,True);
4361 if(!fsp || (fsp->conn != conn)) {
4362 END_PROFILE(SMBgetattrE);
4363 return ERROR_DOS(ERRDOS,ERRbadfid);
4366 /* Do an fstat on this file */
4367 if(fsp_stat(fsp, &sbuf)) {
4368 END_PROFILE(SMBgetattrE);
4369 return(UNIXERROR(ERRDOS,ERRnoaccess));
4372 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4375 * Convert the times into dos times. Set create
4376 * date to be last modify date as UNIX doesn't save
4377 * this.
4380 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4381 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4382 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4384 if (mode & aDIR) {
4385 SIVAL(outbuf,smb_vwv6,0);
4386 SIVAL(outbuf,smb_vwv8,0);
4387 } else {
4388 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4389 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4390 SIVAL(outbuf,smb_vwv8,allocation_size);
4392 SSVAL(outbuf,smb_vwv10, mode);
4394 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4396 END_PROFILE(SMBgetattrE);
4397 return(outsize);