This only touches the fake kaserver support. It adds two parameters:
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
blob6ac4cffddb4eaf3a542e007a33c9bb02585d15f3
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 Ensure we check the path in the same way as W2K.
43 ****************************************************************************/
45 static NTSTATUS check_path_syntax(const char *name)
47 while (*name == '\\')
48 name++;
49 if (strequal(name, "."))
50 return NT_STATUS_OBJECT_NAME_INVALID;
51 else if (strequal(name, ".."))
52 return NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
53 return NT_STATUS_OK;
56 /****************************************************************************
57 Reply to a special message.
58 ****************************************************************************/
60 int reply_special(char *inbuf,char *outbuf)
62 int outsize = 4;
63 int msg_type = CVAL(inbuf,0);
64 int msg_flags = CVAL(inbuf,1);
65 pstring name1,name2;
66 char name_type = 0;
68 static BOOL already_got_session = False;
70 *name1 = *name2 = 0;
72 memset(outbuf,'\0',smb_size);
74 smb_setlen(outbuf,0);
76 switch (msg_type) {
77 case 0x81: /* session request */
79 if (already_got_session) {
80 exit_server("multiple session request not permitted");
83 SCVAL(outbuf,0,0x82);
84 SCVAL(outbuf,3,0);
85 if (name_len(inbuf+4) > 50 ||
86 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
87 DEBUG(0,("Invalid name length in session request\n"));
88 return(0);
90 name_extract(inbuf,4,name1);
91 name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2);
92 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
93 name1,name2));
95 set_local_machine_name(name1, True);
96 set_remote_machine_name(name2, True);
98 DEBUG(2,("netbios connect: local=%s remote=%s, name type = %x\n",
99 get_local_machine_name(), get_remote_machine_name(),
100 name_type));
102 if (name_type == 'R') {
103 /* We are being asked for a pathworks session ---
104 no thanks! */
105 SCVAL(outbuf, 0,0x83);
106 break;
109 /* only add the client's machine name to the list
110 of possibly valid usernames if we are operating
111 in share mode security */
112 if (lp_security() == SEC_SHARE) {
113 add_session_user(get_remote_machine_name());
116 reload_services(True);
117 reopen_logs();
119 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
121 already_got_session = True;
122 break;
124 case 0x89: /* session keepalive request
125 (some old clients produce this?) */
126 SCVAL(outbuf,0,SMBkeepalive);
127 SCVAL(outbuf,3,0);
128 break;
130 case 0x82: /* positive session response */
131 case 0x83: /* negative session response */
132 case 0x84: /* retarget session response */
133 DEBUG(0,("Unexpected session response\n"));
134 break;
136 case SMBkeepalive: /* session keepalive */
137 default:
138 return(0);
141 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
142 msg_type, msg_flags));
144 return(outsize);
147 /****************************************************************************
148 Reply to a tcon.
149 ****************************************************************************/
151 int reply_tcon(connection_struct *conn,
152 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
154 const char *service;
155 pstring service_buf;
156 pstring password;
157 pstring dev;
158 int outsize = 0;
159 uint16 vuid = SVAL(inbuf,smb_uid);
160 int pwlen=0;
161 NTSTATUS nt_status;
162 char *p;
163 DATA_BLOB password_blob;
165 START_PROFILE(SMBtcon);
167 *service_buf = *password = *dev = 0;
169 p = smb_buf(inbuf)+1;
170 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
171 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
172 p += pwlen;
173 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
175 p = strrchr_m(service_buf,'\\');
176 if (p) {
177 service = p+1;
178 } else {
179 service = service_buf;
182 password_blob = data_blob(password, pwlen+1);
184 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
186 data_blob_clear_free(&password_blob);
188 if (!conn) {
189 END_PROFILE(SMBtcon);
190 return ERROR_NT(nt_status);
193 outsize = set_message(outbuf,2,0,True);
194 SSVAL(outbuf,smb_vwv0,max_recv);
195 SSVAL(outbuf,smb_vwv1,conn->cnum);
196 SSVAL(outbuf,smb_tid,conn->cnum);
198 DEBUG(3,("tcon service=%s cnum=%d\n",
199 service, conn->cnum));
201 END_PROFILE(SMBtcon);
202 return(outsize);
205 /****************************************************************************
206 Reply to a tcon and X.
207 ****************************************************************************/
209 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
211 fstring service;
212 DATA_BLOB password;
214 /* what the cleint thinks the device is */
215 fstring client_devicetype;
216 /* what the server tells the client the share represents */
217 const char *server_devicetype;
218 NTSTATUS nt_status;
219 uint16 vuid = SVAL(inbuf,smb_uid);
220 int passlen = SVAL(inbuf,smb_vwv3);
221 pstring path;
222 char *p, *q;
223 extern BOOL global_encrypted_passwords_negotiated;
225 START_PROFILE(SMBtconX);
227 *service = *client_devicetype = 0;
229 /* we might have to close an old one */
230 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
231 close_cnum(conn,vuid);
234 if (passlen > MAX_PASS_LEN) {
235 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
238 if (global_encrypted_passwords_negotiated) {
239 password = data_blob(smb_buf(inbuf),passlen);
240 } else {
241 password = data_blob(smb_buf(inbuf),passlen+1);
242 /* Ensure correct termination */
243 password.data[passlen]=0;
246 p = smb_buf(inbuf) + passlen;
247 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
250 * the service name can be either: \\server\share
251 * or share directly like on the DELL PowerVault 705
253 if (*path=='\\') {
254 q = strchr_m(path+2,'\\');
255 if (!q) {
256 END_PROFILE(SMBtconX);
257 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
259 fstrcpy(service,q+1);
261 else
262 fstrcpy(service,path);
264 p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
266 DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
268 conn = make_connection(service,password,client_devicetype,vuid,&nt_status);
270 data_blob_clear_free(&password);
272 if (!conn) {
273 END_PROFILE(SMBtconX);
274 return ERROR_NT(nt_status);
277 if ( IS_IPC(conn) )
278 server_devicetype = "IPC";
279 else if ( IS_PRINT(conn) )
280 server_devicetype = "LPT1:";
281 else
282 server_devicetype = "A:";
284 if (Protocol < PROTOCOL_NT1) {
285 set_message(outbuf,2,0,True);
286 p = smb_buf(outbuf);
287 p += srvstr_push(outbuf, p, server_devicetype, -1,
288 STR_TERMINATE|STR_ASCII);
289 set_message_end(outbuf,p);
290 } else {
291 /* NT sets the fstype of IPC$ to the null string */
292 const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
294 set_message(outbuf,3,0,True);
296 p = smb_buf(outbuf);
297 p += srvstr_push(outbuf, p, server_devicetype, -1,
298 STR_TERMINATE|STR_ASCII);
299 p += srvstr_push(outbuf, p, fstype, -1,
300 STR_TERMINATE);
302 set_message_end(outbuf,p);
304 /* what does setting this bit do? It is set by NT4 and
305 may affect the ability to autorun mounted cdroms */
306 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
307 (lp_csc_policy(SNUM(conn)) << 2));
309 init_dfsroot(conn, inbuf, outbuf);
313 DEBUG(3,("tconX service=%s \n",
314 service));
316 /* set the incoming and outgoing tid to the just created one */
317 SSVAL(inbuf,smb_tid,conn->cnum);
318 SSVAL(outbuf,smb_tid,conn->cnum);
320 END_PROFILE(SMBtconX);
321 return chain_reply(inbuf,outbuf,length,bufsize);
324 /****************************************************************************
325 Reply to an unknown type.
326 ****************************************************************************/
328 int reply_unknown(char *inbuf,char *outbuf)
330 int type;
331 type = CVAL(inbuf,smb_com);
333 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
334 smb_fn_name(type), type, type));
336 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
339 /****************************************************************************
340 Reply to an ioctl.
341 ****************************************************************************/
343 int reply_ioctl(connection_struct *conn,
344 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
346 uint16 device = SVAL(inbuf,smb_vwv1);
347 uint16 function = SVAL(inbuf,smb_vwv2);
348 uint32 ioctl_code = (device << 16) + function;
349 int replysize, outsize;
350 char *p;
351 START_PROFILE(SMBioctl);
353 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
355 switch (ioctl_code) {
356 case IOCTL_QUERY_JOB_INFO:
357 replysize = 32;
358 break;
359 default:
360 END_PROFILE(SMBioctl);
361 return(ERROR_DOS(ERRSRV,ERRnosupport));
364 outsize = set_message(outbuf,8,replysize+1,True);
365 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
366 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
367 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
368 p = smb_buf(outbuf) + 1; /* Allow for alignment */
370 switch (ioctl_code) {
371 case IOCTL_QUERY_JOB_INFO:
373 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
374 if (!fsp) {
375 END_PROFILE(SMBioctl);
376 return(UNIXERROR(ERRDOS,ERRbadfid));
378 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
379 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
380 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
381 break;
385 END_PROFILE(SMBioctl);
386 return outsize;
389 /****************************************************************************
390 Reply to a chkpth.
391 ****************************************************************************/
393 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
395 int outsize = 0;
396 int mode;
397 pstring name;
398 BOOL ok = False;
399 BOOL bad_path = False;
400 SMB_STRUCT_STAT sbuf;
401 NTSTATUS status;
403 START_PROFILE(SMBchkpth);
405 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
407 status = check_path_syntax(name);
408 if (!NT_STATUS_IS_OK(status))
409 return ERROR_NT(status);
411 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
413 unix_convert(name,conn,0,&bad_path,&sbuf);
415 mode = SVAL(inbuf,smb_vwv0);
417 if (check_name(name,conn)) {
418 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,name,&sbuf) == 0)
419 if (!(ok = S_ISDIR(sbuf.st_mode)))
420 errno = ENOTDIR;
423 if (!ok) {
424 /* We special case this - as when a Windows machine
425 is parsing a path is steps through the components
426 one at a time - if a component fails it expects
427 ERRbadpath, not ERRbadfile.
429 if(errno == ENOENT) {
431 * Windows returns different error codes if
432 * the parent directory is valid but not the
433 * last component - it returns NT_STATUS_OBJECT_NAME_NOT_FOUND
434 * for that case and NT_STATUS_OBJECT_PATH_NOT_FOUND
435 * if the path is invalid.
437 if (bad_path) {
438 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
439 } else {
440 return ERROR_NT(NT_STATUS_OBJECT_NAME_NOT_FOUND);
442 } else if (errno == ENOTDIR)
443 return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY);
445 return(UNIXERROR(ERRDOS,ERRbadpath));
448 outsize = set_message(outbuf,0,0,True);
450 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
452 END_PROFILE(SMBchkpth);
453 return(outsize);
456 /****************************************************************************
457 Reply to a getatr.
458 ****************************************************************************/
460 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
462 pstring fname;
463 int outsize = 0;
464 SMB_STRUCT_STAT sbuf;
465 BOOL ok = False;
466 int mode=0;
467 SMB_OFF_T size=0;
468 time_t mtime=0;
469 BOOL bad_path = False;
470 char *p;
471 START_PROFILE(SMBgetatr);
473 p = smb_buf(inbuf) + 1;
474 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
476 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
478 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
479 under WfWg - weird! */
480 if (! (*fname)) {
481 mode = aHIDDEN | aDIR;
482 if (!CAN_WRITE(conn))
483 mode |= aRONLY;
484 size = 0;
485 mtime = 0;
486 ok = True;
487 } else {
488 unix_convert(fname,conn,0,&bad_path,&sbuf);
489 if (check_name(fname,conn)) {
490 if (VALID_STAT(sbuf) || SMB_VFS_STAT(conn,fname,&sbuf) == 0) {
491 mode = dos_mode(conn,fname,&sbuf);
492 size = sbuf.st_size;
493 mtime = sbuf.st_mtime;
494 if (mode & aDIR)
495 size = 0;
496 ok = True;
497 } else {
498 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
503 if (!ok) {
504 END_PROFILE(SMBgetatr);
505 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS,ERRbadfile);
508 outsize = set_message(outbuf,10,0,True);
510 SSVAL(outbuf,smb_vwv0,mode);
511 if(lp_dos_filetime_resolution(SNUM(conn)) )
512 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
513 else
514 put_dos_date3(outbuf,smb_vwv1,mtime);
515 SIVAL(outbuf,smb_vwv3,(uint32)size);
517 if (Protocol >= PROTOCOL_NT1)
518 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
520 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
522 END_PROFILE(SMBgetatr);
523 return(outsize);
526 /****************************************************************************
527 Reply to a setatr.
528 ****************************************************************************/
530 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
532 pstring fname;
533 int outsize = 0;
534 BOOL ok=False;
535 int mode;
536 time_t mtime;
537 SMB_STRUCT_STAT sbuf;
538 BOOL bad_path = False;
539 char *p;
541 START_PROFILE(SMBsetatr);
543 p = smb_buf(inbuf) + 1;
544 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
545 unix_convert(fname,conn,0,&bad_path,&sbuf);
547 mode = SVAL(inbuf,smb_vwv0);
548 mtime = make_unix_date3(inbuf+smb_vwv1);
550 if (mode != FILE_ATTRIBUTE_NORMAL) {
551 if (VALID_STAT_OF_DIR(sbuf))
552 mode |= aDIR;
553 else
554 mode &= ~aDIR;
556 if (check_name(fname,conn))
557 ok = (file_chmod(conn,fname,mode,NULL) == 0);
558 } else {
559 ok = True;
562 if (ok)
563 ok = set_filetime(conn,fname,mtime);
565 if (!ok) {
566 END_PROFILE(SMBsetatr);
567 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
570 outsize = set_message(outbuf,0,0,True);
572 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
574 END_PROFILE(SMBsetatr);
575 return(outsize);
578 /****************************************************************************
579 Reply to a dskattr.
580 ****************************************************************************/
582 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
584 int outsize = 0;
585 SMB_BIG_UINT dfree,dsize,bsize;
586 START_PROFILE(SMBdskattr);
588 SMB_VFS_DISK_FREE(conn,".",True,&bsize,&dfree,&dsize);
590 outsize = set_message(outbuf,5,0,True);
592 if (Protocol <= PROTOCOL_LANMAN2) {
593 double total_space, free_space;
594 /* we need to scale this to a number that DOS6 can handle. We
595 use floating point so we can handle large drives on systems
596 that don't have 64 bit integers
598 we end up displaying a maximum of 2G to DOS systems
600 total_space = dsize * (double)bsize;
601 free_space = dfree * (double)bsize;
603 dsize = (total_space+63*512) / (64*512);
604 dfree = (free_space+63*512) / (64*512);
606 if (dsize > 0xFFFF) dsize = 0xFFFF;
607 if (dfree > 0xFFFF) dfree = 0xFFFF;
609 SSVAL(outbuf,smb_vwv0,dsize);
610 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
611 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
612 SSVAL(outbuf,smb_vwv3,dfree);
613 } else {
614 SSVAL(outbuf,smb_vwv0,dsize);
615 SSVAL(outbuf,smb_vwv1,bsize/512);
616 SSVAL(outbuf,smb_vwv2,512);
617 SSVAL(outbuf,smb_vwv3,dfree);
620 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
622 END_PROFILE(SMBdskattr);
623 return(outsize);
626 /****************************************************************************
627 Reply to a search.
628 Can be called from SMBsearch, SMBffirst or SMBfunique.
629 ****************************************************************************/
631 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
633 pstring mask;
634 pstring directory;
635 pstring fname;
636 SMB_OFF_T size;
637 int mode;
638 time_t date;
639 int dirtype;
640 int outsize = 0;
641 int numentries = 0;
642 BOOL finished = False;
643 int maxentries;
644 int i;
645 char *p;
646 BOOL ok = False;
647 int status_len;
648 pstring path;
649 char status[21];
650 int dptr_num= -1;
651 BOOL check_descend = False;
652 BOOL expect_close = False;
653 BOOL can_open = True;
654 BOOL bad_path = False;
655 START_PROFILE(SMBsearch);
657 *mask = *directory = *fname = 0;
659 /* If we were called as SMBffirst then we must expect close. */
660 if(CVAL(inbuf,smb_com) == SMBffirst)
661 expect_close = True;
663 outsize = set_message(outbuf,1,3,True);
664 maxentries = SVAL(inbuf,smb_vwv0);
665 dirtype = SVAL(inbuf,smb_vwv1);
666 p = smb_buf(inbuf) + 1;
667 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
668 p++;
669 status_len = SVAL(p, 0);
670 p += 2;
672 /* dirtype &= ~aDIR; */
674 if (status_len == 0) {
675 SMB_STRUCT_STAT sbuf;
676 pstring dir2;
678 pstrcpy(directory,path);
679 pstrcpy(dir2,path);
680 unix_convert(directory,conn,0,&bad_path,&sbuf);
681 unix_format(dir2);
683 if (!check_name(directory,conn))
684 can_open = False;
686 p = strrchr_m(dir2,'/');
687 if (p == NULL) {
688 pstrcpy(mask,dir2);
689 *dir2 = 0;
690 } else {
691 *p = 0;
692 pstrcpy(mask,p+1);
695 p = strrchr_m(directory,'/');
696 if (!p)
697 *directory = 0;
698 else
699 *p = 0;
701 if (strlen(directory) == 0)
702 pstrcpy(directory,".");
703 memset((char *)status,'\0',21);
704 SCVAL(status,0,(dirtype & 0x1F));
705 } else {
706 int status_dirtype;
708 memcpy(status,p,21);
709 status_dirtype = CVAL(status,0) & 0x1F;
710 if (status_dirtype != (dirtype & 0x1F))
711 dirtype = status_dirtype;
713 conn->dirptr = dptr_fetch(status+12,&dptr_num);
714 if (!conn->dirptr)
715 goto SearchEmpty;
716 string_set(&conn->dirpath,dptr_path(dptr_num));
717 pstrcpy(mask, dptr_wcard(dptr_num));
720 if (can_open) {
721 p = smb_buf(outbuf) + 3;
722 ok = True;
724 if (status_len == 0) {
725 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
726 if (dptr_num < 0) {
727 if(dptr_num == -2) {
728 END_PROFILE(SMBsearch);
729 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnofids);
731 END_PROFILE(SMBsearch);
732 return ERROR_DOS(ERRDOS,ERRnofids);
734 dptr_set_wcard(dptr_num, strdup(mask));
735 dptr_set_attr(dptr_num, dirtype);
736 } else {
737 dirtype = dptr_attr(dptr_num);
740 DEBUG(4,("dptr_num is %d\n",dptr_num));
742 if (ok) {
743 if ((dirtype&0x1F) == aVOLID) {
744 memcpy(p,status,21);
745 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
746 dptr_fill(p+12,dptr_num);
747 if (dptr_zero(p+12) && (status_len==0))
748 numentries = 1;
749 else
750 numentries = 0;
751 p += DIR_STRUCT_SIZE;
752 } else {
753 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
754 conn->dirpath,lp_dontdescend(SNUM(conn))));
755 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
756 check_descend = True;
758 for (i=numentries;(i<maxentries) && !finished;i++) {
759 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
760 if (!finished) {
761 memcpy(p,status,21);
762 make_dir_struct(p,mask,fname,size,mode,date);
763 dptr_fill(p+12,dptr_num);
764 numentries++;
766 p += DIR_STRUCT_SIZE;
769 } /* if (ok ) */
773 SearchEmpty:
775 /* If we were called as SMBffirst with smb_search_id == NULL
776 and no entries were found then return error and close dirptr
777 (X/Open spec) */
779 if(ok && expect_close && numentries == 0 && status_len == 0) {
780 if (Protocol < PROTOCOL_NT1) {
781 SCVAL(outbuf,smb_rcls,ERRDOS);
782 SSVAL(outbuf,smb_err,ERRnofiles);
784 /* Also close the dptr - we know it's gone */
785 dptr_close(&dptr_num);
786 } else if (numentries == 0 || !ok) {
787 if (Protocol < PROTOCOL_NT1) {
788 SCVAL(outbuf,smb_rcls,ERRDOS);
789 SSVAL(outbuf,smb_err,ERRnofiles);
791 dptr_close(&dptr_num);
794 /* If we were called as SMBfunique, then we can close the dirptr now ! */
795 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
796 dptr_close(&dptr_num);
798 SSVAL(outbuf,smb_vwv0,numentries);
799 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
800 SCVAL(smb_buf(outbuf),0,5);
801 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
803 if (Protocol >= PROTOCOL_NT1)
804 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
806 outsize += DIR_STRUCT_SIZE*numentries;
807 smb_setlen(outbuf,outsize - 4);
809 if ((! *directory) && dptr_path(dptr_num))
810 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
812 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
813 smb_fn_name(CVAL(inbuf,smb_com)),
814 mask, directory, dirtype, numentries, maxentries ) );
816 END_PROFILE(SMBsearch);
817 return(outsize);
820 /****************************************************************************
821 Reply to a fclose (stop directory search).
822 ****************************************************************************/
824 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
826 int outsize = 0;
827 int status_len;
828 pstring path;
829 char status[21];
830 int dptr_num= -2;
831 char *p;
833 START_PROFILE(SMBfclose);
835 outsize = set_message(outbuf,1,0,True);
836 p = smb_buf(inbuf) + 1;
837 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
838 p++;
839 status_len = SVAL(p,0);
840 p += 2;
842 if (status_len == 0) {
843 END_PROFILE(SMBfclose);
844 return ERROR_DOS(ERRSRV,ERRsrverror);
847 memcpy(status,p,21);
849 if(dptr_fetch(status+12,&dptr_num)) {
850 /* Close the dptr - we know it's gone */
851 dptr_close(&dptr_num);
854 SSVAL(outbuf,smb_vwv0,0);
856 DEBUG(3,("search close\n"));
858 END_PROFILE(SMBfclose);
859 return(outsize);
862 /****************************************************************************
863 Reply to an open.
864 ****************************************************************************/
866 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
868 pstring fname;
869 int outsize = 0;
870 int fmode=0;
871 int share_mode;
872 SMB_OFF_T size = 0;
873 time_t mtime=0;
874 mode_t unixmode;
875 int rmode=0;
876 SMB_STRUCT_STAT sbuf;
877 BOOL bad_path = False;
878 files_struct *fsp;
879 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
880 START_PROFILE(SMBopen);
882 share_mode = SVAL(inbuf,smb_vwv0);
884 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
886 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
888 unix_convert(fname,conn,0,&bad_path,&sbuf);
890 unixmode = unix_mode(conn,aARCH,fname);
892 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
893 unixmode, oplock_request,&rmode,NULL);
895 if (!fsp) {
896 END_PROFILE(SMBopen);
897 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
900 size = sbuf.st_size;
901 fmode = dos_mode(conn,fname,&sbuf);
902 mtime = sbuf.st_mtime;
904 if (fmode & aDIR) {
905 DEBUG(3,("attempt to open a directory %s\n",fname));
906 close_file(fsp,False);
907 END_PROFILE(SMBopen);
908 return ERROR_DOS(ERRDOS,ERRnoaccess);
911 outsize = set_message(outbuf,7,0,True);
912 SSVAL(outbuf,smb_vwv0,fsp->fnum);
913 SSVAL(outbuf,smb_vwv1,fmode);
914 if(lp_dos_filetime_resolution(SNUM(conn)) )
915 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
916 else
917 put_dos_date3(outbuf,smb_vwv2,mtime);
918 SIVAL(outbuf,smb_vwv4,(uint32)size);
919 SSVAL(outbuf,smb_vwv6,rmode);
921 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
922 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
924 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
925 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
926 END_PROFILE(SMBopen);
927 return(outsize);
930 /****************************************************************************
931 Reply to an open and X.
932 ****************************************************************************/
934 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
936 pstring fname;
937 int smb_mode = SVAL(inbuf,smb_vwv3);
938 int smb_attr = SVAL(inbuf,smb_vwv5);
939 /* Breakout the oplock request bits so we can set the
940 reply bits separately. */
941 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
942 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
943 BOOL oplock_request = ex_oplock_request | core_oplock_request;
944 #if 0
945 int open_flags = SVAL(inbuf,smb_vwv2);
946 int smb_sattr = SVAL(inbuf,smb_vwv4);
947 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
948 #endif
949 int smb_ofun = SVAL(inbuf,smb_vwv8);
950 mode_t unixmode;
951 SMB_OFF_T size=0;
952 int fmode=0,mtime=0,rmode=0;
953 SMB_STRUCT_STAT sbuf;
954 int smb_action = 0;
955 BOOL bad_path = False;
956 files_struct *fsp;
957 START_PROFILE(SMBopenX);
959 /* If it's an IPC, pass off the pipe handler. */
960 if (IS_IPC(conn)) {
961 if (lp_nt_pipe_support()) {
962 END_PROFILE(SMBopenX);
963 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
964 } else {
965 END_PROFILE(SMBopenX);
966 return ERROR_DOS(ERRSRV,ERRaccess);
970 /* XXXX we need to handle passed times, sattr and flags */
971 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
973 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
975 unix_convert(fname,conn,0,&bad_path,&sbuf);
977 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
979 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
980 oplock_request, &rmode,&smb_action);
982 if (!fsp) {
983 END_PROFILE(SMBopenX);
984 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
987 size = sbuf.st_size;
988 fmode = dos_mode(conn,fname,&sbuf);
989 mtime = sbuf.st_mtime;
990 if (fmode & aDIR) {
991 close_file(fsp,False);
992 END_PROFILE(SMBopenX);
993 return ERROR_DOS(ERRDOS,ERRnoaccess);
996 /* If the caller set the extended oplock request bit
997 and we granted one (by whatever means) - set the
998 correct bit for extended oplock reply.
1001 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
1002 smb_action |= EXTENDED_OPLOCK_GRANTED;
1004 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1005 smb_action |= EXTENDED_OPLOCK_GRANTED;
1007 /* If the caller set the core oplock request bit
1008 and we granted one (by whatever means) - set the
1009 correct bit for core oplock reply.
1012 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
1013 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1015 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1016 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1018 set_message(outbuf,15,0,True);
1019 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1020 SSVAL(outbuf,smb_vwv3,fmode);
1021 if(lp_dos_filetime_resolution(SNUM(conn)) )
1022 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1023 else
1024 put_dos_date3(outbuf,smb_vwv4,mtime);
1025 SIVAL(outbuf,smb_vwv6,(uint32)size);
1026 SSVAL(outbuf,smb_vwv8,rmode);
1027 SSVAL(outbuf,smb_vwv11,smb_action);
1029 END_PROFILE(SMBopenX);
1030 return chain_reply(inbuf,outbuf,length,bufsize);
1033 /****************************************************************************
1034 Reply to a SMBulogoffX.
1035 ****************************************************************************/
1037 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1039 uint16 vuid = SVAL(inbuf,smb_uid);
1040 user_struct *vuser = get_valid_user_struct(vuid);
1041 START_PROFILE(SMBulogoffX);
1043 if(vuser == 0)
1044 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1046 /* in user level security we are supposed to close any files
1047 open by this user */
1048 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1049 file_close_user(vuid);
1051 invalidate_vuid(vuid);
1053 set_message(outbuf,2,0,True);
1055 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1057 END_PROFILE(SMBulogoffX);
1058 return chain_reply(inbuf,outbuf,length,bufsize);
1061 /****************************************************************************
1062 Reply to a mknew or a create.
1063 ****************************************************************************/
1065 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1067 pstring fname;
1068 int com;
1069 int outsize = 0;
1070 int createmode;
1071 mode_t unixmode;
1072 int ofun = 0;
1073 BOOL bad_path = False;
1074 files_struct *fsp;
1075 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1076 SMB_STRUCT_STAT sbuf;
1077 START_PROFILE(SMBcreate);
1079 com = SVAL(inbuf,smb_com);
1081 createmode = SVAL(inbuf,smb_vwv0);
1082 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
1084 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1086 unix_convert(fname,conn,0,&bad_path,&sbuf);
1088 if (createmode & aVOLID)
1089 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1091 unixmode = unix_mode(conn,createmode,fname);
1093 if(com == SMBmknew) {
1094 /* We should fail if file exists. */
1095 ofun = FILE_CREATE_IF_NOT_EXIST;
1096 } else {
1097 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1098 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1101 /* Open file in dos compatibility share mode. */
1102 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1103 ofun, unixmode, oplock_request, NULL, NULL);
1105 if (!fsp) {
1106 END_PROFILE(SMBcreate);
1107 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1110 outsize = set_message(outbuf,1,0,True);
1111 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1113 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1114 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1116 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1117 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1119 DEBUG( 2, ( "new file %s\n", fname ) );
1120 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1122 END_PROFILE(SMBcreate);
1123 return(outsize);
1126 /****************************************************************************
1127 Reply to a create temporary file.
1128 ****************************************************************************/
1130 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1132 pstring fname;
1133 int outsize = 0;
1134 int createmode;
1135 mode_t unixmode;
1136 BOOL bad_path = False;
1137 files_struct *fsp;
1138 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1139 int tmpfd;
1140 SMB_STRUCT_STAT sbuf;
1141 char *p, *s;
1143 START_PROFILE(SMBctemp);
1145 createmode = SVAL(inbuf,smb_vwv0);
1146 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1147 pstrcat(fname,"\\TMXXXXXX");
1149 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1151 unix_convert(fname,conn,0,&bad_path,&sbuf);
1153 unixmode = unix_mode(conn,createmode,fname);
1155 tmpfd = smb_mkstemp(fname);
1156 if (tmpfd == -1) {
1157 END_PROFILE(SMBctemp);
1158 return(UNIXERROR(ERRDOS,ERRnoaccess));
1161 SMB_VFS_STAT(conn,fname,&sbuf);
1163 /* Open file in dos compatibility share mode. */
1164 /* We should fail if file does not exist. */
1165 fsp = open_file_shared(conn,fname,&sbuf,
1166 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1167 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1168 unixmode, oplock_request, NULL, NULL);
1170 /* close fd from smb_mkstemp() */
1171 close(tmpfd);
1173 if (!fsp) {
1174 END_PROFILE(SMBctemp);
1175 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRnoaccess);
1178 outsize = set_message(outbuf,1,0,True);
1179 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1181 /* the returned filename is relative to the directory */
1182 s = strrchr_m(fname, '/');
1183 if (!s)
1184 s = fname;
1185 else
1186 s++;
1188 p = smb_buf(outbuf);
1189 SSVALS(p, 0, -1); /* what is this? not in spec */
1190 SSVAL(p, 2, strlen(s));
1191 p += 4;
1192 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1193 outsize = set_message_end(outbuf, p);
1195 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1196 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1198 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1199 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1201 DEBUG( 2, ( "created temp file %s\n", fname ) );
1202 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1203 fname, fsp->fd, createmode, (int)unixmode ) );
1205 END_PROFILE(SMBctemp);
1206 return(outsize);
1209 /*******************************************************************
1210 Check if a user is allowed to rename a file.
1211 ********************************************************************/
1213 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1215 int smb_action;
1216 int access_mode;
1217 files_struct *fsp;
1219 if (!CAN_WRITE(conn))
1220 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1222 if (S_ISDIR(pst->st_mode))
1223 return NT_STATUS_OK;
1225 /* We need a better way to return NT status codes from open... */
1226 unix_ERR_class = 0;
1227 unix_ERR_code = 0;
1229 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1230 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1232 if (!fsp) {
1233 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1234 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1235 ret = NT_STATUS_SHARING_VIOLATION;
1236 unix_ERR_class = 0;
1237 unix_ERR_code = 0;
1238 return ret;
1240 close_file(fsp,False);
1241 return NT_STATUS_OK;
1244 /*******************************************************************
1245 Check if a user is allowed to delete a file.
1246 ********************************************************************/
1248 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1250 SMB_STRUCT_STAT sbuf;
1251 int fmode;
1252 int smb_action;
1253 int access_mode;
1254 files_struct *fsp;
1256 DEBUG(10,("can_delete: %s, dirtype = %d\n",
1257 fname, dirtype ));
1259 if (!CAN_WRITE(conn))
1260 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1262 if (SMB_VFS_LSTAT(conn,fname,&sbuf) != 0)
1263 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1265 fmode = dos_mode(conn,fname,&sbuf);
1267 /* Can't delete a directory. */
1268 if (fmode & aDIR)
1269 return NT_STATUS_FILE_IS_A_DIRECTORY;
1270 #if 0 /* JRATEST */
1271 else if (dirtype & aDIR) /* Asked for a directory and it isn't. */
1272 return NT_STATUS_OBJECT_NAME_INVALID;
1273 #endif /* JRATEST */
1275 if (!lp_delete_readonly(SNUM(conn))) {
1276 if (fmode & aRONLY)
1277 return NT_STATUS_CANNOT_DELETE;
1279 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1280 return NT_STATUS_NO_SUCH_FILE;
1282 /* We need a better way to return NT status codes from open... */
1283 unix_ERR_class = 0;
1284 unix_ERR_code = 0;
1286 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1287 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1289 if (!fsp) {
1290 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1291 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1292 ret = unix_ERR_ntstatus;
1293 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1294 ret = NT_STATUS_SHARING_VIOLATION;
1295 unix_ERR_class = 0;
1296 unix_ERR_code = 0;
1297 unix_ERR_ntstatus = NT_STATUS_OK;
1298 return ret;
1300 close_file(fsp,False);
1301 return NT_STATUS_OK;
1304 /****************************************************************************
1305 The guts of the unlink command, split out so it may be called by the NT SMB
1306 code.
1307 ****************************************************************************/
1309 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1311 pstring directory;
1312 pstring mask;
1313 char *p;
1314 int count=0;
1315 NTSTATUS error = NT_STATUS_OK;
1316 BOOL has_wild;
1317 BOOL bad_path = False;
1318 BOOL rc = True;
1319 SMB_STRUCT_STAT sbuf;
1321 *directory = *mask = 0;
1323 /* We must check for wildcards in the name given
1324 * directly by the client - before any unmangling.
1325 * This prevents an unmangling of a UNIX name containing
1326 * a DOS wildcard like '*' or '?' from unmangling into
1327 * a wildcard delete which was not intended.
1328 * FIX for #226. JRA.
1331 has_wild = ms_has_wild(name);
1333 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1335 p = strrchr_m(name,'/');
1336 if (!p) {
1337 pstrcpy(directory,".");
1338 pstrcpy(mask,name);
1339 } else {
1340 *p = 0;
1341 pstrcpy(directory,name);
1342 pstrcpy(mask,p+1);
1346 * We should only check the mangled cache
1347 * here if unix_convert failed. This means
1348 * that the path in 'mask' doesn't exist
1349 * on the file system and so we need to look
1350 * for a possible mangle. This patch from
1351 * Tine Smukavec <valentin.smukavec@hermes.si>.
1354 if (!rc && mangle_is_mangled(mask))
1355 mangle_check_cache( mask );
1357 if (!has_wild) {
1358 pstrcat(directory,"/");
1359 pstrcat(directory,mask);
1360 error = can_delete(directory,conn,dirtype);
1361 if (!NT_STATUS_IS_OK(error))
1362 return error;
1364 if (SMB_VFS_UNLINK(conn,directory) == 0) {
1365 count++;
1367 } else {
1368 void *dirptr = NULL;
1369 const char *dname;
1371 if (check_name(directory,conn))
1372 dirptr = OpenDir(conn, directory, True);
1374 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1375 the pattern matches against the long name, otherwise the short name
1376 We don't implement this yet XXXX
1379 if (dirptr) {
1380 error = NT_STATUS_NO_SUCH_FILE;
1382 if (strequal(mask,"????????.???"))
1383 pstrcpy(mask,"*");
1385 while ((dname = ReadDirName(dirptr))) {
1386 pstring fname;
1387 pstrcpy(fname,dname);
1389 if(!mask_match(fname, mask, case_sensitive))
1390 continue;
1392 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1393 error = can_delete(fname,conn,dirtype);
1394 if (!NT_STATUS_IS_OK(error))
1395 continue;
1396 if (SMB_VFS_UNLINK(conn,fname) == 0)
1397 count++;
1398 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1400 CloseDir(dirptr);
1404 if (count == 0 && NT_STATUS_IS_OK(error)) {
1405 error = map_nt_error_from_unix(errno);
1408 return error;
1411 /****************************************************************************
1412 Reply to a unlink
1413 ****************************************************************************/
1415 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1416 int dum_buffsize)
1418 int outsize = 0;
1419 pstring name;
1420 int dirtype;
1421 NTSTATUS status;
1422 START_PROFILE(SMBunlink);
1424 dirtype = SVAL(inbuf,smb_vwv0);
1426 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1428 status = check_path_syntax(name);
1429 if (!NT_STATUS_IS_OK(status))
1430 return ERROR_NT(status);
1432 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1434 DEBUG(3,("reply_unlink : %s\n",name));
1436 status = unlink_internals(conn, dirtype, name);
1437 if (!NT_STATUS_IS_OK(status))
1438 return ERROR_NT(status);
1441 * Win2k needs a changenotify request response before it will
1442 * update after a rename..
1444 process_pending_change_notify_queue((time_t)0);
1446 outsize = set_message(outbuf,0,0,True);
1448 END_PROFILE(SMBunlink);
1449 return outsize;
1452 /****************************************************************************
1453 Fail for readbraw.
1454 ****************************************************************************/
1456 void fail_readraw(void)
1458 pstring errstr;
1459 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1460 strerror(errno) );
1461 exit_server(errstr);
1464 /****************************************************************************
1465 Use sendfile in readbraw.
1466 ****************************************************************************/
1468 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1469 ssize_t mincount, char *outbuf)
1471 ssize_t ret=0;
1473 #if defined(WITH_SENDFILE)
1475 * We can only use sendfile on a non-chained packet and on a file
1476 * that is exclusively oplocked. reply_readbraw has already checked the length.
1479 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1480 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1481 DATA_BLOB header;
1483 _smb_setlen(outbuf,nread);
1484 header.data = outbuf;
1485 header.length = 4;
1486 header.free = NULL;
1488 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1490 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1491 * return ENOSYS then pretend we just got a normal read.
1493 if (errno == ENOSYS)
1494 goto normal_read;
1496 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1497 fsp->fsp_name, strerror(errno) ));
1498 exit_server("send_file_readbraw sendfile failed");
1503 normal_read:
1504 #endif
1506 if (nread > 0) {
1507 ret = read_file(fsp,outbuf+4,startpos,nread);
1508 if (ret < mincount)
1509 ret = 0;
1512 _smb_setlen(outbuf,ret);
1513 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1514 fail_readraw();
1517 /****************************************************************************
1518 Reply to a readbraw (core+ protocol).
1519 ****************************************************************************/
1521 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1523 extern struct current_user current_user;
1524 ssize_t maxcount,mincount;
1525 size_t nread = 0;
1526 SMB_OFF_T startpos;
1527 char *header = outbuf;
1528 files_struct *fsp;
1529 START_PROFILE(SMBreadbraw);
1531 if (srv_is_signing_active()) {
1532 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1536 * Special check if an oplock break has been issued
1537 * and the readraw request croses on the wire, we must
1538 * return a zero length response here.
1541 if(global_oplock_break) {
1542 _smb_setlen(header,0);
1543 if (write_data(smbd_server_fd(),header,4) != 4)
1544 fail_readraw();
1545 DEBUG(5,("readbraw - oplock break finished\n"));
1546 END_PROFILE(SMBreadbraw);
1547 return -1;
1550 fsp = file_fsp(inbuf,smb_vwv0);
1552 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1554 * fsp could be NULL here so use the value from the packet. JRA.
1556 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1557 _smb_setlen(header,0);
1558 if (write_data(smbd_server_fd(),header,4) != 4)
1559 fail_readraw();
1560 END_PROFILE(SMBreadbraw);
1561 return(-1);
1564 CHECK_FSP(fsp,conn);
1566 flush_write_cache(fsp, READRAW_FLUSH);
1568 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1569 if(CVAL(inbuf,smb_wct) == 10) {
1571 * This is a large offset (64 bit) read.
1573 #ifdef LARGE_SMB_OFF_T
1575 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1577 #else /* !LARGE_SMB_OFF_T */
1580 * Ensure we haven't been sent a >32 bit offset.
1583 if(IVAL(inbuf,smb_vwv8) != 0) {
1584 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1585 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1586 _smb_setlen(header,0);
1587 if (write_data(smbd_server_fd(),header,4) != 4)
1588 fail_readraw();
1589 END_PROFILE(SMBreadbraw);
1590 return(-1);
1593 #endif /* LARGE_SMB_OFF_T */
1595 if(startpos < 0) {
1596 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1597 _smb_setlen(header,0);
1598 if (write_data(smbd_server_fd(),header,4) != 4)
1599 fail_readraw();
1600 END_PROFILE(SMBreadbraw);
1601 return(-1);
1604 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1605 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1607 /* ensure we don't overrun the packet size */
1608 maxcount = MIN(65535,maxcount);
1609 maxcount = MAX(mincount,maxcount);
1611 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1612 SMB_OFF_T size = fsp->size;
1613 SMB_OFF_T sizeneeded = startpos + maxcount;
1615 if (size < sizeneeded) {
1616 SMB_STRUCT_STAT st;
1617 if (SMB_VFS_FSTAT(fsp,fsp->fd,&st) == 0)
1618 size = st.st_size;
1619 if (!fsp->can_write)
1620 fsp->size = size;
1623 if (startpos >= size)
1624 nread = 0;
1625 else
1626 nread = MIN(maxcount,(size - startpos));
1629 if (nread < mincount)
1630 nread = 0;
1632 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1633 (int)maxcount, (int)mincount, (int)nread ) );
1635 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1637 DEBUG(5,("readbraw finished\n"));
1638 END_PROFILE(SMBreadbraw);
1639 return -1;
1642 /****************************************************************************
1643 Reply to a lockread (core+ protocol).
1644 ****************************************************************************/
1646 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1648 ssize_t nread = -1;
1649 char *data;
1650 int outsize = 0;
1651 SMB_OFF_T startpos;
1652 size_t numtoread;
1653 NTSTATUS status;
1654 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1655 START_PROFILE(SMBlockread);
1657 CHECK_FSP(fsp,conn);
1658 CHECK_READ(fsp);
1660 release_level_2_oplocks_on_change(fsp);
1662 numtoread = SVAL(inbuf,smb_vwv1);
1663 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1665 outsize = set_message(outbuf,5,3,True);
1666 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1667 data = smb_buf(outbuf) + 3;
1670 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1671 * protocol request that predates the read/write lock concept.
1672 * Thus instead of asking for a read lock here we need to ask
1673 * for a write lock. JRA.
1676 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1677 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1679 if (NT_STATUS_V(status)) {
1680 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
1682 * A blocking lock was requested. Package up
1683 * this smb into a queued request and push it
1684 * onto the blocking lock queue.
1686 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)startpos,
1687 (SMB_BIG_UINT)numtoread)) {
1688 END_PROFILE(SMBlockread);
1689 return -1;
1692 END_PROFILE(SMBlockread);
1693 return ERROR_NT(status);
1696 nread = read_file(fsp,data,startpos,numtoread);
1698 if (nread < 0) {
1699 END_PROFILE(SMBlockread);
1700 return(UNIXERROR(ERRDOS,ERRnoaccess));
1703 outsize += nread;
1704 SSVAL(outbuf,smb_vwv0,nread);
1705 SSVAL(outbuf,smb_vwv5,nread+3);
1706 SSVAL(smb_buf(outbuf),1,nread);
1708 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1709 fsp->fnum, (int)numtoread, (int)nread));
1711 END_PROFILE(SMBlockread);
1712 return(outsize);
1715 /****************************************************************************
1716 Reply to a read.
1717 ****************************************************************************/
1719 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1721 size_t numtoread;
1722 ssize_t nread = 0;
1723 char *data;
1724 SMB_OFF_T startpos;
1725 int outsize = 0;
1726 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1727 START_PROFILE(SMBread);
1729 CHECK_FSP(fsp,conn);
1730 CHECK_READ(fsp);
1732 numtoread = SVAL(inbuf,smb_vwv1);
1733 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1735 outsize = set_message(outbuf,5,3,True);
1736 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1737 data = smb_buf(outbuf) + 3;
1739 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1740 END_PROFILE(SMBread);
1741 return ERROR_DOS(ERRDOS,ERRlock);
1744 if (numtoread > 0)
1745 nread = read_file(fsp,data,startpos,numtoread);
1747 if (nread < 0) {
1748 END_PROFILE(SMBread);
1749 return(UNIXERROR(ERRDOS,ERRnoaccess));
1752 outsize += nread;
1753 SSVAL(outbuf,smb_vwv0,nread);
1754 SSVAL(outbuf,smb_vwv5,nread+3);
1755 SCVAL(smb_buf(outbuf),0,1);
1756 SSVAL(smb_buf(outbuf),1,nread);
1758 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1759 fsp->fnum, (int)numtoread, (int)nread ) );
1761 END_PROFILE(SMBread);
1762 return(outsize);
1765 /****************************************************************************
1766 Reply to a read and X - possibly using sendfile.
1767 ****************************************************************************/
1769 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1770 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1772 ssize_t nread = -1;
1773 char *data = smb_buf(outbuf);
1775 #if defined(WITH_SENDFILE)
1777 * We can only use sendfile on a non-chained packet and on a file
1778 * that is exclusively oplocked.
1781 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1782 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1783 SMB_STRUCT_STAT sbuf;
1784 DATA_BLOB header;
1786 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1)
1787 return(UNIXERROR(ERRDOS,ERRnoaccess));
1789 if (startpos > sbuf.st_size)
1790 goto normal_read;
1792 if (smb_maxcnt > (sbuf.st_size - startpos))
1793 smb_maxcnt = (sbuf.st_size - startpos);
1795 if (smb_maxcnt == 0)
1796 goto normal_read;
1799 * Set up the packet header before send. We
1800 * assume here the sendfile will work (get the
1801 * correct amount of data).
1804 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1805 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1806 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1807 SCVAL(outbuf,smb_vwv0,0xFF);
1808 set_message(outbuf,12,smb_maxcnt,False);
1809 header.data = outbuf;
1810 header.length = data - outbuf;
1811 header.free = NULL;
1813 if ( SMB_VFS_SENDFILE( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1815 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1816 * return ENOSYS then pretend we just got a normal read.
1818 if (errno == ENOSYS)
1819 goto normal_read;
1821 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1822 fsp->fsp_name, strerror(errno) ));
1823 exit_server("send_file_readX sendfile failed");
1826 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1827 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1828 return -1;
1831 normal_read:
1833 #endif
1835 nread = read_file(fsp,data,startpos,smb_maxcnt);
1837 if (nread < 0) {
1838 END_PROFILE(SMBreadX);
1839 return(UNIXERROR(ERRDOS,ERRnoaccess));
1842 SSVAL(outbuf,smb_vwv5,nread);
1843 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1844 SSVAL(smb_buf(outbuf),-2,nread);
1846 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1847 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1849 return nread;
1852 /****************************************************************************
1853 Reply to a read and X.
1854 ****************************************************************************/
1856 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1858 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1859 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1860 ssize_t nread = -1;
1861 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1862 #if 0
1863 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1864 #endif
1866 START_PROFILE(SMBreadX);
1868 /* If it's an IPC, pass off the pipe handler. */
1869 if (IS_IPC(conn)) {
1870 END_PROFILE(SMBreadX);
1871 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1874 CHECK_FSP(fsp,conn);
1875 CHECK_READ(fsp);
1877 set_message(outbuf,12,0,True);
1879 if(CVAL(inbuf,smb_wct) == 12) {
1880 #ifdef LARGE_SMB_OFF_T
1882 * This is a large offset (64 bit) read.
1884 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1886 #else /* !LARGE_SMB_OFF_T */
1889 * Ensure we haven't been sent a >32 bit offset.
1892 if(IVAL(inbuf,smb_vwv10) != 0) {
1893 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1894 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1895 END_PROFILE(SMBreadX);
1896 return ERROR_DOS(ERRDOS,ERRbadaccess);
1899 #endif /* LARGE_SMB_OFF_T */
1903 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1904 END_PROFILE(SMBreadX);
1905 return ERROR_DOS(ERRDOS,ERRlock);
1908 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
1909 if (nread != -1)
1910 nread = chain_reply(inbuf,outbuf,length,bufsize);
1912 END_PROFILE(SMBreadX);
1913 return nread;
1916 /****************************************************************************
1917 Reply to a writebraw (core+ or LANMAN1.0 protocol).
1918 ****************************************************************************/
1920 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1922 ssize_t nwritten=0;
1923 ssize_t total_written=0;
1924 size_t numtowrite=0;
1925 size_t tcount;
1926 SMB_OFF_T startpos;
1927 char *data=NULL;
1928 BOOL write_through;
1929 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1930 int outsize = 0;
1931 START_PROFILE(SMBwritebraw);
1933 if (srv_is_signing_active()) {
1934 exit_server("reply_readbraw: SMB signing is active - raw reads/writes are disallowed.");
1937 CHECK_FSP(fsp,conn);
1938 CHECK_WRITE(fsp);
1940 tcount = IVAL(inbuf,smb_vwv1);
1941 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1942 write_through = BITSETW(inbuf+smb_vwv7,0);
1944 /* We have to deal with slightly different formats depending
1945 on whether we are using the core+ or lanman1.0 protocol */
1947 if(Protocol <= PROTOCOL_COREPLUS) {
1948 numtowrite = SVAL(smb_buf(inbuf),-2);
1949 data = smb_buf(inbuf);
1950 } else {
1951 numtowrite = SVAL(inbuf,smb_vwv10);
1952 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1955 /* force the error type */
1956 SCVAL(inbuf,smb_com,SMBwritec);
1957 SCVAL(outbuf,smb_com,SMBwritec);
1959 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1960 END_PROFILE(SMBwritebraw);
1961 return(ERROR_DOS(ERRDOS,ERRlock));
1964 if (numtowrite>0)
1965 nwritten = write_file(fsp,data,startpos,numtowrite);
1967 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1968 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1970 if (nwritten < (ssize_t)numtowrite) {
1971 END_PROFILE(SMBwritebraw);
1972 return(UNIXERROR(ERRHRD,ERRdiskfull));
1975 total_written = nwritten;
1977 /* Return a message to the redirector to tell it to send more bytes */
1978 SCVAL(outbuf,smb_com,SMBwritebraw);
1979 SSVALS(outbuf,smb_vwv0,-1);
1980 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1981 if (!send_smb(smbd_server_fd(),outbuf))
1982 exit_server("reply_writebraw: send_smb failed.");
1984 /* Now read the raw data into the buffer and write it */
1985 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1986 exit_server("secondary writebraw failed");
1989 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1990 numtowrite = smb_len(inbuf);
1992 /* Set up outbuf to return the correct return */
1993 outsize = set_message(outbuf,1,0,True);
1994 SCVAL(outbuf,smb_com,SMBwritec);
1995 SSVAL(outbuf,smb_vwv0,total_written);
1997 if (numtowrite != 0) {
1999 if (numtowrite > BUFFER_SIZE) {
2000 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
2001 (unsigned int)numtowrite ));
2002 exit_server("secondary writebraw failed");
2005 if (tcount > nwritten+numtowrite) {
2006 DEBUG(3,("Client overestimated the write %d %d %d\n",
2007 (int)tcount,(int)nwritten,(int)numtowrite));
2010 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
2011 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
2012 strerror(errno) ));
2013 exit_server("secondary writebraw failed");
2016 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
2018 if (nwritten < (ssize_t)numtowrite) {
2019 SCVAL(outbuf,smb_rcls,ERRHRD);
2020 SSVAL(outbuf,smb_err,ERRdiskfull);
2023 if (nwritten > 0)
2024 total_written += nwritten;
2027 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
2028 sync_file(conn,fsp);
2030 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
2031 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
2033 /* we won't return a status if write through is not selected - this follows what WfWg does */
2034 END_PROFILE(SMBwritebraw);
2035 if (!write_through && total_written==tcount) {
2037 #if RABBIT_PELLET_FIX
2039 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2040 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2042 if (!send_keepalive(smbd_server_fd()))
2043 exit_server("reply_writebraw: send of keepalive failed");
2044 #endif
2045 return(-1);
2048 return(outsize);
2051 /****************************************************************************
2052 Reply to a writeunlock (core+).
2053 ****************************************************************************/
2055 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2056 int size, int dum_buffsize)
2058 ssize_t nwritten = -1;
2059 size_t numtowrite;
2060 SMB_OFF_T startpos;
2061 char *data;
2062 NTSTATUS status;
2063 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2064 int outsize = 0;
2065 START_PROFILE(SMBwriteunlock);
2067 CHECK_FSP(fsp,conn);
2068 CHECK_WRITE(fsp);
2070 numtowrite = SVAL(inbuf,smb_vwv1);
2071 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2072 data = smb_buf(inbuf) + 3;
2074 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2075 WRITE_LOCK,False)) {
2076 END_PROFILE(SMBwriteunlock);
2077 return ERROR_DOS(ERRDOS,ERRlock);
2080 /* The special X/Open SMB protocol handling of
2081 zero length writes is *NOT* done for
2082 this call */
2083 if(numtowrite == 0)
2084 nwritten = 0;
2085 else
2086 nwritten = write_file(fsp,data,startpos,numtowrite);
2088 if (lp_syncalways(SNUM(conn)))
2089 sync_file(conn,fsp);
2091 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2092 END_PROFILE(SMBwriteunlock);
2093 return(UNIXERROR(ERRHRD,ERRdiskfull));
2096 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2097 (SMB_BIG_UINT)startpos);
2098 if (NT_STATUS_V(status)) {
2099 END_PROFILE(SMBwriteunlock);
2100 return ERROR_NT(status);
2103 outsize = set_message(outbuf,1,0,True);
2105 SSVAL(outbuf,smb_vwv0,nwritten);
2107 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2108 fsp->fnum, (int)numtowrite, (int)nwritten));
2110 END_PROFILE(SMBwriteunlock);
2111 return outsize;
2114 /****************************************************************************
2115 Reply to a write.
2116 ****************************************************************************/
2118 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2120 size_t numtowrite;
2121 ssize_t nwritten = -1;
2122 SMB_OFF_T startpos;
2123 char *data;
2124 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2125 int outsize = 0;
2126 START_PROFILE(SMBwrite);
2128 /* If it's an IPC, pass off the pipe handler. */
2129 if (IS_IPC(conn)) {
2130 END_PROFILE(SMBwrite);
2131 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2134 CHECK_FSP(fsp,conn);
2135 CHECK_WRITE(fsp);
2137 numtowrite = SVAL(inbuf,smb_vwv1);
2138 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2139 data = smb_buf(inbuf) + 3;
2141 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2142 END_PROFILE(SMBwrite);
2143 return ERROR_DOS(ERRDOS,ERRlock);
2147 * X/Open SMB protocol says that if smb_vwv1 is
2148 * zero then the file size should be extended or
2149 * truncated to the size given in smb_vwv[2-3].
2152 if(numtowrite == 0) {
2154 * This is actually an allocate call, and set EOF. JRA.
2156 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2157 if (nwritten < 0) {
2158 END_PROFILE(SMBwrite);
2159 return ERROR_NT(NT_STATUS_DISK_FULL);
2161 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2162 if (nwritten < 0) {
2163 END_PROFILE(SMBwrite);
2164 return ERROR_NT(NT_STATUS_DISK_FULL);
2166 } else
2167 nwritten = write_file(fsp,data,startpos,numtowrite);
2169 if (lp_syncalways(SNUM(conn)))
2170 sync_file(conn,fsp);
2172 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2173 END_PROFILE(SMBwrite);
2174 return(UNIXERROR(ERRHRD,ERRdiskfull));
2177 outsize = set_message(outbuf,1,0,True);
2179 SSVAL(outbuf,smb_vwv0,nwritten);
2181 if (nwritten < (ssize_t)numtowrite) {
2182 SCVAL(outbuf,smb_rcls,ERRHRD);
2183 SSVAL(outbuf,smb_err,ERRdiskfull);
2186 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2188 END_PROFILE(SMBwrite);
2189 return(outsize);
2192 /****************************************************************************
2193 Reply to a write and X.
2194 ****************************************************************************/
2196 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2198 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2199 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2200 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2201 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2202 ssize_t nwritten = -1;
2203 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2204 unsigned int smblen = smb_len(inbuf);
2205 char *data;
2206 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2207 START_PROFILE(SMBwriteX);
2209 /* If it's an IPC, pass off the pipe handler. */
2210 if (IS_IPC(conn)) {
2211 END_PROFILE(SMBwriteX);
2212 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2215 CHECK_FSP(fsp,conn);
2216 CHECK_WRITE(fsp);
2218 /* Deal with possible LARGE_WRITEX */
2219 if (large_writeX)
2220 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2222 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2223 END_PROFILE(SMBwriteX);
2224 return ERROR_DOS(ERRDOS,ERRbadmem);
2227 data = smb_base(inbuf) + smb_doff;
2229 if(CVAL(inbuf,smb_wct) == 14) {
2230 #ifdef LARGE_SMB_OFF_T
2232 * This is a large offset (64 bit) write.
2234 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2236 #else /* !LARGE_SMB_OFF_T */
2239 * Ensure we haven't been sent a >32 bit offset.
2242 if(IVAL(inbuf,smb_vwv12) != 0) {
2243 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2244 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2245 END_PROFILE(SMBwriteX);
2246 return ERROR_DOS(ERRDOS,ERRbadaccess);
2249 #endif /* LARGE_SMB_OFF_T */
2252 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2253 END_PROFILE(SMBwriteX);
2254 return ERROR_DOS(ERRDOS,ERRlock);
2257 /* X/Open SMB protocol says that, unlike SMBwrite
2258 if the length is zero then NO truncation is
2259 done, just a write of zero. To truncate a file,
2260 use SMBwrite. */
2262 if(numtowrite == 0)
2263 nwritten = 0;
2264 else
2265 nwritten = write_file(fsp,data,startpos,numtowrite);
2267 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2268 END_PROFILE(SMBwriteX);
2269 return(UNIXERROR(ERRHRD,ERRdiskfull));
2272 set_message(outbuf,6,0,True);
2274 SSVAL(outbuf,smb_vwv2,nwritten);
2275 if (large_writeX)
2276 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2278 if (nwritten < (ssize_t)numtowrite) {
2279 SCVAL(outbuf,smb_rcls,ERRHRD);
2280 SSVAL(outbuf,smb_err,ERRdiskfull);
2283 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2284 fsp->fnum, (int)numtowrite, (int)nwritten));
2286 if (lp_syncalways(SNUM(conn)) || write_through)
2287 sync_file(conn,fsp);
2289 END_PROFILE(SMBwriteX);
2290 return chain_reply(inbuf,outbuf,length,bufsize);
2293 /****************************************************************************
2294 Reply to a lseek.
2295 ****************************************************************************/
2297 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2299 SMB_OFF_T startpos;
2300 SMB_OFF_T res= -1;
2301 int mode,umode;
2302 int outsize = 0;
2303 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2304 START_PROFILE(SMBlseek);
2306 CHECK_FSP(fsp,conn);
2308 flush_write_cache(fsp, SEEK_FLUSH);
2310 mode = SVAL(inbuf,smb_vwv1) & 3;
2311 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2312 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2314 switch (mode) {
2315 case 0:
2316 umode = SEEK_SET;
2317 res = startpos;
2318 break;
2319 case 1:
2320 umode = SEEK_CUR;
2321 res = fsp->pos + startpos;
2322 break;
2323 case 2:
2324 umode = SEEK_END;
2325 break;
2326 default:
2327 umode = SEEK_SET;
2328 res = startpos;
2329 break;
2332 if (umode == SEEK_END) {
2333 if((res = SMB_VFS_LSEEK(fsp,fsp->fd,startpos,umode)) == -1) {
2334 if(errno == EINVAL) {
2335 SMB_OFF_T current_pos = startpos;
2336 SMB_STRUCT_STAT sbuf;
2338 if(SMB_VFS_FSTAT(fsp,fsp->fd, &sbuf) == -1) {
2339 END_PROFILE(SMBlseek);
2340 return(UNIXERROR(ERRDOS,ERRnoaccess));
2343 current_pos += sbuf.st_size;
2344 if(current_pos < 0)
2345 res = SMB_VFS_LSEEK(fsp,fsp->fd,0,SEEK_SET);
2349 if(res == -1) {
2350 END_PROFILE(SMBlseek);
2351 return(UNIXERROR(ERRDOS,ERRnoaccess));
2355 fsp->pos = res;
2357 outsize = set_message(outbuf,2,0,True);
2358 SIVAL(outbuf,smb_vwv0,res);
2360 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2361 fsp->fnum, (double)startpos, (double)res, mode));
2363 END_PROFILE(SMBlseek);
2364 return(outsize);
2367 /****************************************************************************
2368 Reply to a flush.
2369 ****************************************************************************/
2371 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2373 int outsize = set_message(outbuf,0,0,True);
2374 uint16 fnum = SVAL(inbuf,smb_vwv0);
2375 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2376 START_PROFILE(SMBflush);
2378 if (fnum != 0xFFFF)
2379 CHECK_FSP(fsp,conn);
2381 if (!fsp) {
2382 file_sync_all(conn);
2383 } else {
2384 sync_file(conn,fsp);
2387 DEBUG(3,("flush\n"));
2388 END_PROFILE(SMBflush);
2389 return(outsize);
2392 /****************************************************************************
2393 Reply to a exit.
2394 ****************************************************************************/
2396 int reply_exit(connection_struct *conn,
2397 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2399 int outsize;
2400 START_PROFILE(SMBexit);
2402 file_close_pid(SVAL(inbuf,smb_pid));
2404 outsize = set_message(outbuf,0,0,True);
2406 DEBUG(3,("exit\n"));
2408 END_PROFILE(SMBexit);
2409 return(outsize);
2412 /****************************************************************************
2413 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2414 ****************************************************************************/
2416 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2417 int dum_buffsize)
2419 extern struct current_user current_user;
2420 int outsize = 0;
2421 time_t mtime;
2422 int32 eclass = 0, err = 0;
2423 files_struct *fsp = NULL;
2424 START_PROFILE(SMBclose);
2426 outsize = set_message(outbuf,0,0,True);
2428 /* If it's an IPC, pass off to the pipe handler. */
2429 if (IS_IPC(conn)) {
2430 END_PROFILE(SMBclose);
2431 return reply_pipe_close(conn, inbuf,outbuf);
2434 fsp = file_fsp(inbuf,smb_vwv0);
2437 * We can only use CHECK_FSP if we know it's not a directory.
2440 if(!fsp || (fsp->conn != conn) || (fsp->vuid != current_user.vuid)) {
2441 END_PROFILE(SMBclose);
2442 return ERROR_DOS(ERRDOS,ERRbadfid);
2445 if(fsp->is_directory) {
2447 * Special case - close NT SMB directory handle.
2449 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2450 close_file(fsp,True);
2451 } else {
2453 * Close ordinary file.
2455 int close_err;
2456 pstring file_name;
2458 /* Save the name for time set in close. */
2459 pstrcpy( file_name, fsp->fsp_name);
2461 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2462 fsp->fd, fsp->fnum,
2463 conn->num_files_open));
2466 * close_file() returns the unix errno if an error
2467 * was detected on close - normally this is due to
2468 * a disk full error. If not then it was probably an I/O error.
2471 if((close_err = close_file(fsp,True)) != 0) {
2472 errno = close_err;
2473 END_PROFILE(SMBclose);
2474 return (UNIXERROR(ERRHRD,ERRgeneral));
2478 * Now take care of any time sent in the close.
2481 mtime = make_unix_date3(inbuf+smb_vwv1);
2483 /* try and set the date */
2484 set_filetime(conn, file_name, mtime);
2488 /* We have a cached error */
2489 if(eclass || err) {
2490 END_PROFILE(SMBclose);
2491 return ERROR_DOS(eclass,err);
2494 END_PROFILE(SMBclose);
2495 return(outsize);
2498 /****************************************************************************
2499 Reply to a writeclose (Core+ protocol).
2500 ****************************************************************************/
2502 int reply_writeclose(connection_struct *conn,
2503 char *inbuf,char *outbuf, int size, int dum_buffsize)
2505 size_t numtowrite;
2506 ssize_t nwritten = -1;
2507 int outsize = 0;
2508 int close_err = 0;
2509 SMB_OFF_T startpos;
2510 char *data;
2511 time_t mtime;
2512 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2513 START_PROFILE(SMBwriteclose);
2515 CHECK_FSP(fsp,conn);
2516 CHECK_WRITE(fsp);
2518 numtowrite = SVAL(inbuf,smb_vwv1);
2519 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2520 mtime = make_unix_date3(inbuf+smb_vwv4);
2521 data = smb_buf(inbuf) + 1;
2523 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2524 END_PROFILE(SMBwriteclose);
2525 return ERROR_DOS(ERRDOS,ERRlock);
2528 nwritten = write_file(fsp,data,startpos,numtowrite);
2530 set_filetime(conn, fsp->fsp_name,mtime);
2532 close_err = close_file(fsp,True);
2534 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2535 fsp->fnum, (int)numtowrite, (int)nwritten,
2536 conn->num_files_open));
2538 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2539 END_PROFILE(SMBwriteclose);
2540 return(UNIXERROR(ERRHRD,ERRdiskfull));
2543 if(close_err != 0) {
2544 errno = close_err;
2545 END_PROFILE(SMBwriteclose);
2546 return(UNIXERROR(ERRHRD,ERRgeneral));
2549 outsize = set_message(outbuf,1,0,True);
2551 SSVAL(outbuf,smb_vwv0,nwritten);
2552 END_PROFILE(SMBwriteclose);
2553 return(outsize);
2556 /****************************************************************************
2557 Reply to a lock.
2558 ****************************************************************************/
2560 int reply_lock(connection_struct *conn,
2561 char *inbuf,char *outbuf, int length, int dum_buffsize)
2563 int outsize = set_message(outbuf,0,0,True);
2564 SMB_BIG_UINT count,offset;
2565 NTSTATUS status;
2566 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2567 START_PROFILE(SMBlock);
2569 CHECK_FSP(fsp,conn);
2571 release_level_2_oplocks_on_change(fsp);
2573 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2574 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2576 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2577 fsp->fd, fsp->fnum, (double)offset, (double)count));
2579 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2580 if (NT_STATUS_V(status)) {
2581 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2583 * A blocking lock was requested. Package up
2584 * this smb into a queued request and push it
2585 * onto the blocking lock queue.
2587 if(push_blocking_lock_request(inbuf, length, -1, 0, SVAL(inbuf,smb_pid), offset, count)) {
2588 END_PROFILE(SMBlock);
2589 return -1;
2592 END_PROFILE(SMBlock);
2593 return ERROR_NT(status);
2596 END_PROFILE(SMBlock);
2597 return(outsize);
2600 /****************************************************************************
2601 Reply to a unlock.
2602 ****************************************************************************/
2604 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2605 int dum_buffsize)
2607 int outsize = set_message(outbuf,0,0,True);
2608 SMB_BIG_UINT count,offset;
2609 NTSTATUS status;
2610 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2611 START_PROFILE(SMBunlock);
2613 CHECK_FSP(fsp,conn);
2615 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2616 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2618 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2619 if (NT_STATUS_V(status)) {
2620 END_PROFILE(SMBunlock);
2621 return ERROR_NT(status);
2624 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2625 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2627 END_PROFILE(SMBunlock);
2628 return(outsize);
2631 /****************************************************************************
2632 Reply to a tdis.
2633 ****************************************************************************/
2635 int reply_tdis(connection_struct *conn,
2636 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2638 int outsize = set_message(outbuf,0,0,True);
2639 uint16 vuid;
2640 START_PROFILE(SMBtdis);
2642 vuid = SVAL(inbuf,smb_uid);
2644 if (!conn) {
2645 DEBUG(4,("Invalid connection in tdis\n"));
2646 END_PROFILE(SMBtdis);
2647 return ERROR_DOS(ERRSRV,ERRinvnid);
2650 conn->used = False;
2652 close_cnum(conn,vuid);
2654 END_PROFILE(SMBtdis);
2655 return outsize;
2658 /****************************************************************************
2659 Reply to a echo.
2660 ****************************************************************************/
2662 int reply_echo(connection_struct *conn,
2663 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2665 int smb_reverb = SVAL(inbuf,smb_vwv0);
2666 int seq_num;
2667 unsigned int data_len = smb_buflen(inbuf);
2668 int outsize = set_message(outbuf,1,data_len,True);
2669 START_PROFILE(SMBecho);
2671 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2673 /* copy any incoming data back out */
2674 if (data_len > 0)
2675 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2677 if (smb_reverb > 100) {
2678 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2679 smb_reverb = 100;
2682 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2683 SSVAL(outbuf,smb_vwv0,seq_num);
2685 smb_setlen(outbuf,outsize - 4);
2687 if (!send_smb(smbd_server_fd(),outbuf))
2688 exit_server("reply_echo: send_smb failed.");
2691 DEBUG(3,("echo %d times\n", smb_reverb));
2693 smb_echo_count++;
2695 END_PROFILE(SMBecho);
2696 return -1;
2699 /****************************************************************************
2700 Reply to a printopen.
2701 ****************************************************************************/
2703 int reply_printopen(connection_struct *conn,
2704 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2706 int outsize = 0;
2707 files_struct *fsp;
2708 START_PROFILE(SMBsplopen);
2710 if (!CAN_PRINT(conn)) {
2711 END_PROFILE(SMBsplopen);
2712 return ERROR_DOS(ERRDOS,ERRnoaccess);
2715 /* Open for exclusive use, write only. */
2716 fsp = print_fsp_open(conn, NULL);
2718 if (!fsp) {
2719 END_PROFILE(SMBsplopen);
2720 return(UNIXERROR(ERRDOS,ERRnoaccess));
2723 outsize = set_message(outbuf,1,0,True);
2724 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2726 DEBUG(3,("openprint fd=%d fnum=%d\n",
2727 fsp->fd, fsp->fnum));
2729 END_PROFILE(SMBsplopen);
2730 return(outsize);
2733 /****************************************************************************
2734 Reply to a printclose.
2735 ****************************************************************************/
2737 int reply_printclose(connection_struct *conn,
2738 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2740 int outsize = set_message(outbuf,0,0,True);
2741 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2742 int close_err = 0;
2743 START_PROFILE(SMBsplclose);
2745 CHECK_FSP(fsp,conn);
2747 if (!CAN_PRINT(conn)) {
2748 END_PROFILE(SMBsplclose);
2749 return ERROR_NT(NT_STATUS_UNSUCCESSFUL);
2752 DEBUG(3,("printclose fd=%d fnum=%d\n",
2753 fsp->fd,fsp->fnum));
2755 close_err = close_file(fsp,True);
2757 if(close_err != 0) {
2758 errno = close_err;
2759 END_PROFILE(SMBsplclose);
2760 return(UNIXERROR(ERRHRD,ERRgeneral));
2763 END_PROFILE(SMBsplclose);
2764 return(outsize);
2767 /****************************************************************************
2768 Reply to a printqueue.
2769 ****************************************************************************/
2771 int reply_printqueue(connection_struct *conn,
2772 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2774 int outsize = set_message(outbuf,2,3,True);
2775 int max_count = SVAL(inbuf,smb_vwv0);
2776 int start_index = SVAL(inbuf,smb_vwv1);
2777 START_PROFILE(SMBsplretq);
2779 /* we used to allow the client to get the cnum wrong, but that
2780 is really quite gross and only worked when there was only
2781 one printer - I think we should now only accept it if they
2782 get it right (tridge) */
2783 if (!CAN_PRINT(conn)) {
2784 END_PROFILE(SMBsplretq);
2785 return ERROR_DOS(ERRDOS,ERRnoaccess);
2788 SSVAL(outbuf,smb_vwv0,0);
2789 SSVAL(outbuf,smb_vwv1,0);
2790 SCVAL(smb_buf(outbuf),0,1);
2791 SSVAL(smb_buf(outbuf),1,0);
2793 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2794 start_index, max_count));
2797 print_queue_struct *queue = NULL;
2798 print_status_struct status;
2799 char *p = smb_buf(outbuf) + 3;
2800 int count = print_queue_status(SNUM(conn), &queue, &status);
2801 int num_to_get = ABS(max_count);
2802 int first = (max_count>0?start_index:start_index+max_count+1);
2803 int i;
2805 if (first >= count)
2806 num_to_get = 0;
2807 else
2808 num_to_get = MIN(num_to_get,count-first);
2811 for (i=first;i<first+num_to_get;i++) {
2812 put_dos_date2(p,0,queue[i].time);
2813 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2814 SSVAL(p,5, queue[i].job);
2815 SIVAL(p,7,queue[i].size);
2816 SCVAL(p,11,0);
2817 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2818 p += 28;
2821 if (count > 0) {
2822 outsize = set_message(outbuf,2,28*count+3,False);
2823 SSVAL(outbuf,smb_vwv0,count);
2824 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2825 SCVAL(smb_buf(outbuf),0,1);
2826 SSVAL(smb_buf(outbuf),1,28*count);
2829 SAFE_FREE(queue);
2831 DEBUG(3,("%d entries returned in queue\n",count));
2834 END_PROFILE(SMBsplretq);
2835 return(outsize);
2838 /****************************************************************************
2839 Reply to a printwrite.
2840 ****************************************************************************/
2842 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2844 int numtowrite;
2845 int outsize = set_message(outbuf,0,0,True);
2846 char *data;
2847 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2849 START_PROFILE(SMBsplwr);
2851 if (!CAN_PRINT(conn)) {
2852 END_PROFILE(SMBsplwr);
2853 return ERROR_DOS(ERRDOS,ERRnoaccess);
2856 CHECK_FSP(fsp,conn);
2857 CHECK_WRITE(fsp);
2859 numtowrite = SVAL(smb_buf(inbuf),1);
2860 data = smb_buf(inbuf) + 3;
2862 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2863 END_PROFILE(SMBsplwr);
2864 return(UNIXERROR(ERRHRD,ERRdiskfull));
2867 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2869 END_PROFILE(SMBsplwr);
2870 return(outsize);
2873 /****************************************************************************
2874 The guts of the mkdir command, split out so it may be called by the NT SMB
2875 code.
2876 ****************************************************************************/
2878 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2880 BOOL bad_path = False;
2881 SMB_STRUCT_STAT sbuf;
2882 int ret= -1;
2884 unix_convert(directory,conn,0,&bad_path,&sbuf);
2886 if (ms_has_wild(directory)) {
2887 return NT_STATUS_OBJECT_NAME_INVALID;
2890 if (check_name(directory, conn))
2891 ret = vfs_MkDir(conn,directory,unix_mode(conn,aDIR,directory));
2893 if (ret == -1) {
2894 NTSTATUS nterr = NT_STATUS_OK;
2895 if(errno == ENOENT) {
2896 unix_ERR_class = ERRDOS;
2897 if (bad_path) {
2898 unix_ERR_code = ERRbadpath;
2899 nterr = NT_STATUS_OBJECT_PATH_NOT_FOUND;
2900 } else {
2901 unix_ERR_code = ERRbadfile;
2902 nterr = NT_STATUS_OBJECT_NAME_NOT_FOUND;
2905 if (!NT_STATUS_IS_OK(nterr))
2906 return nterr;
2907 return map_nt_error_from_unix(errno);
2910 return NT_STATUS_OK;
2913 /****************************************************************************
2914 Reply to a mkdir.
2915 ****************************************************************************/
2917 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2919 pstring directory;
2920 int outsize;
2921 NTSTATUS status;
2922 START_PROFILE(SMBmkdir);
2924 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2926 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
2928 status = mkdir_internal(conn, directory);
2929 if (!NT_STATUS_IS_OK(status))
2930 return ERROR_NT(status);
2932 outsize = set_message(outbuf,0,0,True);
2934 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2936 END_PROFILE(SMBmkdir);
2937 return(outsize);
2940 /****************************************************************************
2941 Static function used by reply_rmdir to delete an entire directory
2942 tree recursively. Return False on ok, True on fail.
2943 ****************************************************************************/
2945 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2947 const char *dname = NULL;
2948 BOOL ret = False;
2949 void *dirptr = OpenDir(conn, directory, False);
2951 if(dirptr == NULL)
2952 return True;
2954 while((dname = ReadDirName(dirptr))) {
2955 pstring fullname;
2956 SMB_STRUCT_STAT st;
2958 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2959 continue;
2961 /* Construct the full name. */
2962 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2963 errno = ENOMEM;
2964 ret = True;
2965 break;
2968 pstrcpy(fullname, directory);
2969 pstrcat(fullname, "/");
2970 pstrcat(fullname, dname);
2972 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0) {
2973 ret = True;
2974 break;
2977 if(st.st_mode & S_IFDIR) {
2978 if(recursive_rmdir(conn, fullname)!=0) {
2979 ret = True;
2980 break;
2982 if(SMB_VFS_RMDIR(conn,fullname) != 0) {
2983 ret = True;
2984 break;
2986 } else if(SMB_VFS_UNLINK(conn,fullname) != 0) {
2987 ret = True;
2988 break;
2991 CloseDir(dirptr);
2992 return ret;
2995 /****************************************************************************
2996 The internals of the rmdir code - called elsewhere.
2997 ****************************************************************************/
2999 BOOL rmdir_internals(connection_struct *conn, char *directory)
3001 BOOL ok;
3003 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3004 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
3006 * Check to see if the only thing in this directory are
3007 * vetoed files/directories. If so then delete them and
3008 * retry. If we fail to delete any of them (and we *don't*
3009 * do a recursive delete) then fail the rmdir.
3011 BOOL all_veto_files = True;
3012 const char *dname;
3013 void *dirptr = OpenDir(conn, directory, False);
3015 if(dirptr != NULL) {
3016 int dirpos = TellDir(dirptr);
3017 while ((dname = ReadDirName(dirptr))) {
3018 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3019 continue;
3020 if(!IS_VETO_PATH(conn, dname)) {
3021 all_veto_files = False;
3022 break;
3026 if(all_veto_files) {
3027 SeekDir(dirptr,dirpos);
3028 while ((dname = ReadDirName(dirptr))) {
3029 pstring fullname;
3030 SMB_STRUCT_STAT st;
3032 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
3033 continue;
3035 /* Construct the full name. */
3036 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
3037 errno = ENOMEM;
3038 break;
3041 pstrcpy(fullname, directory);
3042 pstrcat(fullname, "/");
3043 pstrcat(fullname, dname);
3045 if(SMB_VFS_LSTAT(conn,fullname, &st) != 0)
3046 break;
3047 if(st.st_mode & S_IFDIR) {
3048 if(lp_recursive_veto_delete(SNUM(conn))) {
3049 if(recursive_rmdir(conn, fullname) != 0)
3050 break;
3052 if(SMB_VFS_RMDIR(conn,fullname) != 0)
3053 break;
3054 } else if(SMB_VFS_UNLINK(conn,fullname) != 0)
3055 break;
3057 CloseDir(dirptr);
3058 /* Retry the rmdir */
3059 ok = (SMB_VFS_RMDIR(conn,directory) == 0);
3060 } else {
3061 CloseDir(dirptr);
3063 } else {
3064 errno = ENOTEMPTY;
3068 if (!ok)
3069 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3071 return ok;
3074 /****************************************************************************
3075 Reply to a rmdir.
3076 ****************************************************************************/
3078 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3080 pstring directory;
3081 int outsize = 0;
3082 BOOL ok = False;
3083 BOOL bad_path = False;
3084 SMB_STRUCT_STAT sbuf;
3085 START_PROFILE(SMBrmdir);
3087 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
3089 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3091 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3093 if (check_name(directory,conn)) {
3094 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3095 ok = rmdir_internals(conn, directory);
3098 if (!ok) {
3099 END_PROFILE(SMBrmdir);
3100 return set_bad_path_error(errno, bad_path, outbuf, ERRDOS, ERRbadpath);
3103 outsize = set_message(outbuf,0,0,True);
3105 DEBUG( 3, ( "rmdir %s\n", directory ) );
3107 END_PROFILE(SMBrmdir);
3108 return(outsize);
3111 /*******************************************************************
3112 Resolve wildcards in a filename rename.
3113 ********************************************************************/
3115 static BOOL resolve_wildcards(const char *name1, char *name2)
3117 fstring root1,root2;
3118 fstring ext1,ext2;
3119 char *p,*p2, *pname1, *pname2;
3120 int available_space;
3123 pname1 = strrchr_m(name1,'/');
3124 pname2 = strrchr_m(name2,'/');
3126 if (!pname1 || !pname2)
3127 return(False);
3129 fstrcpy(root1,pname1);
3130 fstrcpy(root2,pname2);
3131 p = strrchr_m(root1,'.');
3132 if (p) {
3133 *p = 0;
3134 fstrcpy(ext1,p+1);
3135 } else {
3136 fstrcpy(ext1,"");
3138 p = strrchr_m(root2,'.');
3139 if (p) {
3140 *p = 0;
3141 fstrcpy(ext2,p+1);
3142 } else {
3143 fstrcpy(ext2,"");
3146 p = root1;
3147 p2 = root2;
3148 while (*p2) {
3149 if (*p2 == '?') {
3150 *p2 = *p;
3151 p2++;
3152 } else {
3153 p2++;
3155 if (*p)
3156 p++;
3159 p = ext1;
3160 p2 = ext2;
3161 while (*p2) {
3162 if (*p2 == '?') {
3163 *p2 = *p;
3164 p2++;
3165 } else {
3166 p2++;
3168 if (*p)
3169 p++;
3172 available_space = sizeof(pstring) - PTR_DIFF(pname2, name2);
3174 if (ext2[0]) {
3175 snprintf(pname2, available_space - 1, "%s.%s", root2, ext2);
3176 } else {
3177 pstrcpy_base(pname2, root2, name2);
3180 return(True);
3183 /****************************************************************************
3184 Ensure open files have their names updates.
3185 ****************************************************************************/
3187 static void rename_open_files(connection_struct *conn, SMB_DEV_T dev, SMB_INO_T inode, char *newname)
3189 files_struct *fsp;
3190 BOOL did_rename = False;
3192 for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
3193 DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
3194 fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
3195 fsp->fsp_name, newname ));
3196 string_set(&fsp->fsp_name, newname);
3197 did_rename = True;
3200 if (!did_rename)
3201 DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
3202 (unsigned int)dev, (double)inode, newname ));
3205 /****************************************************************************
3206 Rename an open file - given an fsp.
3207 ****************************************************************************/
3209 NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, char *newname, BOOL replace_if_exists)
3211 SMB_STRUCT_STAT sbuf;
3212 BOOL bad_path = False;
3213 pstring newname_last_component;
3214 NTSTATUS error = NT_STATUS_OK;
3215 BOOL dest_exists;
3217 ZERO_STRUCT(sbuf);
3218 unix_convert(newname,conn,newname_last_component,&bad_path,&sbuf);
3220 /* Ensure newname contains a '/' */
3221 if(strrchr_m(newname,'/') == 0) {
3222 pstring tmpstr;
3224 pstrcpy(tmpstr, "./");
3225 pstrcat(tmpstr, newname);
3226 pstrcpy(newname, tmpstr);
3230 * Check for special case with case preserving and not
3231 * case sensitive. If the old last component differs from the original
3232 * last component only by case, then we should allow
3233 * the rename (user is trying to change the case of the
3234 * filename).
3237 if((case_sensitive == False) && (case_preserve == True) &&
3238 strequal(newname, fsp->fsp_name)) {
3239 char *p;
3240 pstring newname_modified_last_component;
3243 * Get the last component of the modified name.
3244 * Note that we guarantee that newname contains a '/'
3245 * character above.
3247 p = strrchr_m(newname,'/');
3248 pstrcpy(newname_modified_last_component,p+1);
3250 if(strcsequal(newname_modified_last_component,
3251 newname_last_component) == False) {
3253 * Replace the modified last component with
3254 * the original.
3256 pstrcpy(p+1, newname_last_component);
3261 * If the src and dest names are identical - including case,
3262 * don't do the rename, just return success.
3265 if (strcsequal(fsp->fsp_name, newname)) {
3266 DEBUG(3,("rename_internals_fsp: identical names in rename %s - returning success\n",
3267 newname));
3268 return NT_STATUS_OK;
3271 dest_exists = vfs_object_exist(conn,newname,NULL);
3273 if(!replace_if_exists && dest_exists) {
3274 DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
3275 fsp->fsp_name,newname));
3276 return NT_STATUS_OBJECT_NAME_COLLISION;
3279 error = can_rename(newname,conn,&sbuf);
3281 if (dest_exists && !NT_STATUS_IS_OK(error)) {
3282 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3283 nt_errstr(error), fsp->fsp_name,newname));
3284 if (NT_STATUS_EQUAL(error,NT_STATUS_SHARING_VIOLATION))
3285 error = NT_STATUS_ACCESS_DENIED;
3286 return error;
3289 if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
3290 DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
3291 fsp->fsp_name,newname));
3292 rename_open_files(conn, fsp->dev, fsp->inode, newname);
3293 return NT_STATUS_OK;
3296 if (errno == ENOTDIR || errno == EISDIR)
3297 error = NT_STATUS_OBJECT_NAME_COLLISION;
3298 else
3299 error = map_nt_error_from_unix(errno);
3301 DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
3302 nt_errstr(error), fsp->fsp_name,newname));
3304 return error;
3307 /****************************************************************************
3308 The guts of the rename command, split out so it may be called by the NT SMB
3309 code.
3310 ****************************************************************************/
3312 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3314 pstring directory;
3315 pstring mask;
3316 pstring newname_last_component;
3317 char *p;
3318 BOOL has_wild;
3319 BOOL bad_path1 = False;
3320 BOOL bad_path2 = False;
3321 int count=0;
3322 NTSTATUS error = NT_STATUS_OK;
3323 BOOL rc = True;
3324 SMB_STRUCT_STAT sbuf1, sbuf2;
3326 *directory = *mask = 0;
3328 ZERO_STRUCT(sbuf1);
3329 ZERO_STRUCT(sbuf2);
3330 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3331 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3334 * Split the old name into directory and last component
3335 * strings. Note that unix_convert may have stripped off a
3336 * leading ./ from both name and newname if the rename is
3337 * at the root of the share. We need to make sure either both
3338 * name and newname contain a / character or neither of them do
3339 * as this is checked in resolve_wildcards().
3342 p = strrchr_m(name,'/');
3343 if (!p) {
3344 pstrcpy(directory,".");
3345 pstrcpy(mask,name);
3346 } else {
3347 *p = 0;
3348 pstrcpy(directory,name);
3349 pstrcpy(mask,p+1);
3350 *p = '/'; /* Replace needed for exceptional test below. */
3354 * We should only check the mangled cache
3355 * here if unix_convert failed. This means
3356 * that the path in 'mask' doesn't exist
3357 * on the file system and so we need to look
3358 * for a possible mangle. This patch from
3359 * Tine Smukavec <valentin.smukavec@hermes.si>.
3362 if (!rc && mangle_is_mangled(mask))
3363 mangle_check_cache( mask );
3365 has_wild = ms_has_wild(mask);
3367 if (!has_wild) {
3369 * No wildcards - just process the one file.
3371 BOOL is_short_name = mangle_is_8_3(name, True);
3373 /* Add a terminating '/' to the directory name. */
3374 pstrcat(directory,"/");
3375 pstrcat(directory,mask);
3377 /* Ensure newname contains a '/' also */
3378 if(strrchr_m(newname,'/') == 0) {
3379 pstring tmpstr;
3381 pstrcpy(tmpstr, "./");
3382 pstrcat(tmpstr, newname);
3383 pstrcpy(newname, tmpstr);
3386 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3387 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3388 case_sensitive, case_preserve, short_case_preserve, directory,
3389 newname, newname_last_component, is_short_name));
3392 * Check for special case with case preserving and not
3393 * case sensitive, if directory and newname are identical,
3394 * and the old last component differs from the original
3395 * last component only by case, then we should allow
3396 * the rename (user is trying to change the case of the
3397 * filename).
3399 if((case_sensitive == False) &&
3400 (((case_preserve == True) &&
3401 (is_short_name == False)) ||
3402 ((short_case_preserve == True) &&
3403 (is_short_name == True))) &&
3404 strcsequal(directory, newname)) {
3405 pstring newname_modified_last_component;
3408 * Get the last component of the modified name.
3409 * Note that we guarantee that newname contains a '/'
3410 * character above.
3412 p = strrchr_m(newname,'/');
3413 pstrcpy(newname_modified_last_component,p+1);
3415 if(strcsequal(newname_modified_last_component,
3416 newname_last_component) == False) {
3418 * Replace the modified last component with
3419 * the original.
3421 pstrcpy(p+1, newname_last_component);
3425 resolve_wildcards(directory,newname);
3428 * The source object must exist.
3431 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3432 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3433 directory,newname));
3435 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3437 * Must return different errors depending on whether the parent
3438 * directory existed or not.
3441 p = strrchr_m(directory, '/');
3442 if (!p)
3443 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3444 *p = '\0';
3445 if (vfs_object_exist(conn, directory, NULL))
3446 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3447 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3449 error = map_nt_error_from_unix(errno);
3450 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3451 nt_errstr(error), directory,newname));
3453 return error;
3456 error = can_rename(directory,conn,&sbuf1);
3458 if (!NT_STATUS_IS_OK(error)) {
3459 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3460 nt_errstr(error), directory,newname));
3461 return error;
3465 * If the src and dest names are identical - including case,
3466 * don't do the rename, just return success.
3469 if (strcsequal(directory, newname)) {
3470 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3471 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3472 return NT_STATUS_OK;
3475 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3476 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3477 directory,newname));
3478 return NT_STATUS_OBJECT_NAME_COLLISION;
3481 if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
3482 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3483 directory,newname));
3484 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3485 return NT_STATUS_OK;
3488 if (errno == ENOTDIR || errno == EISDIR)
3489 error = NT_STATUS_OBJECT_NAME_COLLISION;
3490 else
3491 error = map_nt_error_from_unix(errno);
3493 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3494 nt_errstr(error), directory,newname));
3496 return error;
3497 } else {
3499 * Wildcards - process each file that matches.
3501 void *dirptr = NULL;
3502 const char *dname;
3503 pstring destname;
3505 if (check_name(directory,conn))
3506 dirptr = OpenDir(conn, directory, True);
3508 if (dirptr) {
3509 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3511 if (strequal(mask,"????????.???"))
3512 pstrcpy(mask,"*");
3514 while ((dname = ReadDirName(dirptr))) {
3515 pstring fname;
3517 pstrcpy(fname,dname);
3519 if(!mask_match(fname, mask, case_sensitive))
3520 continue;
3522 error = NT_STATUS_ACCESS_DENIED;
3523 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3524 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3525 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3526 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3527 continue;
3529 error = can_rename(fname,conn,&sbuf1);
3530 if (!NT_STATUS_IS_OK(error)) {
3531 DEBUG(6,("rename %s refused\n", fname));
3532 continue;
3534 pstrcpy(destname,newname);
3536 if (!resolve_wildcards(fname,destname)) {
3537 DEBUG(6,("resolve_wildcards %s %s failed\n",
3538 fname, destname));
3539 continue;
3542 if (!replace_if_exists &&
3543 vfs_file_exist(conn,destname, NULL)) {
3544 DEBUG(6,("file_exist %s\n", destname));
3545 error = NT_STATUS_OBJECT_NAME_COLLISION;
3546 continue;
3549 if (!SMB_VFS_RENAME(conn,fname,destname)) {
3550 rename_open_files(conn, sbuf1.st_dev, sbuf1.st_ino, newname);
3551 count++;
3553 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3555 CloseDir(dirptr);
3559 if (count == 0 && NT_STATUS_IS_OK(error)) {
3560 error = map_nt_error_from_unix(errno);
3563 return error;
3566 /****************************************************************************
3567 Reply to a mv.
3568 ****************************************************************************/
3570 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3571 int dum_buffsize)
3573 int outsize = 0;
3574 pstring name;
3575 pstring newname;
3576 char *p;
3577 NTSTATUS status;
3579 START_PROFILE(SMBmv);
3581 p = smb_buf(inbuf) + 1;
3582 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3583 p++;
3584 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3586 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3587 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3589 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3591 status = rename_internals(conn, name, newname, False);
3592 if (!NT_STATUS_IS_OK(status)) {
3593 return ERROR_NT(status);
3597 * Win2k needs a changenotify request response before it will
3598 * update after a rename..
3600 process_pending_change_notify_queue((time_t)0);
3601 outsize = set_message(outbuf,0,0,True);
3603 END_PROFILE(SMBmv);
3604 return(outsize);
3607 /*******************************************************************
3608 Copy a file as part of a reply_copy.
3609 ******************************************************************/
3611 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3612 int count,BOOL target_is_directory, int *err_ret)
3614 int Access,action;
3615 SMB_STRUCT_STAT src_sbuf, sbuf2;
3616 SMB_OFF_T ret=-1;
3617 files_struct *fsp1,*fsp2;
3618 pstring dest;
3620 *err_ret = 0;
3622 pstrcpy(dest,dest1);
3623 if (target_is_directory) {
3624 char *p = strrchr_m(src,'/');
3625 if (p)
3626 p++;
3627 else
3628 p = src;
3629 pstrcat(dest,"/");
3630 pstrcat(dest,p);
3633 if (!vfs_file_exist(conn,src,&src_sbuf))
3634 return(False);
3636 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3637 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3639 if (!fsp1)
3640 return(False);
3642 if (!target_is_directory && count)
3643 ofun = FILE_EXISTS_OPEN;
3645 if (SMB_VFS_STAT(conn,dest,&sbuf2) == -1)
3646 ZERO_STRUCTP(&sbuf2);
3648 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3649 ofun,src_sbuf.st_mode,0,&Access,&action);
3651 if (!fsp2) {
3652 close_file(fsp1,False);
3653 return(False);
3656 if ((ofun&3) == 1) {
3657 if(SMB_VFS_LSEEK(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3658 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3660 * Stop the copy from occurring.
3662 ret = -1;
3663 src_sbuf.st_size = 0;
3667 if (src_sbuf.st_size)
3668 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3670 close_file(fsp1,False);
3672 /* Ensure the modtime is set correctly on the destination file. */
3673 fsp2->pending_modtime = src_sbuf.st_mtime;
3676 * As we are opening fsp1 read-only we only expect
3677 * an error on close on fsp2 if we are out of space.
3678 * Thus we don't look at the error return from the
3679 * close of fsp1.
3681 *err_ret = close_file(fsp2,False);
3683 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3686 /****************************************************************************
3687 Reply to a file copy.
3688 ****************************************************************************/
3690 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3692 int outsize = 0;
3693 pstring name;
3694 pstring directory;
3695 pstring mask,newname;
3696 char *p;
3697 int count=0;
3698 int error = ERRnoaccess;
3699 int err = 0;
3700 BOOL has_wild;
3701 BOOL exists=False;
3702 int tid2 = SVAL(inbuf,smb_vwv0);
3703 int ofun = SVAL(inbuf,smb_vwv1);
3704 int flags = SVAL(inbuf,smb_vwv2);
3705 BOOL target_is_directory=False;
3706 BOOL bad_path1 = False;
3707 BOOL bad_path2 = False;
3708 BOOL rc = True;
3709 SMB_STRUCT_STAT sbuf1, sbuf2;
3711 START_PROFILE(SMBcopy);
3713 *directory = *mask = 0;
3715 p = smb_buf(inbuf);
3716 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3717 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3719 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3721 if (tid2 != conn->cnum) {
3722 /* can't currently handle inter share copies XXXX */
3723 DEBUG(3,("Rejecting inter-share copy\n"));
3724 END_PROFILE(SMBcopy);
3725 return ERROR_DOS(ERRSRV,ERRinvdevice);
3728 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3729 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3731 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3732 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3734 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3736 if ((flags&1) && target_is_directory) {
3737 END_PROFILE(SMBcopy);
3738 return ERROR_DOS(ERRDOS,ERRbadfile);
3741 if ((flags&2) && !target_is_directory) {
3742 END_PROFILE(SMBcopy);
3743 return ERROR_DOS(ERRDOS,ERRbadpath);
3746 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3747 /* wants a tree copy! XXXX */
3748 DEBUG(3,("Rejecting tree copy\n"));
3749 END_PROFILE(SMBcopy);
3750 return ERROR_DOS(ERRSRV,ERRerror);
3753 p = strrchr_m(name,'/');
3754 if (!p) {
3755 pstrcpy(directory,"./");
3756 pstrcpy(mask,name);
3757 } else {
3758 *p = 0;
3759 pstrcpy(directory,name);
3760 pstrcpy(mask,p+1);
3764 * We should only check the mangled cache
3765 * here if unix_convert failed. This means
3766 * that the path in 'mask' doesn't exist
3767 * on the file system and so we need to look
3768 * for a possible mangle. This patch from
3769 * Tine Smukavec <valentin.smukavec@hermes.si>.
3772 if (!rc && mangle_is_mangled(mask))
3773 mangle_check_cache( mask );
3775 has_wild = ms_has_wild(mask);
3777 if (!has_wild) {
3778 pstrcat(directory,"/");
3779 pstrcat(directory,mask);
3780 if (resolve_wildcards(directory,newname) &&
3781 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3782 count++;
3783 if(!count && err) {
3784 errno = err;
3785 END_PROFILE(SMBcopy);
3786 return(UNIXERROR(ERRHRD,ERRgeneral));
3788 if (!count) {
3789 exists = vfs_file_exist(conn,directory,NULL);
3791 } else {
3792 void *dirptr = NULL;
3793 const char *dname;
3794 pstring destname;
3796 if (check_name(directory,conn))
3797 dirptr = OpenDir(conn, directory, True);
3799 if (dirptr) {
3800 error = ERRbadfile;
3802 if (strequal(mask,"????????.???"))
3803 pstrcpy(mask,"*");
3805 while ((dname = ReadDirName(dirptr))) {
3806 pstring fname;
3807 pstrcpy(fname,dname);
3809 if(!mask_match(fname, mask, case_sensitive))
3810 continue;
3812 error = ERRnoaccess;
3813 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3814 pstrcpy(destname,newname);
3815 if (resolve_wildcards(fname,destname) &&
3816 copy_file(fname,destname,conn,ofun,
3817 count,target_is_directory,&err))
3818 count++;
3819 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3821 CloseDir(dirptr);
3825 if (count == 0) {
3826 if(err) {
3827 /* Error on close... */
3828 errno = err;
3829 END_PROFILE(SMBcopy);
3830 return(UNIXERROR(ERRHRD,ERRgeneral));
3833 if (exists) {
3834 END_PROFILE(SMBcopy);
3835 return ERROR_DOS(ERRDOS,error);
3836 } else {
3837 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3838 unix_ERR_class = ERRDOS;
3839 unix_ERR_code = ERRbadpath;
3841 END_PROFILE(SMBcopy);
3842 return(UNIXERROR(ERRDOS,error));
3846 outsize = set_message(outbuf,1,0,True);
3847 SSVAL(outbuf,smb_vwv0,count);
3849 END_PROFILE(SMBcopy);
3850 return(outsize);
3853 /****************************************************************************
3854 Reply to a setdir.
3855 ****************************************************************************/
3857 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3859 int snum;
3860 int outsize = 0;
3861 BOOL ok = False;
3862 pstring newdir;
3864 START_PROFILE(pathworks_setdir);
3866 snum = SNUM(conn);
3867 if (!CAN_SETDIR(snum)) {
3868 END_PROFILE(pathworks_setdir);
3869 return ERROR_DOS(ERRDOS,ERRnoaccess);
3872 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3874 if (strlen(newdir) == 0) {
3875 ok = True;
3876 } else {
3877 ok = vfs_directory_exist(conn,newdir,NULL);
3878 if (ok)
3879 string_set(&conn->connectpath,newdir);
3882 if (!ok) {
3883 END_PROFILE(pathworks_setdir);
3884 return ERROR_DOS(ERRDOS,ERRbadpath);
3887 outsize = set_message(outbuf,0,0,True);
3888 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3890 DEBUG(3,("setdir %s\n", newdir));
3892 END_PROFILE(pathworks_setdir);
3893 return(outsize);
3896 /****************************************************************************
3897 Get a lock pid, dealing with large count requests.
3898 ****************************************************************************/
3900 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3902 if(!large_file_format)
3903 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3904 else
3905 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3908 /****************************************************************************
3909 Get a lock count, dealing with large count requests.
3910 ****************************************************************************/
3912 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3914 SMB_BIG_UINT count = 0;
3916 if(!large_file_format) {
3917 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3918 } else {
3920 #if defined(HAVE_LONGLONG)
3921 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3922 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3923 #else /* HAVE_LONGLONG */
3926 * NT4.x seems to be broken in that it sends large file (64 bit)
3927 * lockingX calls even if the CAP_LARGE_FILES was *not*
3928 * negotiated. For boxes without large unsigned ints truncate the
3929 * lock count by dropping the top 32 bits.
3932 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3933 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3934 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3935 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3936 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3939 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3940 #endif /* HAVE_LONGLONG */
3943 return count;
3946 #if !defined(HAVE_LONGLONG)
3947 /****************************************************************************
3948 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3949 ****************************************************************************/
3951 static uint32 map_lock_offset(uint32 high, uint32 low)
3953 unsigned int i;
3954 uint32 mask = 0;
3955 uint32 highcopy = high;
3958 * Try and find out how many significant bits there are in high.
3961 for(i = 0; highcopy; i++)
3962 highcopy >>= 1;
3965 * We use 31 bits not 32 here as POSIX
3966 * lock offsets may not be negative.
3969 mask = (~0) << (31 - i);
3971 if(low & mask)
3972 return 0; /* Fail. */
3974 high <<= (31 - i);
3976 return (high|low);
3978 #endif /* !defined(HAVE_LONGLONG) */
3980 /****************************************************************************
3981 Get a lock offset, dealing with large offset requests.
3982 ****************************************************************************/
3984 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3986 SMB_BIG_UINT offset = 0;
3988 *err = False;
3990 if(!large_file_format) {
3991 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3992 } else {
3994 #if defined(HAVE_LONGLONG)
3995 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3996 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3997 #else /* HAVE_LONGLONG */
4000 * NT4.x seems to be broken in that it sends large file (64 bit)
4001 * lockingX calls even if the CAP_LARGE_FILES was *not*
4002 * negotiated. For boxes without large unsigned ints mangle the
4003 * lock offset by mapping the top 32 bits onto the lower 32.
4006 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
4007 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4008 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
4009 uint32 new_low = 0;
4011 if((new_low = map_lock_offset(high, low)) == 0) {
4012 *err = True;
4013 return (SMB_BIG_UINT)-1;
4016 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
4017 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
4018 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
4019 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
4022 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
4023 #endif /* HAVE_LONGLONG */
4026 return offset;
4029 /****************************************************************************
4030 Reply to a lockingX request.
4031 ****************************************************************************/
4033 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4035 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
4036 unsigned char locktype = CVAL(inbuf,smb_vwv3);
4037 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
4038 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
4039 uint16 num_locks = SVAL(inbuf,smb_vwv7);
4040 SMB_BIG_UINT count = 0, offset = 0;
4041 uint16 lock_pid;
4042 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
4043 int i;
4044 char *data;
4045 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
4046 BOOL err;
4047 NTSTATUS status;
4049 START_PROFILE(SMBlockingX);
4051 CHECK_FSP(fsp,conn);
4053 data = smb_buf(inbuf);
4055 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
4056 /* we don't support these - and CANCEL_LOCK makes w2k
4057 and XP reboot so I don't really want to be
4058 compatible! (tridge) */
4059 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
4062 /* Check if this is an oplock break on a file
4063 we have granted an oplock on.
4065 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
4066 /* Client can insist on breaking to none. */
4067 BOOL break_to_none = (oplocklevel == 0);
4069 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
4070 (unsigned int)oplocklevel, fsp->fnum ));
4073 * Make sure we have granted an exclusive or batch oplock on this file.
4076 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
4077 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
4078 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
4080 /* if this is a pure oplock break request then don't send a reply */
4081 if (num_locks == 0 && num_ulocks == 0) {
4082 END_PROFILE(SMBlockingX);
4083 return -1;
4084 } else {
4085 END_PROFILE(SMBlockingX);
4086 return ERROR_DOS(ERRDOS,ERRlock);
4090 if (remove_oplock(fsp, break_to_none) == False) {
4091 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
4092 fsp->fsp_name ));
4095 /* if this is a pure oplock break request then don't send a reply */
4096 if (num_locks == 0 && num_ulocks == 0) {
4097 /* Sanity check - ensure a pure oplock break is not a
4098 chained request. */
4099 if(CVAL(inbuf,smb_vwv0) != 0xff)
4100 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
4101 (unsigned int)CVAL(inbuf,smb_vwv0) ));
4102 END_PROFILE(SMBlockingX);
4103 return -1;
4108 * We do this check *after* we have checked this is not a oplock break
4109 * response message. JRA.
4112 release_level_2_oplocks_on_change(fsp);
4114 /* Data now points at the beginning of the list
4115 of smb_unlkrng structs */
4116 for(i = 0; i < (int)num_ulocks; i++) {
4117 lock_pid = get_lock_pid( data, i, large_file_format);
4118 count = get_lock_count( data, i, large_file_format);
4119 offset = get_lock_offset( data, i, large_file_format, &err);
4122 * There is no error code marked "stupid client bug".... :-).
4124 if(err) {
4125 END_PROFILE(SMBlockingX);
4126 return ERROR_DOS(ERRDOS,ERRnoaccess);
4129 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
4130 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
4132 status = do_unlock(fsp,conn,lock_pid,count,offset);
4133 if (NT_STATUS_V(status)) {
4134 END_PROFILE(SMBlockingX);
4135 return ERROR_NT(status);
4139 /* Setup the timeout in seconds. */
4141 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+499)/500);
4143 /* Now do any requested locks */
4144 data += ((large_file_format ? 20 : 10)*num_ulocks);
4146 /* Data now points at the beginning of the list
4147 of smb_lkrng structs */
4149 for(i = 0; i < (int)num_locks; i++) {
4150 lock_pid = get_lock_pid( data, i, large_file_format);
4151 count = get_lock_count( data, i, large_file_format);
4152 offset = get_lock_offset( data, i, large_file_format, &err);
4155 * There is no error code marked "stupid client bug".... :-).
4157 if(err) {
4158 END_PROFILE(SMBlockingX);
4159 return ERROR_DOS(ERRDOS,ERRnoaccess);
4162 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
4163 (double)offset, (double)count, (unsigned int)lock_pid,
4164 fsp->fsp_name, (int)lock_timeout ));
4166 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
4167 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
4168 if (NT_STATUS_V(status)) {
4169 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
4171 * A blocking lock was requested. Package up
4172 * this smb into a queued request and push it
4173 * onto the blocking lock queue.
4175 if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) {
4176 END_PROFILE(SMBlockingX);
4177 return -1;
4180 break;
4184 /* If any of the above locks failed, then we must unlock
4185 all of the previous locks (X/Open spec). */
4186 if (i != num_locks && num_locks != 0) {
4188 * Ensure we don't do a remove on the lock that just failed,
4189 * as under POSIX rules, if we have a lock already there, we
4190 * will delete it (and we shouldn't) .....
4192 for(i--; i >= 0; i--) {
4193 lock_pid = get_lock_pid( data, i, large_file_format);
4194 count = get_lock_count( data, i, large_file_format);
4195 offset = get_lock_offset( data, i, large_file_format, &err);
4198 * There is no error code marked "stupid client bug".... :-).
4200 if(err) {
4201 END_PROFILE(SMBlockingX);
4202 return ERROR_DOS(ERRDOS,ERRnoaccess);
4205 do_unlock(fsp,conn,lock_pid,count,offset);
4207 END_PROFILE(SMBlockingX);
4208 return ERROR_NT(status);
4211 set_message(outbuf,2,0,True);
4213 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4214 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4216 END_PROFILE(SMBlockingX);
4217 return chain_reply(inbuf,outbuf,length,bufsize);
4220 /****************************************************************************
4221 Reply to a SMBreadbmpx (read block multiplex) request.
4222 ****************************************************************************/
4224 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4226 ssize_t nread = -1;
4227 ssize_t total_read;
4228 char *data;
4229 SMB_OFF_T startpos;
4230 int outsize;
4231 size_t maxcount;
4232 int max_per_packet;
4233 size_t tcount;
4234 int pad;
4235 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4236 START_PROFILE(SMBreadBmpx);
4238 /* this function doesn't seem to work - disable by default */
4239 if (!lp_readbmpx()) {
4240 END_PROFILE(SMBreadBmpx);
4241 return ERROR_DOS(ERRSRV,ERRuseSTD);
4244 outsize = set_message(outbuf,8,0,True);
4246 CHECK_FSP(fsp,conn);
4247 CHECK_READ(fsp);
4249 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4250 maxcount = SVAL(inbuf,smb_vwv3);
4252 data = smb_buf(outbuf);
4253 pad = ((long)data)%4;
4254 if (pad)
4255 pad = 4 - pad;
4256 data += pad;
4258 max_per_packet = bufsize-(outsize+pad);
4259 tcount = maxcount;
4260 total_read = 0;
4262 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4263 END_PROFILE(SMBreadBmpx);
4264 return ERROR_DOS(ERRDOS,ERRlock);
4267 do {
4268 size_t N = MIN(max_per_packet,tcount-total_read);
4270 nread = read_file(fsp,data,startpos,N);
4272 if (nread <= 0)
4273 nread = 0;
4275 if (nread < (ssize_t)N)
4276 tcount = total_read + nread;
4278 set_message(outbuf,8,nread,False);
4279 SIVAL(outbuf,smb_vwv0,startpos);
4280 SSVAL(outbuf,smb_vwv2,tcount);
4281 SSVAL(outbuf,smb_vwv6,nread);
4282 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4284 if (!send_smb(smbd_server_fd(),outbuf))
4285 exit_server("reply_readbmpx: send_smb failed.");
4287 total_read += nread;
4288 startpos += nread;
4289 } while (total_read < (ssize_t)tcount);
4291 END_PROFILE(SMBreadBmpx);
4292 return(-1);
4295 /****************************************************************************
4296 Reply to a SMBsetattrE.
4297 ****************************************************************************/
4299 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4301 struct utimbuf unix_times;
4302 int outsize = 0;
4303 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4304 START_PROFILE(SMBsetattrE);
4306 outsize = set_message(outbuf,0,0,True);
4308 if(!fsp || (fsp->conn != conn)) {
4309 END_PROFILE(SMBgetattrE);
4310 return ERROR_DOS(ERRDOS,ERRbadfid);
4314 * Convert the DOS times into unix times. Ignore create
4315 * time as UNIX can't set this.
4318 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4319 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4322 * Patch from Ray Frush <frush@engr.colostate.edu>
4323 * Sometimes times are sent as zero - ignore them.
4326 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4327 /* Ignore request */
4328 if( DEBUGLVL( 3 ) ) {
4329 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4330 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4332 END_PROFILE(SMBsetattrE);
4333 return(outsize);
4334 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4335 /* set modify time = to access time if modify time was 0 */
4336 unix_times.modtime = unix_times.actime;
4339 /* Set the date on this file */
4340 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4341 END_PROFILE(SMBsetattrE);
4342 return ERROR_DOS(ERRDOS,ERRnoaccess);
4345 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4346 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4348 END_PROFILE(SMBsetattrE);
4349 return(outsize);
4353 /* Back from the dead for OS/2..... JRA. */
4355 /****************************************************************************
4356 Reply to a SMBwritebmpx (write block multiplex primary) request.
4357 ****************************************************************************/
4359 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4361 size_t numtowrite;
4362 ssize_t nwritten = -1;
4363 int outsize = 0;
4364 SMB_OFF_T startpos;
4365 size_t tcount;
4366 BOOL write_through;
4367 int smb_doff;
4368 char *data;
4369 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4370 START_PROFILE(SMBwriteBmpx);
4372 CHECK_FSP(fsp,conn);
4373 CHECK_WRITE(fsp);
4374 CHECK_ERROR(fsp);
4376 tcount = SVAL(inbuf,smb_vwv1);
4377 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4378 write_through = BITSETW(inbuf+smb_vwv7,0);
4379 numtowrite = SVAL(inbuf,smb_vwv10);
4380 smb_doff = SVAL(inbuf,smb_vwv11);
4382 data = smb_base(inbuf) + smb_doff;
4384 /* If this fails we need to send an SMBwriteC response,
4385 not an SMBwritebmpx - set this up now so we don't forget */
4386 SCVAL(outbuf,smb_com,SMBwritec);
4388 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4389 END_PROFILE(SMBwriteBmpx);
4390 return(ERROR_DOS(ERRDOS,ERRlock));
4393 nwritten = write_file(fsp,data,startpos,numtowrite);
4395 if(lp_syncalways(SNUM(conn)) || write_through)
4396 sync_file(conn,fsp);
4398 if(nwritten < (ssize_t)numtowrite) {
4399 END_PROFILE(SMBwriteBmpx);
4400 return(UNIXERROR(ERRHRD,ERRdiskfull));
4403 /* If the maximum to be written to this file
4404 is greater than what we just wrote then set
4405 up a secondary struct to be attached to this
4406 fd, we will use this to cache error messages etc. */
4408 if((ssize_t)tcount > nwritten) {
4409 write_bmpx_struct *wbms;
4410 if(fsp->wbmpx_ptr != NULL)
4411 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4412 else
4413 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4414 if(!wbms) {
4415 DEBUG(0,("Out of memory in reply_readmpx\n"));
4416 END_PROFILE(SMBwriteBmpx);
4417 return(ERROR_DOS(ERRSRV,ERRnoresource));
4419 wbms->wr_mode = write_through;
4420 wbms->wr_discard = False; /* No errors yet */
4421 wbms->wr_total_written = nwritten;
4422 wbms->wr_errclass = 0;
4423 wbms->wr_error = 0;
4424 fsp->wbmpx_ptr = wbms;
4427 /* We are returning successfully, set the message type back to
4428 SMBwritebmpx */
4429 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4431 outsize = set_message(outbuf,1,0,True);
4433 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4435 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4436 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4438 if (write_through && tcount==nwritten) {
4439 /* We need to send both a primary and a secondary response */
4440 smb_setlen(outbuf,outsize - 4);
4441 if (!send_smb(smbd_server_fd(),outbuf))
4442 exit_server("reply_writebmpx: send_smb failed.");
4444 /* Now the secondary */
4445 outsize = set_message(outbuf,1,0,True);
4446 SCVAL(outbuf,smb_com,SMBwritec);
4447 SSVAL(outbuf,smb_vwv0,nwritten);
4450 END_PROFILE(SMBwriteBmpx);
4451 return(outsize);
4454 /****************************************************************************
4455 Reply to a SMBwritebs (write block multiplex secondary) request.
4456 ****************************************************************************/
4458 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4460 size_t numtowrite;
4461 ssize_t nwritten = -1;
4462 int outsize = 0;
4463 SMB_OFF_T startpos;
4464 size_t tcount;
4465 BOOL write_through;
4466 int smb_doff;
4467 char *data;
4468 write_bmpx_struct *wbms;
4469 BOOL send_response = False;
4470 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4471 START_PROFILE(SMBwriteBs);
4473 CHECK_FSP(fsp,conn);
4474 CHECK_WRITE(fsp);
4476 tcount = SVAL(inbuf,smb_vwv1);
4477 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4478 numtowrite = SVAL(inbuf,smb_vwv6);
4479 smb_doff = SVAL(inbuf,smb_vwv7);
4481 data = smb_base(inbuf) + smb_doff;
4483 /* We need to send an SMBwriteC response, not an SMBwritebs */
4484 SCVAL(outbuf,smb_com,SMBwritec);
4486 /* This fd should have an auxiliary struct attached,
4487 check that it does */
4488 wbms = fsp->wbmpx_ptr;
4489 if(!wbms) {
4490 END_PROFILE(SMBwriteBs);
4491 return(-1);
4494 /* If write through is set we can return errors, else we must cache them */
4495 write_through = wbms->wr_mode;
4497 /* Check for an earlier error */
4498 if(wbms->wr_discard) {
4499 END_PROFILE(SMBwriteBs);
4500 return -1; /* Just discard the packet */
4503 nwritten = write_file(fsp,data,startpos,numtowrite);
4505 if(lp_syncalways(SNUM(conn)) || write_through)
4506 sync_file(conn,fsp);
4508 if (nwritten < (ssize_t)numtowrite) {
4509 if(write_through) {
4510 /* We are returning an error - we can delete the aux struct */
4511 if (wbms)
4512 free((char *)wbms);
4513 fsp->wbmpx_ptr = NULL;
4514 END_PROFILE(SMBwriteBs);
4515 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4517 END_PROFILE(SMBwriteBs);
4518 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4521 /* Increment the total written, if this matches tcount
4522 we can discard the auxiliary struct (hurrah !) and return a writeC */
4523 wbms->wr_total_written += nwritten;
4524 if(wbms->wr_total_written >= tcount) {
4525 if (write_through) {
4526 outsize = set_message(outbuf,1,0,True);
4527 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4528 send_response = True;
4531 free((char *)wbms);
4532 fsp->wbmpx_ptr = NULL;
4535 if(send_response) {
4536 END_PROFILE(SMBwriteBs);
4537 return(outsize);
4540 END_PROFILE(SMBwriteBs);
4541 return(-1);
4544 /****************************************************************************
4545 Reply to a SMBgetattrE.
4546 ****************************************************************************/
4548 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4550 SMB_STRUCT_STAT sbuf;
4551 int outsize = 0;
4552 int mode;
4553 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4554 START_PROFILE(SMBgetattrE);
4556 outsize = set_message(outbuf,11,0,True);
4558 if(!fsp || (fsp->conn != conn)) {
4559 END_PROFILE(SMBgetattrE);
4560 return ERROR_DOS(ERRDOS,ERRbadfid);
4563 /* Do an fstat on this file */
4564 if(fsp_stat(fsp, &sbuf)) {
4565 END_PROFILE(SMBgetattrE);
4566 return(UNIXERROR(ERRDOS,ERRnoaccess));
4569 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4572 * Convert the times into dos times. Set create
4573 * date to be last modify date as UNIX doesn't save
4574 * this.
4577 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4578 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4579 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4581 if (mode & aDIR) {
4582 SIVAL(outbuf,smb_vwv6,0);
4583 SIVAL(outbuf,smb_vwv8,0);
4584 } else {
4585 uint32 allocation_size = get_allocation_size(fsp, &sbuf);
4586 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4587 SIVAL(outbuf,smb_vwv8,allocation_size);
4589 SSVAL(outbuf,smb_vwv10, mode);
4591 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4593 END_PROFILE(SMBgetattrE);
4594 return(outsize);