off by one bug in string length; CR 1159
[Samba.git] / source / smbd / reply.c
blob580878fe3205597b8d96a36ab0c952044d496fa1
1 /*
2 Unix SMB/CIFS implementation.
3 Main SMB reply routines
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Andrew Bartlett 2001
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles most of the reply_ calls that the server
23 makes to handle specific protocols
26 #include "includes.h"
28 /* look in server.c for some explanation of these variables */
29 extern int Protocol;
30 extern int max_send;
31 extern int max_recv;
32 extern char magic_char;
33 extern BOOL case_sensitive;
34 extern BOOL case_preserve;
35 extern BOOL short_case_preserve;
36 extern int global_oplock_break;
37 unsigned int smb_echo_count = 0;
39 extern BOOL global_encrypted_passwords_negotiated;
41 /****************************************************************************
42 Reply to an special message.
43 ****************************************************************************/
45 int reply_special(char *inbuf,char *outbuf)
47 int outsize = 4;
48 int msg_type = CVAL(inbuf,0);
49 int msg_flags = CVAL(inbuf,1);
50 pstring name1,name2;
52 int len;
53 char name_type = 0;
55 static BOOL already_got_session = False;
57 *name1 = *name2 = 0;
59 memset(outbuf,'\0',smb_size);
61 smb_setlen(outbuf,0);
63 switch (msg_type) {
64 case 0x81: /* session request */
66 if (already_got_session) {
67 exit_server("multiple session request not permitted");
70 SCVAL(outbuf,0,0x82);
71 SCVAL(outbuf,3,0);
72 if (name_len(inbuf+4) > 50 ||
73 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
74 DEBUG(0,("Invalid name length in session request\n"));
75 return(0);
77 name_extract(inbuf,4,name1);
78 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
79 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
80 name1,name2));
82 name1[15] = 0;
84 len = strlen(name2);
85 if (len == 16) {
86 name_type = name2[15];
87 name2[15] = 0;
90 set_local_machine_name(name1);
91 set_remote_machine_name(name2);
93 DEBUG(2,("netbios connect: local=%s remote=%s\n",
94 get_local_machine_name(), get_remote_machine_name() ));
96 if (name_type == 'R') {
97 /* We are being asked for a pathworks session ---
98 no thanks! */
99 SCVAL(outbuf, 0,0x83);
100 break;
103 /* only add the client's machine name to the list
104 of possibly valid usernames if we are operating
105 in share mode security */
106 if (lp_security() == SEC_SHARE) {
107 add_session_user(get_remote_machine_name());
110 reload_services(True);
111 reopen_logs();
113 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
115 already_got_session = True;
116 break;
118 case 0x89: /* session keepalive request
119 (some old clients produce this?) */
120 SCVAL(outbuf,0,SMBkeepalive);
121 SCVAL(outbuf,3,0);
122 break;
124 case 0x82: /* positive session response */
125 case 0x83: /* negative session response */
126 case 0x84: /* retarget session response */
127 DEBUG(0,("Unexpected session response\n"));
128 break;
130 case SMBkeepalive: /* session keepalive */
131 default:
132 return(0);
135 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
136 msg_type, msg_flags));
138 return(outsize);
141 /****************************************************************************
142 Reply to a tcon.
143 ****************************************************************************/
145 int reply_tcon(connection_struct *conn,
146 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
148 const char *service;
149 pstring service_buf;
150 pstring password;
151 pstring dev;
152 int outsize = 0;
153 uint16 vuid = SVAL(inbuf,smb_uid);
154 int pwlen=0;
155 NTSTATUS nt_status;
156 char *p;
157 DATA_BLOB password_blob;
159 START_PROFILE(SMBtcon);
161 *service_buf = *password = *dev = 0;
163 p = smb_buf(inbuf)+1;
164 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service), STR_TERMINATE) + 1;
165 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
166 p += pwlen;
167 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
169 p = strrchr_m(service_buf,'\\');
170 if (p) {
171 service = p+1;
172 } else {
173 service = service_buf;
176 password_blob = data_blob(password, pwlen+1);
178 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
180 data_blob_clear_free(&password_blob);
182 if (!conn) {
183 END_PROFILE(SMBtcon);
184 return ERROR_NT(nt_status);
187 outsize = set_message(outbuf,2,0,True);
188 SSVAL(outbuf,smb_vwv0,max_recv);
189 SSVAL(outbuf,smb_vwv1,conn->cnum);
190 SSVAL(outbuf,smb_tid,conn->cnum);
192 DEBUG(3,("tcon service=%s cnum=%d\n",
193 service, conn->cnum));
195 END_PROFILE(SMBtcon);
196 return(outsize);
199 /****************************************************************************
200 Reply to a tcon and X.
201 ****************************************************************************/
203 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
205 fstring service;
206 DATA_BLOB password;
207 pstring devicename;
208 NTSTATUS nt_status;
209 uint16 vuid = SVAL(inbuf,smb_uid);
210 int passlen = SVAL(inbuf,smb_vwv3);
211 pstring path;
212 char *p, *q;
213 extern BOOL global_encrypted_passwords_negotiated;
214 START_PROFILE(SMBtconX);
216 *service = *devicename = 0;
218 /* we might have to close an old one */
219 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
220 close_cnum(conn,vuid);
223 if (passlen > MAX_PASS_LEN) {
224 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
227 if (global_encrypted_passwords_negotiated) {
228 password = data_blob(smb_buf(inbuf),passlen);
229 } else {
230 password = data_blob(smb_buf(inbuf),passlen+1);
231 /* Ensure correct termination */
232 password.data[passlen]=0;
235 p = smb_buf(inbuf) + passlen;
236 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
239 * the service name can be either: \\server\share
240 * or share directly like on the DELL PowerVault 705
242 if (*path=='\\') {
243 q = strchr_m(path+2,'\\');
244 if (!q) {
245 END_PROFILE(SMBtconX);
246 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
248 fstrcpy(service,q+1);
250 else
251 fstrcpy(service,path);
253 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
255 DEBUG(4,("Got device type %s\n",devicename));
257 conn = make_connection(service,password,devicename,vuid,&nt_status);
259 data_blob_clear_free(&password);
261 if (!conn) {
262 END_PROFILE(SMBtconX);
263 return ERROR_NT(nt_status);
266 if (Protocol < PROTOCOL_NT1) {
267 set_message(outbuf,2,0,True);
268 p = smb_buf(outbuf);
269 p += srvstr_push(outbuf, p, devicename, -1,
270 STR_TERMINATE|STR_ASCII);
271 set_message_end(outbuf,p);
272 } else {
273 /* NT sets the fstype of IPC$ to the null string */
274 const char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
276 set_message(outbuf,3,0,True);
278 p = smb_buf(outbuf);
279 p += srvstr_push(outbuf, p, devicename, -1,
280 STR_TERMINATE|STR_ASCII);
281 p += srvstr_push(outbuf, p, fsname, -1,
282 STR_TERMINATE);
284 set_message_end(outbuf,p);
286 /* what does setting this bit do? It is set by NT4 and
287 may affect the ability to autorun mounted cdroms */
288 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
289 (lp_csc_policy(SNUM(conn)) << 2));
291 init_dfsroot(conn, inbuf, outbuf);
295 DEBUG(3,("tconX service=%s \n",
296 service));
298 /* set the incoming and outgoing tid to the just created one */
299 SSVAL(inbuf,smb_tid,conn->cnum);
300 SSVAL(outbuf,smb_tid,conn->cnum);
302 END_PROFILE(SMBtconX);
303 return chain_reply(inbuf,outbuf,length,bufsize);
306 /****************************************************************************
307 Reply to an unknown type.
308 ****************************************************************************/
310 int reply_unknown(char *inbuf,char *outbuf)
312 int type;
313 type = CVAL(inbuf,smb_com);
315 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
316 smb_fn_name(type), type, type));
318 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
321 /****************************************************************************
322 Reply to an ioctl.
323 ****************************************************************************/
325 int reply_ioctl(connection_struct *conn,
326 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
328 uint16 device = SVAL(inbuf,smb_vwv1);
329 uint16 function = SVAL(inbuf,smb_vwv2);
330 uint32 ioctl_code = (device << 16) + function;
331 int replysize, outsize;
332 char *p;
333 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
334 START_PROFILE(SMBioctl);
336 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
338 switch (ioctl_code) {
339 case IOCTL_QUERY_JOB_INFO:
340 replysize = 32;
341 break;
342 default:
343 END_PROFILE(SMBioctl);
344 return(ERROR_DOS(ERRSRV,ERRnosupport));
347 outsize = set_message(outbuf,8,replysize+1,True);
348 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
349 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
350 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
351 p = smb_buf(outbuf) + 1; /* Allow for alignment */
353 switch (ioctl_code) {
354 case IOCTL_QUERY_JOB_INFO:
356 SSVAL(p,0,fsp->rap_print_jobid); /* Job number */
357 srvstr_push(outbuf, p+2, global_myname(), 15, STR_TERMINATE|STR_ASCII);
358 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
359 break;
363 END_PROFILE(SMBioctl);
364 return outsize;
367 /****************************************************************************
368 Reply to a chkpth.
369 ****************************************************************************/
371 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
373 int outsize = 0;
374 int mode;
375 pstring name;
376 BOOL ok = False;
377 BOOL bad_path = False;
378 SMB_STRUCT_STAT sbuf;
379 START_PROFILE(SMBchkpth);
381 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
383 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
385 unix_convert(name,conn,0,&bad_path,&sbuf);
387 mode = SVAL(inbuf,smb_vwv0);
389 if (check_name(name,conn)) {
390 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
391 ok = S_ISDIR(sbuf.st_mode);
394 if (!ok) {
395 /* We special case this - as when a Windows machine
396 is parsing a path is steps through the components
397 one at a time - if a component fails it expects
398 ERRbadpath, not ERRbadfile.
400 if(errno == ENOENT)
401 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
403 return(UNIXERROR(ERRDOS,ERRbadpath));
406 outsize = set_message(outbuf,0,0,True);
408 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
410 END_PROFILE(SMBchkpth);
411 return(outsize);
414 /****************************************************************************
415 Reply to a getatr.
416 ****************************************************************************/
418 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
420 pstring fname;
421 int outsize = 0;
422 SMB_STRUCT_STAT sbuf;
423 BOOL ok = False;
424 int mode=0;
425 SMB_OFF_T size=0;
426 time_t mtime=0;
427 BOOL bad_path = False;
428 char *p;
429 START_PROFILE(SMBgetatr);
431 p = smb_buf(inbuf) + 1;
432 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
434 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
436 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
437 under WfWg - weird! */
438 if (! (*fname)) {
439 mode = aHIDDEN | aDIR;
440 if (!CAN_WRITE(conn))
441 mode |= aRONLY;
442 size = 0;
443 mtime = 0;
444 ok = True;
445 } else {
446 unix_convert(fname,conn,0,&bad_path,&sbuf);
447 if (check_name(fname,conn)) {
448 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0) {
449 mode = dos_mode(conn,fname,&sbuf);
450 size = sbuf.st_size;
451 mtime = sbuf.st_mtime;
452 if (mode & aDIR)
453 size = 0;
454 ok = True;
455 } else {
456 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
461 if (!ok) {
462 set_bad_path_error(errno, bad_path);
463 END_PROFILE(SMBgetatr);
464 return(UNIXERROR(ERRDOS,ERRbadfile));
467 outsize = set_message(outbuf,10,0,True);
469 SSVAL(outbuf,smb_vwv0,mode);
470 if(lp_dos_filetime_resolution(SNUM(conn)) )
471 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
472 else
473 put_dos_date3(outbuf,smb_vwv1,mtime);
474 SIVAL(outbuf,smb_vwv3,(uint32)size);
476 if (Protocol >= PROTOCOL_NT1)
477 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
479 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
481 END_PROFILE(SMBgetatr);
482 return(outsize);
485 /****************************************************************************
486 Reply to a setatr.
487 ****************************************************************************/
489 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
491 pstring fname;
492 int outsize = 0;
493 BOOL ok=False;
494 int mode;
495 time_t mtime;
496 SMB_STRUCT_STAT sbuf;
497 BOOL bad_path = False;
498 char *p;
500 START_PROFILE(SMBsetatr);
502 p = smb_buf(inbuf) + 1;
503 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
504 unix_convert(fname,conn,0,&bad_path,&sbuf);
506 mode = SVAL(inbuf,smb_vwv0);
507 mtime = make_unix_date3(inbuf+smb_vwv1);
509 if (VALID_STAT_OF_DIR(sbuf))
510 mode |= aDIR;
511 else
512 mode &= ~aDIR;
514 if (check_name(fname,conn))
515 ok = (file_chmod(conn,fname,mode,NULL) == 0);
516 if (ok)
517 ok = set_filetime(conn,fname,mtime);
519 if (!ok) {
520 set_bad_path_error(errno, bad_path);
521 END_PROFILE(SMBsetatr);
522 return(UNIXERROR(ERRDOS,ERRnoaccess));
525 outsize = set_message(outbuf,0,0,True);
527 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
529 END_PROFILE(SMBsetatr);
530 return(outsize);
533 /****************************************************************************
534 Reply to a dskattr.
535 ****************************************************************************/
537 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
539 int outsize = 0;
540 SMB_BIG_UINT dfree,dsize,bsize;
541 START_PROFILE(SMBdskattr);
543 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
545 outsize = set_message(outbuf,5,0,True);
547 if (Protocol <= PROTOCOL_LANMAN2) {
548 double total_space, free_space;
549 /* we need to scale this to a number that DOS6 can handle. We
550 use floating point so we can handle large drives on systems
551 that don't have 64 bit integers
553 we end up displaying a maximum of 2G to DOS systems
555 total_space = dsize * (double)bsize;
556 free_space = dfree * (double)bsize;
558 dsize = (total_space+63*512) / (64*512);
559 dfree = (free_space+63*512) / (64*512);
561 if (dsize > 0xFFFF) dsize = 0xFFFF;
562 if (dfree > 0xFFFF) dfree = 0xFFFF;
564 SSVAL(outbuf,smb_vwv0,dsize);
565 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
566 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
567 SSVAL(outbuf,smb_vwv3,dfree);
568 } else {
569 SSVAL(outbuf,smb_vwv0,dsize);
570 SSVAL(outbuf,smb_vwv1,bsize/512);
571 SSVAL(outbuf,smb_vwv2,512);
572 SSVAL(outbuf,smb_vwv3,dfree);
575 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
577 END_PROFILE(SMBdskattr);
578 return(outsize);
581 /****************************************************************************
582 Reply to a search.
583 Can be called from SMBsearch, SMBffirst or SMBfunique.
584 ****************************************************************************/
586 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
588 pstring mask;
589 pstring directory;
590 pstring fname;
591 SMB_OFF_T size;
592 int mode;
593 time_t date;
594 int dirtype;
595 int outsize = 0;
596 int numentries = 0;
597 BOOL finished = False;
598 int maxentries;
599 int i;
600 char *p;
601 BOOL ok = False;
602 int status_len;
603 pstring path;
604 char status[21];
605 int dptr_num= -1;
606 BOOL check_descend = False;
607 BOOL expect_close = False;
608 BOOL can_open = True;
609 BOOL bad_path = False;
610 START_PROFILE(SMBsearch);
612 *mask = *directory = *fname = 0;
614 /* If we were called as SMBffirst then we must expect close. */
615 if(CVAL(inbuf,smb_com) == SMBffirst)
616 expect_close = True;
618 outsize = set_message(outbuf,1,3,True);
619 maxentries = SVAL(inbuf,smb_vwv0);
620 dirtype = SVAL(inbuf,smb_vwv1);
621 p = smb_buf(inbuf) + 1;
622 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
623 p++;
624 status_len = SVAL(p, 0);
625 p += 2;
627 /* dirtype &= ~aDIR; */
629 if (status_len == 0) {
630 SMB_STRUCT_STAT sbuf;
631 pstring dir2;
633 pstrcpy(directory,path);
634 pstrcpy(dir2,path);
635 unix_convert(directory,conn,0,&bad_path,&sbuf);
636 unix_format(dir2);
638 if (!check_name(directory,conn))
639 can_open = False;
641 p = strrchr_m(dir2,'/');
642 if (p == NULL) {
643 pstrcpy(mask,dir2);
644 *dir2 = 0;
645 } else {
646 *p = 0;
647 pstrcpy(mask,p+1);
650 p = strrchr_m(directory,'/');
651 if (!p)
652 *directory = 0;
653 else
654 *p = 0;
656 if (strlen(directory) == 0)
657 pstrcpy(directory,".");
658 memset((char *)status,'\0',21);
659 SCVAL(status,0,(dirtype & 0x1F));
660 } else {
661 int status_dirtype;
663 memcpy(status,p,21);
664 status_dirtype = CVAL(status,0) & 0x1F;
665 if (status_dirtype != (dirtype & 0x1F))
666 dirtype = status_dirtype;
668 conn->dirptr = dptr_fetch(status+12,&dptr_num);
669 if (!conn->dirptr)
670 goto SearchEmpty;
671 string_set(&conn->dirpath,dptr_path(dptr_num));
672 pstrcpy(mask, dptr_wcard(dptr_num));
675 if (can_open) {
676 p = smb_buf(outbuf) + 3;
677 ok = True;
679 if (status_len == 0) {
680 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
681 if (dptr_num < 0) {
682 if(dptr_num == -2) {
683 set_bad_path_error(errno, bad_path);
684 END_PROFILE(SMBsearch);
685 return (UNIXERROR(ERRDOS,ERRnofids));
687 END_PROFILE(SMBsearch);
688 return ERROR_DOS(ERRDOS,ERRnofids);
690 dptr_set_wcard(dptr_num, strdup(mask));
691 dptr_set_attr(dptr_num, dirtype);
692 } else {
693 dirtype = dptr_attr(dptr_num);
696 DEBUG(4,("dptr_num is %d\n",dptr_num));
698 if (ok) {
699 if ((dirtype&0x1F) == aVOLID) {
700 memcpy(p,status,21);
701 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
702 dptr_fill(p+12,dptr_num);
703 if (dptr_zero(p+12) && (status_len==0))
704 numentries = 1;
705 else
706 numentries = 0;
707 p += DIR_STRUCT_SIZE;
708 } else {
709 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
710 conn->dirpath,lp_dontdescend(SNUM(conn))));
711 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
712 check_descend = True;
714 for (i=numentries;(i<maxentries) && !finished;i++) {
715 finished = !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
716 if (!finished) {
717 memcpy(p,status,21);
718 make_dir_struct(p,mask,fname,size,mode,date);
719 dptr_fill(p+12,dptr_num);
720 numentries++;
722 p += DIR_STRUCT_SIZE;
725 } /* if (ok ) */
729 SearchEmpty:
731 if (numentries == 0 || !ok) {
732 SCVAL(outbuf,smb_rcls,ERRDOS);
733 SSVAL(outbuf,smb_err,ERRnofiles);
734 dptr_close(&dptr_num);
737 /* If we were called as SMBffirst with smb_search_id == NULL
738 and no entries were found then return error and close dirptr
739 (X/Open spec) */
741 if(ok && expect_close && numentries == 0 && status_len == 0) {
742 SCVAL(outbuf,smb_rcls,ERRDOS);
743 SSVAL(outbuf,smb_err,ERRnofiles);
744 /* Also close the dptr - we know it's gone */
745 dptr_close(&dptr_num);
748 /* If we were called as SMBfunique, then we can close the dirptr now ! */
749 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
750 dptr_close(&dptr_num);
752 SSVAL(outbuf,smb_vwv0,numentries);
753 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
754 SCVAL(smb_buf(outbuf),0,5);
755 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
757 if (Protocol >= PROTOCOL_NT1)
758 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
760 outsize += DIR_STRUCT_SIZE*numentries;
761 smb_setlen(outbuf,outsize - 4);
763 if ((! *directory) && dptr_path(dptr_num))
764 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
766 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
767 smb_fn_name(CVAL(inbuf,smb_com)),
768 mask, directory, dirtype, numentries, maxentries ) );
770 END_PROFILE(SMBsearch);
771 return(outsize);
774 /****************************************************************************
775 Reply to a fclose (stop directory search).
776 ****************************************************************************/
778 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
780 int outsize = 0;
781 int status_len;
782 pstring path;
783 char status[21];
784 int dptr_num= -2;
785 char *p;
787 START_PROFILE(SMBfclose);
789 outsize = set_message(outbuf,1,0,True);
790 p = smb_buf(inbuf) + 1;
791 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
792 p++;
793 status_len = SVAL(p,0);
794 p += 2;
796 if (status_len == 0) {
797 END_PROFILE(SMBfclose);
798 return ERROR_DOS(ERRSRV,ERRsrverror);
801 memcpy(status,p,21);
803 if(dptr_fetch(status+12,&dptr_num)) {
804 /* Close the dptr - we know it's gone */
805 dptr_close(&dptr_num);
808 SSVAL(outbuf,smb_vwv0,0);
810 DEBUG(3,("search close\n"));
812 END_PROFILE(SMBfclose);
813 return(outsize);
816 /****************************************************************************
817 Reply to an open.
818 ****************************************************************************/
820 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
822 pstring fname;
823 int outsize = 0;
824 int fmode=0;
825 int share_mode;
826 SMB_OFF_T size = 0;
827 time_t mtime=0;
828 mode_t unixmode;
829 int rmode=0;
830 SMB_STRUCT_STAT sbuf;
831 BOOL bad_path = False;
832 files_struct *fsp;
833 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
834 START_PROFILE(SMBopen);
836 share_mode = SVAL(inbuf,smb_vwv0);
838 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
840 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
842 unix_convert(fname,conn,0,&bad_path,&sbuf);
844 unixmode = unix_mode(conn,aARCH,fname);
846 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
847 unixmode, oplock_request,&rmode,NULL);
849 if (!fsp) {
850 set_bad_path_error(errno, bad_path);
851 END_PROFILE(SMBopen);
852 return(UNIXERROR(ERRDOS,ERRnoaccess));
855 size = sbuf.st_size;
856 fmode = dos_mode(conn,fname,&sbuf);
857 mtime = sbuf.st_mtime;
859 if (fmode & aDIR) {
860 DEBUG(3,("attempt to open a directory %s\n",fname));
861 close_file(fsp,False);
862 END_PROFILE(SMBopen);
863 return ERROR_DOS(ERRDOS,ERRnoaccess);
866 outsize = set_message(outbuf,7,0,True);
867 SSVAL(outbuf,smb_vwv0,fsp->fnum);
868 SSVAL(outbuf,smb_vwv1,fmode);
869 if(lp_dos_filetime_resolution(SNUM(conn)) )
870 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
871 else
872 put_dos_date3(outbuf,smb_vwv2,mtime);
873 SIVAL(outbuf,smb_vwv4,(uint32)size);
874 SSVAL(outbuf,smb_vwv6,rmode);
876 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
877 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
879 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
880 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
881 END_PROFILE(SMBopen);
882 return(outsize);
885 /****************************************************************************
886 Reply to an open and X.
887 ****************************************************************************/
889 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
891 pstring fname;
892 int smb_mode = SVAL(inbuf,smb_vwv3);
893 int smb_attr = SVAL(inbuf,smb_vwv5);
894 /* Breakout the oplock request bits so we can set the
895 reply bits separately. */
896 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
897 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
898 BOOL oplock_request = ex_oplock_request | core_oplock_request;
899 #if 0
900 int open_flags = SVAL(inbuf,smb_vwv2);
901 int smb_sattr = SVAL(inbuf,smb_vwv4);
902 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
903 #endif
904 int smb_ofun = SVAL(inbuf,smb_vwv8);
905 mode_t unixmode;
906 SMB_OFF_T size=0;
907 int fmode=0,mtime=0,rmode=0;
908 SMB_STRUCT_STAT sbuf;
909 int smb_action = 0;
910 BOOL bad_path = False;
911 files_struct *fsp;
912 START_PROFILE(SMBopenX);
914 /* If it's an IPC, pass off the pipe handler. */
915 if (IS_IPC(conn)) {
916 if (lp_nt_pipe_support()) {
917 END_PROFILE(SMBopenX);
918 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
919 } else {
920 END_PROFILE(SMBopenX);
921 return ERROR_DOS(ERRSRV,ERRaccess);
925 /* XXXX we need to handle passed times, sattr and flags */
926 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
928 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
930 unix_convert(fname,conn,0,&bad_path,&sbuf);
932 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
934 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
935 oplock_request, &rmode,&smb_action);
937 if (!fsp) {
938 set_bad_path_error(errno, bad_path);
939 END_PROFILE(SMBopenX);
940 return(UNIXERROR(ERRDOS,ERRnoaccess));
943 size = sbuf.st_size;
944 fmode = dos_mode(conn,fname,&sbuf);
945 mtime = sbuf.st_mtime;
946 if (fmode & aDIR) {
947 close_file(fsp,False);
948 END_PROFILE(SMBopenX);
949 return ERROR_DOS(ERRDOS,ERRnoaccess);
952 /* If the caller set the extended oplock request bit
953 and we granted one (by whatever means) - set the
954 correct bit for extended oplock reply.
957 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn)))
958 smb_action |= EXTENDED_OPLOCK_GRANTED;
960 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
961 smb_action |= EXTENDED_OPLOCK_GRANTED;
963 /* If the caller set the core oplock request bit
964 and we granted one (by whatever means) - set the
965 correct bit for core oplock reply.
968 if (core_oplock_request && lp_fake_oplocks(SNUM(conn)))
969 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
971 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
972 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
974 set_message(outbuf,15,0,True);
975 SSVAL(outbuf,smb_vwv2,fsp->fnum);
976 SSVAL(outbuf,smb_vwv3,fmode);
977 if(lp_dos_filetime_resolution(SNUM(conn)) )
978 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
979 else
980 put_dos_date3(outbuf,smb_vwv4,mtime);
981 SIVAL(outbuf,smb_vwv6,(uint32)size);
982 SSVAL(outbuf,smb_vwv8,rmode);
983 SSVAL(outbuf,smb_vwv11,smb_action);
985 END_PROFILE(SMBopenX);
986 return chain_reply(inbuf,outbuf,length,bufsize);
989 /****************************************************************************
990 Reply to a SMBulogoffX.
991 ****************************************************************************/
993 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
995 uint16 vuid = SVAL(inbuf,smb_uid);
996 user_struct *vuser = get_valid_user_struct(vuid);
997 START_PROFILE(SMBulogoffX);
999 if(vuser == 0)
1000 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1002 /* in user level security we are supposed to close any files
1003 open by this user */
1004 if ((vuser != 0) && (lp_security() != SEC_SHARE))
1005 file_close_user(vuid);
1007 invalidate_vuid(vuid);
1009 set_message(outbuf,2,0,True);
1011 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1013 END_PROFILE(SMBulogoffX);
1014 return chain_reply(inbuf,outbuf,length,bufsize);
1017 /****************************************************************************
1018 Reply to a mknew or a create.
1019 ****************************************************************************/
1021 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1023 pstring fname;
1024 int com;
1025 int outsize = 0;
1026 int createmode;
1027 mode_t unixmode;
1028 int ofun = 0;
1029 BOOL bad_path = False;
1030 files_struct *fsp;
1031 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1032 SMB_STRUCT_STAT sbuf;
1033 START_PROFILE(SMBcreate);
1035 com = SVAL(inbuf,smb_com);
1037 createmode = SVAL(inbuf,smb_vwv0);
1038 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
1040 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1042 unix_convert(fname,conn,0,&bad_path,&sbuf);
1044 if (createmode & aVOLID)
1045 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1047 unixmode = unix_mode(conn,createmode,fname);
1049 if(com == SMBmknew) {
1050 /* We should fail if file exists. */
1051 ofun = FILE_CREATE_IF_NOT_EXIST;
1052 } else {
1053 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1054 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1057 /* Open file in dos compatibility share mode. */
1058 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1059 ofun, unixmode, oplock_request, NULL, NULL);
1061 if (!fsp) {
1062 set_bad_path_error(errno, bad_path);
1063 END_PROFILE(SMBcreate);
1064 return(UNIXERROR(ERRDOS,ERRnoaccess));
1067 outsize = set_message(outbuf,1,0,True);
1068 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1070 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1071 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1073 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1074 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1076 DEBUG( 2, ( "new file %s\n", fname ) );
1077 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n", fname, fsp->fd, createmode, (int)unixmode ) );
1079 END_PROFILE(SMBcreate);
1080 return(outsize);
1083 /****************************************************************************
1084 Reply to a create temporary file.
1085 ****************************************************************************/
1087 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1089 pstring fname;
1090 int outsize = 0;
1091 int createmode;
1092 mode_t unixmode;
1093 BOOL bad_path = False;
1094 files_struct *fsp;
1095 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1096 int tmpfd;
1097 SMB_STRUCT_STAT sbuf;
1098 char *p, *s;
1100 START_PROFILE(SMBctemp);
1102 createmode = SVAL(inbuf,smb_vwv0);
1103 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1104 pstrcat(fname,"\\TMXXXXXX");
1106 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1108 unix_convert(fname,conn,0,&bad_path,&sbuf);
1110 unixmode = unix_mode(conn,createmode,fname);
1112 tmpfd = smb_mkstemp(fname);
1113 if (tmpfd == -1) {
1114 END_PROFILE(SMBctemp);
1115 return(UNIXERROR(ERRDOS,ERRnoaccess));
1118 vfs_stat(conn,fname,&sbuf);
1120 /* Open file in dos compatibility share mode. */
1121 /* We should fail if file does not exist. */
1122 fsp = open_file_shared(conn,fname,&sbuf,
1123 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1124 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1125 unixmode, oplock_request, NULL, NULL);
1127 /* close fd from smb_mkstemp() */
1128 close(tmpfd);
1130 if (!fsp) {
1131 set_bad_path_error(errno, bad_path);
1132 END_PROFILE(SMBctemp);
1133 return(UNIXERROR(ERRDOS,ERRnoaccess));
1136 outsize = set_message(outbuf,1,0,True);
1137 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1139 /* the returned filename is relative to the directory */
1140 s = strrchr_m(fname, '/');
1141 if (!s)
1142 s = fname;
1143 else
1144 s++;
1146 p = smb_buf(outbuf);
1147 SSVALS(p, 0, -1); /* what is this? not in spec */
1148 SSVAL(p, 2, strlen(s));
1149 p += 4;
1150 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1151 outsize = set_message_end(outbuf, p);
1153 if (oplock_request && lp_fake_oplocks(SNUM(conn)))
1154 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1156 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1157 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1159 DEBUG( 2, ( "created temp file %s\n", fname ) );
1160 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1161 fname, fsp->fd, createmode, (int)unixmode ) );
1163 END_PROFILE(SMBctemp);
1164 return(outsize);
1167 /*******************************************************************
1168 Check if a user is allowed to rename a file.
1169 ********************************************************************/
1171 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1173 int smb_action;
1174 int access_mode;
1175 files_struct *fsp;
1177 if (!CAN_WRITE(conn))
1178 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1180 if (S_ISDIR(pst->st_mode))
1181 return NT_STATUS_OK;
1183 /* We need a better way to return NT status codes from open... */
1184 unix_ERR_class = 0;
1185 unix_ERR_code = 0;
1187 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1188 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1190 if (!fsp) {
1191 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1192 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1193 ret = NT_STATUS_SHARING_VIOLATION;
1194 unix_ERR_class = 0;
1195 unix_ERR_code = 0;
1196 return ret;
1198 close_file(fsp,False);
1199 return NT_STATUS_OK;
1202 /*******************************************************************
1203 Check if a user is allowed to delete a file.
1204 ********************************************************************/
1206 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1208 SMB_STRUCT_STAT sbuf;
1209 int fmode;
1210 int smb_action;
1211 int access_mode;
1212 files_struct *fsp;
1214 if (!CAN_WRITE(conn))
1215 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1217 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
1218 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1220 fmode = dos_mode(conn,fname,&sbuf);
1221 if (fmode & aDIR)
1222 return NT_STATUS_FILE_IS_A_DIRECTORY;
1223 if (!lp_delete_readonly(SNUM(conn))) {
1224 if (fmode & aRONLY)
1225 return NT_STATUS_CANNOT_DELETE;
1227 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1228 return NT_STATUS_CANNOT_DELETE;
1230 /* We need a better way to return NT status codes from open... */
1231 unix_ERR_class = 0;
1232 unix_ERR_code = 0;
1234 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1235 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1237 if (!fsp) {
1238 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1239 if (!NT_STATUS_IS_OK(unix_ERR_ntstatus))
1240 ret = unix_ERR_ntstatus;
1241 else if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1242 ret = NT_STATUS_SHARING_VIOLATION;
1243 unix_ERR_class = 0;
1244 unix_ERR_code = 0;
1245 unix_ERR_ntstatus = NT_STATUS_OK;
1246 return ret;
1248 close_file(fsp,False);
1249 return NT_STATUS_OK;
1252 /****************************************************************************
1253 The guts of the unlink command, split out so it may be called by the NT SMB
1254 code.
1255 ****************************************************************************/
1257 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1259 pstring directory;
1260 pstring mask;
1261 char *p;
1262 int count=0;
1263 NTSTATUS error = NT_STATUS_OK;
1264 BOOL has_wild;
1265 BOOL bad_path = False;
1266 BOOL rc = True;
1267 SMB_STRUCT_STAT sbuf;
1269 *directory = *mask = 0;
1271 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1273 p = strrchr_m(name,'/');
1274 if (!p) {
1275 pstrcpy(directory,".");
1276 pstrcpy(mask,name);
1277 } else {
1278 *p = 0;
1279 pstrcpy(directory,name);
1280 pstrcpy(mask,p+1);
1284 * We should only check the mangled cache
1285 * here if unix_convert failed. This means
1286 * that the path in 'mask' doesn't exist
1287 * on the file system and so we need to look
1288 * for a possible mangle. This patch from
1289 * Tine Smukavec <valentin.smukavec@hermes.si>.
1292 if (!rc && mangle_is_mangled(mask))
1293 mangle_check_cache( mask );
1295 has_wild = ms_has_wild(mask);
1297 if (!has_wild) {
1298 pstrcat(directory,"/");
1299 pstrcat(directory,mask);
1300 error = can_delete(directory,conn,dirtype);
1301 if (!NT_STATUS_IS_OK(error)) return error;
1303 if (vfs_unlink(conn,directory) == 0) {
1304 count++;
1306 } else {
1307 void *dirptr = NULL;
1308 char *dname;
1310 if (check_name(directory,conn))
1311 dirptr = OpenDir(conn, directory, True);
1313 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1314 the pattern matches against the long name, otherwise the short name
1315 We don't implement this yet XXXX
1318 if (dirptr) {
1319 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1321 if (strequal(mask,"????????.???"))
1322 pstrcpy(mask,"*");
1324 while ((dname = ReadDirName(dirptr))) {
1325 pstring fname;
1326 pstrcpy(fname,dname);
1328 if(!mask_match(fname, mask, case_sensitive)) continue;
1330 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1331 error = can_delete(fname,conn,dirtype);
1332 if (!NT_STATUS_IS_OK(error)) continue;
1333 if (vfs_unlink(conn,fname) == 0) count++;
1334 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1336 CloseDir(dirptr);
1340 if (count == 0 && NT_STATUS_IS_OK(error)) {
1341 error = map_nt_error_from_unix(errno);
1344 return error;
1347 /****************************************************************************
1348 Reply to a unlink
1349 ****************************************************************************/
1351 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1352 int dum_buffsize)
1354 int outsize = 0;
1355 pstring name;
1356 int dirtype;
1357 NTSTATUS status;
1358 START_PROFILE(SMBunlink);
1360 dirtype = SVAL(inbuf,smb_vwv0);
1362 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1364 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1366 DEBUG(3,("reply_unlink : %s\n",name));
1368 status = unlink_internals(conn, dirtype, name);
1369 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1372 * Win2k needs a changenotify request response before it will
1373 * update after a rename..
1375 process_pending_change_notify_queue((time_t)0);
1377 outsize = set_message(outbuf,0,0,True);
1379 END_PROFILE(SMBunlink);
1380 return outsize;
1383 /****************************************************************************
1384 Fail for readbraw.
1385 ****************************************************************************/
1387 void fail_readraw(void)
1389 pstring errstr;
1390 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1391 strerror(errno) );
1392 exit_server(errstr);
1395 /****************************************************************************
1396 Use sendfile in readbraw.
1397 ****************************************************************************/
1399 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1400 ssize_t mincount, char *outbuf)
1402 ssize_t ret=0;
1404 #if defined(WITH_SENDFILE)
1406 * We can only use sendfile on a non-chained packet and on a file
1407 * that is exclusively oplocked. reply_readbraw has already checked the length.
1410 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1411 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1412 DATA_BLOB header;
1414 _smb_setlen(outbuf,nread);
1415 header.data = outbuf;
1416 header.length = 4;
1417 header.free = NULL;
1419 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1421 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1422 * return ENOSYS then pretend we just got a normal read.
1424 if (errno == ENOSYS)
1425 goto normal_read;
1427 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1428 fsp->fsp_name, strerror(errno) ));
1429 exit_server("send_file_readbraw sendfile failed");
1434 normal_read:
1435 #endif
1437 if (nread > 0) {
1438 ret = read_file(fsp,outbuf+4,startpos,nread);
1439 if (ret < mincount)
1440 ret = 0;
1443 _smb_setlen(outbuf,ret);
1444 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1445 fail_readraw();
1448 /****************************************************************************
1449 Reply to a readbraw (core+ protocol).
1450 ****************************************************************************/
1452 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1454 ssize_t maxcount,mincount;
1455 size_t nread = 0;
1456 SMB_OFF_T startpos;
1457 char *header = outbuf;
1458 files_struct *fsp;
1459 START_PROFILE(SMBreadbraw);
1462 * Special check if an oplock break has been issued
1463 * and the readraw request croses on the wire, we must
1464 * return a zero length response here.
1467 if(global_oplock_break) {
1468 _smb_setlen(header,0);
1469 if (write_data(smbd_server_fd(),header,4) != 4)
1470 fail_readraw();
1471 DEBUG(5,("readbraw - oplock break finished\n"));
1472 END_PROFILE(SMBreadbraw);
1473 return -1;
1476 fsp = file_fsp(inbuf,smb_vwv0);
1478 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1480 * fsp could be NULL here so use the value from the packet. JRA.
1482 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1483 _smb_setlen(header,0);
1484 if (write_data(smbd_server_fd(),header,4) != 4)
1485 fail_readraw();
1486 END_PROFILE(SMBreadbraw);
1487 return(-1);
1490 CHECK_FSP(fsp,conn);
1492 flush_write_cache(fsp, READRAW_FLUSH);
1494 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
1495 if(CVAL(inbuf,smb_wct) == 10) {
1497 * This is a large offset (64 bit) read.
1499 #ifdef LARGE_SMB_OFF_T
1501 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1503 #else /* !LARGE_SMB_OFF_T */
1506 * Ensure we haven't been sent a >32 bit offset.
1509 if(IVAL(inbuf,smb_vwv8) != 0) {
1510 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1511 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1512 _smb_setlen(header,0);
1513 if (write_data(smbd_server_fd(),header,4) != 4)
1514 fail_readraw();
1515 END_PROFILE(SMBreadbraw);
1516 return(-1);
1519 #endif /* LARGE_SMB_OFF_T */
1521 if(startpos < 0) {
1522 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1523 _smb_setlen(header,0);
1524 if (write_data(smbd_server_fd(),header,4) != 4)
1525 fail_readraw();
1526 END_PROFILE(SMBreadbraw);
1527 return(-1);
1530 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1531 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1533 /* ensure we don't overrun the packet size */
1534 maxcount = MIN(65535,maxcount);
1535 maxcount = MAX(mincount,maxcount);
1537 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1538 SMB_OFF_T size = fsp->size;
1539 SMB_OFF_T sizeneeded = startpos + maxcount;
1541 if (size < sizeneeded) {
1542 SMB_STRUCT_STAT st;
1543 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1544 size = st.st_size;
1545 if (!fsp->can_write)
1546 fsp->size = size;
1549 if (startpos >= size)
1550 nread = 0;
1551 else
1552 nread = MIN(maxcount,(size - startpos));
1555 if (nread < mincount)
1556 nread = 0;
1558 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1559 (int)maxcount, (int)mincount, (int)nread ) );
1561 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1563 DEBUG(5,("readbraw finished\n"));
1564 END_PROFILE(SMBreadbraw);
1565 return -1;
1568 /****************************************************************************
1569 Reply to a lockread (core+ protocol).
1570 ****************************************************************************/
1572 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1574 ssize_t nread = -1;
1575 char *data;
1576 int outsize = 0;
1577 SMB_OFF_T startpos;
1578 size_t numtoread;
1579 NTSTATUS status;
1580 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1581 START_PROFILE(SMBlockread);
1583 CHECK_FSP(fsp,conn);
1584 CHECK_READ(fsp);
1586 release_level_2_oplocks_on_change(fsp);
1588 numtoread = SVAL(inbuf,smb_vwv1);
1589 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1591 outsize = set_message(outbuf,5,3,True);
1592 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1593 data = smb_buf(outbuf) + 3;
1596 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1597 * protocol request that predates the read/write lock concept.
1598 * Thus instead of asking for a read lock here we need to ask
1599 * for a write lock. JRA.
1602 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1603 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1605 if (NT_STATUS_V(status)) {
1606 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
1608 * A blocking lock was requested. Package up
1609 * this smb into a queued request and push it
1610 * onto the blocking lock queue.
1612 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
1613 END_PROFILE(SMBlockread);
1614 return -1;
1617 END_PROFILE(SMBlockread);
1618 return ERROR_NT(status);
1621 nread = read_file(fsp,data,startpos,numtoread);
1623 if (nread < 0) {
1624 END_PROFILE(SMBlockread);
1625 return(UNIXERROR(ERRDOS,ERRnoaccess));
1628 outsize += nread;
1629 SSVAL(outbuf,smb_vwv0,nread);
1630 SSVAL(outbuf,smb_vwv5,nread+3);
1631 SSVAL(smb_buf(outbuf),1,nread);
1633 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1634 fsp->fnum, (int)numtoread, (int)nread));
1636 END_PROFILE(SMBlockread);
1637 return(outsize);
1640 /****************************************************************************
1641 Reply to a read.
1642 ****************************************************************************/
1644 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1646 size_t numtoread;
1647 ssize_t nread = 0;
1648 char *data;
1649 SMB_OFF_T startpos;
1650 int outsize = 0;
1651 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1652 START_PROFILE(SMBread);
1654 CHECK_FSP(fsp,conn);
1655 CHECK_READ(fsp);
1657 numtoread = SVAL(inbuf,smb_vwv1);
1658 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1660 outsize = set_message(outbuf,5,3,True);
1661 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1662 data = smb_buf(outbuf) + 3;
1664 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1665 END_PROFILE(SMBread);
1666 return ERROR_DOS(ERRDOS,ERRlock);
1669 if (numtoread > 0)
1670 nread = read_file(fsp,data,startpos,numtoread);
1672 if (nread < 0) {
1673 END_PROFILE(SMBread);
1674 return(UNIXERROR(ERRDOS,ERRnoaccess));
1677 outsize += nread;
1678 SSVAL(outbuf,smb_vwv0,nread);
1679 SSVAL(outbuf,smb_vwv5,nread+3);
1680 SCVAL(smb_buf(outbuf),0,1);
1681 SSVAL(smb_buf(outbuf),1,nread);
1683 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1684 fsp->fnum, (int)numtoread, (int)nread ) );
1686 END_PROFILE(SMBread);
1687 return(outsize);
1690 /****************************************************************************
1691 Reply to a read and X - possibly using sendfile.
1692 ****************************************************************************/
1694 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1695 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1697 ssize_t nread = -1;
1698 char *data = smb_buf(outbuf);
1700 #if defined(WITH_SENDFILE)
1702 * We can only use sendfile on a non-chained packet and on a file
1703 * that is exclusively oplocked.
1706 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1707 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1708 SMB_STRUCT_STAT sbuf;
1709 DATA_BLOB header;
1711 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1)
1712 return(UNIXERROR(ERRDOS,ERRnoaccess));
1714 if (startpos > sbuf.st_size)
1715 goto normal_read;
1717 if (smb_maxcnt > (sbuf.st_size - startpos))
1718 smb_maxcnt = (sbuf.st_size - startpos);
1720 if (smb_maxcnt == 0)
1721 goto normal_read;
1724 * Set up the packet header before send. We
1725 * assume here the sendfile will work (get the
1726 * correct amount of data).
1729 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1730 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1731 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1732 SCVAL(outbuf,smb_vwv0,0xFF);
1733 set_message(outbuf,12,smb_maxcnt,False);
1734 header.data = outbuf;
1735 header.length = data - outbuf;
1736 header.free = NULL;
1738 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1740 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1741 * return ENOSYS then pretend we just got a normal read.
1743 if (errno == ENOSYS)
1744 goto normal_read;
1746 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1747 fsp->fsp_name, strerror(errno) ));
1748 exit_server("send_file_readX sendfile failed");
1751 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1752 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1753 return -1;
1756 normal_read:
1758 #endif
1760 nread = read_file(fsp,data,startpos,smb_maxcnt);
1762 if (nread < 0) {
1763 END_PROFILE(SMBreadX);
1764 return(UNIXERROR(ERRDOS,ERRnoaccess));
1767 SSVAL(outbuf,smb_vwv5,nread);
1768 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1769 SSVAL(smb_buf(outbuf),-2,nread);
1771 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1772 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1774 return nread;
1777 /****************************************************************************
1778 Reply to a read and X.
1779 ****************************************************************************/
1781 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1783 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1784 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1785 ssize_t nread = -1;
1786 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1787 #if 0
1788 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1789 #endif
1791 START_PROFILE(SMBreadX);
1793 /* If it's an IPC, pass off the pipe handler. */
1794 if (IS_IPC(conn)) {
1795 END_PROFILE(SMBreadX);
1796 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1799 CHECK_FSP(fsp,conn);
1800 CHECK_READ(fsp);
1802 set_message(outbuf,12,0,True);
1804 if(CVAL(inbuf,smb_wct) == 12) {
1805 #ifdef LARGE_SMB_OFF_T
1807 * This is a large offset (64 bit) read.
1809 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1811 #else /* !LARGE_SMB_OFF_T */
1814 * Ensure we haven't been sent a >32 bit offset.
1817 if(IVAL(inbuf,smb_vwv10) != 0) {
1818 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1819 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1820 END_PROFILE(SMBreadX);
1821 return ERROR_DOS(ERRDOS,ERRbadaccess);
1824 #endif /* LARGE_SMB_OFF_T */
1828 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1829 END_PROFILE(SMBreadX);
1830 return ERROR_DOS(ERRDOS,ERRlock);
1833 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
1834 if (nread != -1)
1835 nread = chain_reply(inbuf,outbuf,length,bufsize);
1837 END_PROFILE(SMBreadX);
1838 return nread;
1841 /****************************************************************************
1842 Reply to a writebraw (core+ or LANMAN1.0 protocol).
1843 ****************************************************************************/
1845 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1847 ssize_t nwritten=0;
1848 ssize_t total_written=0;
1849 size_t numtowrite=0;
1850 size_t tcount;
1851 SMB_OFF_T startpos;
1852 char *data=NULL;
1853 BOOL write_through;
1854 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1855 int outsize = 0;
1856 START_PROFILE(SMBwritebraw);
1858 CHECK_FSP(fsp,conn);
1859 CHECK_WRITE(fsp);
1861 tcount = IVAL(inbuf,smb_vwv1);
1862 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
1863 write_through = BITSETW(inbuf+smb_vwv7,0);
1865 /* We have to deal with slightly different formats depending
1866 on whether we are using the core+ or lanman1.0 protocol */
1868 if(Protocol <= PROTOCOL_COREPLUS) {
1869 numtowrite = SVAL(smb_buf(inbuf),-2);
1870 data = smb_buf(inbuf);
1871 } else {
1872 numtowrite = SVAL(inbuf,smb_vwv10);
1873 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1876 /* force the error type */
1877 SCVAL(inbuf,smb_com,SMBwritec);
1878 SCVAL(outbuf,smb_com,SMBwritec);
1880 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1881 END_PROFILE(SMBwritebraw);
1882 return(ERROR_DOS(ERRDOS,ERRlock));
1885 if (numtowrite>0)
1886 nwritten = write_file(fsp,data,startpos,numtowrite);
1888 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1889 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1891 if (nwritten < (ssize_t)numtowrite) {
1892 END_PROFILE(SMBwritebraw);
1893 return(UNIXERROR(ERRHRD,ERRdiskfull));
1896 total_written = nwritten;
1898 /* Return a message to the redirector to tell it to send more bytes */
1899 SCVAL(outbuf,smb_com,SMBwritebraw);
1900 SSVALS(outbuf,smb_vwv0,-1);
1901 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1902 if (!send_smb(smbd_server_fd(),outbuf))
1903 exit_server("reply_writebraw: send_smb failed.");
1905 /* Now read the raw data into the buffer and write it */
1906 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1907 exit_server("secondary writebraw failed");
1910 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1911 numtowrite = smb_len(inbuf);
1913 /* Set up outbuf to return the correct return */
1914 outsize = set_message(outbuf,1,0,True);
1915 SCVAL(outbuf,smb_com,SMBwritec);
1916 SSVAL(outbuf,smb_vwv0,total_written);
1918 if (numtowrite != 0) {
1920 if (numtowrite > BUFFER_SIZE) {
1921 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1922 (unsigned int)numtowrite ));
1923 exit_server("secondary writebraw failed");
1926 if (tcount > nwritten+numtowrite) {
1927 DEBUG(3,("Client overestimated the write %d %d %d\n",
1928 (int)tcount,(int)nwritten,(int)numtowrite));
1931 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1932 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1933 strerror(errno) ));
1934 exit_server("secondary writebraw failed");
1937 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1939 if (nwritten < (ssize_t)numtowrite) {
1940 SCVAL(outbuf,smb_rcls,ERRHRD);
1941 SSVAL(outbuf,smb_err,ERRdiskfull);
1944 if (nwritten > 0)
1945 total_written += nwritten;
1948 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1949 sync_file(conn,fsp);
1951 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1952 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1954 /* we won't return a status if write through is not selected - this follows what WfWg does */
1955 END_PROFILE(SMBwritebraw);
1956 if (!write_through && total_written==tcount) {
1958 #if RABBIT_PELLET_FIX
1960 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
1961 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
1963 if (!send_keepalive(smbd_server_fd()))
1964 exit_server("reply_writebraw: send of keepalive failed");
1965 #endif
1966 return(-1);
1969 return(outsize);
1972 /****************************************************************************
1973 Reply to a writeunlock (core+).
1974 ****************************************************************************/
1976 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
1977 int size, int dum_buffsize)
1979 ssize_t nwritten = -1;
1980 size_t numtowrite;
1981 SMB_OFF_T startpos;
1982 char *data;
1983 NTSTATUS status;
1984 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1985 int outsize = 0;
1986 START_PROFILE(SMBwriteunlock);
1988 CHECK_FSP(fsp,conn);
1989 CHECK_WRITE(fsp);
1991 numtowrite = SVAL(inbuf,smb_vwv1);
1992 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
1993 data = smb_buf(inbuf) + 3;
1995 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
1996 WRITE_LOCK,False)) {
1997 END_PROFILE(SMBwriteunlock);
1998 return ERROR_DOS(ERRDOS,ERRlock);
2001 /* The special X/Open SMB protocol handling of
2002 zero length writes is *NOT* done for
2003 this call */
2004 if(numtowrite == 0)
2005 nwritten = 0;
2006 else
2007 nwritten = write_file(fsp,data,startpos,numtowrite);
2009 if (lp_syncalways(SNUM(conn)))
2010 sync_file(conn,fsp);
2012 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2013 END_PROFILE(SMBwriteunlock);
2014 return(UNIXERROR(ERRHRD,ERRdiskfull));
2017 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2018 (SMB_BIG_UINT)startpos);
2019 if (NT_STATUS_V(status)) {
2020 END_PROFILE(SMBwriteunlock);
2021 return ERROR_NT(status);
2024 outsize = set_message(outbuf,1,0,True);
2026 SSVAL(outbuf,smb_vwv0,nwritten);
2028 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2029 fsp->fnum, (int)numtowrite, (int)nwritten));
2031 END_PROFILE(SMBwriteunlock);
2032 return outsize;
2035 /****************************************************************************
2036 Reply to a write.
2037 ****************************************************************************/
2039 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2041 size_t numtowrite;
2042 ssize_t nwritten = -1;
2043 SMB_OFF_T startpos;
2044 char *data;
2045 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2046 int outsize = 0;
2047 START_PROFILE(SMBwrite);
2049 /* If it's an IPC, pass off the pipe handler. */
2050 if (IS_IPC(conn)) {
2051 END_PROFILE(SMBwrite);
2052 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2055 CHECK_FSP(fsp,conn);
2056 CHECK_WRITE(fsp);
2058 numtowrite = SVAL(inbuf,smb_vwv1);
2059 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2060 data = smb_buf(inbuf) + 3;
2062 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2063 END_PROFILE(SMBwrite);
2064 return ERROR_DOS(ERRDOS,ERRlock);
2068 * X/Open SMB protocol says that if smb_vwv1 is
2069 * zero then the file size should be extended or
2070 * truncated to the size given in smb_vwv[2-3].
2073 if(numtowrite == 0) {
2075 * This is actually an allocate call, and set EOF. JRA.
2077 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2078 if (nwritten < 0) {
2079 END_PROFILE(SMBwrite);
2080 return ERROR_NT(NT_STATUS_DISK_FULL);
2082 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2083 if (nwritten < 0) {
2084 END_PROFILE(SMBwrite);
2085 return ERROR_NT(NT_STATUS_DISK_FULL);
2087 } else
2088 nwritten = write_file(fsp,data,startpos,numtowrite);
2090 if (lp_syncalways(SNUM(conn)))
2091 sync_file(conn,fsp);
2093 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2094 END_PROFILE(SMBwrite);
2095 return(UNIXERROR(ERRHRD,ERRdiskfull));
2098 outsize = set_message(outbuf,1,0,True);
2100 SSVAL(outbuf,smb_vwv0,nwritten);
2102 if (nwritten < (ssize_t)numtowrite) {
2103 SCVAL(outbuf,smb_rcls,ERRHRD);
2104 SSVAL(outbuf,smb_err,ERRdiskfull);
2107 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2109 END_PROFILE(SMBwrite);
2110 return(outsize);
2113 /****************************************************************************
2114 Reply to a write and X.
2115 ****************************************************************************/
2117 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2119 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2120 SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
2121 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2122 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2123 ssize_t nwritten = -1;
2124 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2125 unsigned int smblen = smb_len(inbuf);
2126 char *data;
2127 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2128 START_PROFILE(SMBwriteX);
2130 /* If it's an IPC, pass off the pipe handler. */
2131 if (IS_IPC(conn)) {
2132 END_PROFILE(SMBwriteX);
2133 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2136 CHECK_FSP(fsp,conn);
2137 CHECK_WRITE(fsp);
2139 /* Deal with possible LARGE_WRITEX */
2140 if (large_writeX)
2141 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2143 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2144 END_PROFILE(SMBwriteX);
2145 return ERROR_DOS(ERRDOS,ERRbadmem);
2148 data = smb_base(inbuf) + smb_doff;
2150 if(CVAL(inbuf,smb_wct) == 14) {
2151 #ifdef LARGE_SMB_OFF_T
2153 * This is a large offset (64 bit) write.
2155 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2157 #else /* !LARGE_SMB_OFF_T */
2160 * Ensure we haven't been sent a >32 bit offset.
2163 if(IVAL(inbuf,smb_vwv12) != 0) {
2164 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2165 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2166 END_PROFILE(SMBwriteX);
2167 return ERROR_DOS(ERRDOS,ERRbadaccess);
2170 #endif /* LARGE_SMB_OFF_T */
2173 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2174 END_PROFILE(SMBwriteX);
2175 return ERROR_DOS(ERRDOS,ERRlock);
2178 /* X/Open SMB protocol says that, unlike SMBwrite
2179 if the length is zero then NO truncation is
2180 done, just a write of zero. To truncate a file,
2181 use SMBwrite. */
2183 if(numtowrite == 0)
2184 nwritten = 0;
2185 else
2186 nwritten = write_file(fsp,data,startpos,numtowrite);
2188 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2189 END_PROFILE(SMBwriteX);
2190 return(UNIXERROR(ERRHRD,ERRdiskfull));
2193 set_message(outbuf,6,0,True);
2195 SSVAL(outbuf,smb_vwv2,nwritten);
2196 if (large_writeX)
2197 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2199 if (nwritten < (ssize_t)numtowrite) {
2200 SCVAL(outbuf,smb_rcls,ERRHRD);
2201 SSVAL(outbuf,smb_err,ERRdiskfull);
2204 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2205 fsp->fnum, (int)numtowrite, (int)nwritten));
2207 if (lp_syncalways(SNUM(conn)) || write_through)
2208 sync_file(conn,fsp);
2210 END_PROFILE(SMBwriteX);
2211 return chain_reply(inbuf,outbuf,length,bufsize);
2214 /****************************************************************************
2215 Reply to a lseek.
2216 ****************************************************************************/
2218 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2220 SMB_OFF_T startpos;
2221 SMB_OFF_T res= -1;
2222 int mode,umode;
2223 int outsize = 0;
2224 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2225 START_PROFILE(SMBlseek);
2227 CHECK_FSP(fsp,conn);
2229 flush_write_cache(fsp, SEEK_FLUSH);
2231 mode = SVAL(inbuf,smb_vwv1) & 3;
2232 /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */
2233 startpos = (SMB_OFF_T)IVALS(inbuf,smb_vwv2);
2235 switch (mode) {
2236 case 0:
2237 umode = SEEK_SET;
2238 break;
2239 case 1:
2240 umode = SEEK_CUR;
2241 break;
2242 case 2:
2243 umode = SEEK_END;
2244 break;
2245 default:
2246 umode = SEEK_SET;
2247 break;
2250 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2252 * Check for the special case where a seek before the start
2253 * of the file sets the offset to zero. Added in the CIFS spec,
2254 * section 4.2.7.
2257 if(errno == EINVAL) {
2258 SMB_OFF_T current_pos = startpos;
2260 if(umode == SEEK_CUR) {
2262 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2263 END_PROFILE(SMBlseek);
2264 return(UNIXERROR(ERRDOS,ERRnoaccess));
2267 current_pos += startpos;
2269 } else if (umode == SEEK_END) {
2271 SMB_STRUCT_STAT sbuf;
2273 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2274 END_PROFILE(SMBlseek);
2275 return(UNIXERROR(ERRDOS,ERRnoaccess));
2278 current_pos += sbuf.st_size;
2281 if(current_pos < 0)
2282 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2285 if(res == -1) {
2286 END_PROFILE(SMBlseek);
2287 return(UNIXERROR(ERRDOS,ERRnoaccess));
2291 fsp->pos = res;
2293 outsize = set_message(outbuf,2,0,True);
2294 SIVAL(outbuf,smb_vwv0,res);
2296 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2297 fsp->fnum, (double)startpos, (double)res, mode));
2299 END_PROFILE(SMBlseek);
2300 return(outsize);
2303 /****************************************************************************
2304 Reply to a flush.
2305 ****************************************************************************/
2307 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2309 int outsize = set_message(outbuf,0,0,True);
2310 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2311 START_PROFILE(SMBflush);
2313 CHECK_FSP(fsp,conn);
2315 if (!fsp) {
2316 file_sync_all(conn);
2317 } else {
2318 sync_file(conn,fsp);
2321 DEBUG(3,("flush\n"));
2322 END_PROFILE(SMBflush);
2323 return(outsize);
2326 /****************************************************************************
2327 Reply to a exit.
2328 ****************************************************************************/
2330 int reply_exit(connection_struct *conn,
2331 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2333 int outsize;
2334 START_PROFILE(SMBexit);
2335 outsize = set_message(outbuf,0,0,True);
2337 DEBUG(3,("exit\n"));
2339 END_PROFILE(SMBexit);
2340 return(outsize);
2343 /****************************************************************************
2344 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2345 ****************************************************************************/
2347 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2348 int dum_buffsize)
2350 int outsize = 0;
2351 time_t mtime;
2352 int32 eclass = 0, err = 0;
2353 files_struct *fsp = NULL;
2354 START_PROFILE(SMBclose);
2356 outsize = set_message(outbuf,0,0,True);
2358 /* If it's an IPC, pass off to the pipe handler. */
2359 if (IS_IPC(conn)) {
2360 END_PROFILE(SMBclose);
2361 return reply_pipe_close(conn, inbuf,outbuf);
2364 fsp = file_fsp(inbuf,smb_vwv0);
2367 * We can only use CHECK_FSP if we know it's not a directory.
2370 if(!fsp || (fsp->conn != conn)) {
2371 END_PROFILE(SMBclose);
2372 return ERROR_DOS(ERRDOS,ERRbadfid);
2375 if(fsp->is_directory) {
2377 * Special case - close NT SMB directory handle.
2379 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2380 close_file(fsp,True);
2381 } else {
2383 * Close ordinary file.
2385 int close_err;
2386 pstring file_name;
2388 /* Save the name for time set in close. */
2389 pstrcpy( file_name, fsp->fsp_name);
2391 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2392 fsp->fd, fsp->fnum,
2393 conn->num_files_open));
2396 * close_file() returns the unix errno if an error
2397 * was detected on close - normally this is due to
2398 * a disk full error. If not then it was probably an I/O error.
2401 if((close_err = close_file(fsp,True)) != 0) {
2402 errno = close_err;
2403 END_PROFILE(SMBclose);
2404 return (UNIXERROR(ERRHRD,ERRgeneral));
2408 * Now take care of any time sent in the close.
2411 mtime = make_unix_date3(inbuf+smb_vwv1);
2413 /* try and set the date */
2414 set_filetime(conn, file_name, mtime);
2418 /* We have a cached error */
2419 if(eclass || err) {
2420 END_PROFILE(SMBclose);
2421 return ERROR_DOS(eclass,err);
2424 END_PROFILE(SMBclose);
2425 return(outsize);
2428 /****************************************************************************
2429 Reply to a writeclose (Core+ protocol).
2430 ****************************************************************************/
2432 int reply_writeclose(connection_struct *conn,
2433 char *inbuf,char *outbuf, int size, int dum_buffsize)
2435 size_t numtowrite;
2436 ssize_t nwritten = -1;
2437 int outsize = 0;
2438 int close_err = 0;
2439 SMB_OFF_T startpos;
2440 char *data;
2441 time_t mtime;
2442 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2443 START_PROFILE(SMBwriteclose);
2445 CHECK_FSP(fsp,conn);
2446 CHECK_WRITE(fsp);
2448 numtowrite = SVAL(inbuf,smb_vwv1);
2449 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
2450 mtime = make_unix_date3(inbuf+smb_vwv4);
2451 data = smb_buf(inbuf) + 1;
2453 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2454 END_PROFILE(SMBwriteclose);
2455 return ERROR_DOS(ERRDOS,ERRlock);
2458 nwritten = write_file(fsp,data,startpos,numtowrite);
2460 set_filetime(conn, fsp->fsp_name,mtime);
2462 close_err = close_file(fsp,True);
2464 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2465 fsp->fnum, (int)numtowrite, (int)nwritten,
2466 conn->num_files_open));
2468 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2469 END_PROFILE(SMBwriteclose);
2470 return(UNIXERROR(ERRHRD,ERRdiskfull));
2473 if(close_err != 0) {
2474 errno = close_err;
2475 END_PROFILE(SMBwriteclose);
2476 return(UNIXERROR(ERRHRD,ERRgeneral));
2479 outsize = set_message(outbuf,1,0,True);
2481 SSVAL(outbuf,smb_vwv0,nwritten);
2482 END_PROFILE(SMBwriteclose);
2483 return(outsize);
2486 /****************************************************************************
2487 Reply to a lock.
2488 ****************************************************************************/
2490 int reply_lock(connection_struct *conn,
2491 char *inbuf,char *outbuf, int length, int dum_buffsize)
2493 int outsize = set_message(outbuf,0,0,True);
2494 SMB_BIG_UINT count,offset;
2495 NTSTATUS status;
2496 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2497 START_PROFILE(SMBlock);
2499 CHECK_FSP(fsp,conn);
2501 release_level_2_oplocks_on_change(fsp);
2503 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2504 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2506 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2507 fsp->fd, fsp->fnum, (double)offset, (double)count));
2509 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2510 if (NT_STATUS_V(status)) {
2511 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2513 * A blocking lock was requested. Package up
2514 * this smb into a queued request and push it
2515 * onto the blocking lock queue.
2517 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2518 END_PROFILE(SMBlock);
2519 return -1;
2522 END_PROFILE(SMBlock);
2523 return ERROR_NT(status);
2526 END_PROFILE(SMBlock);
2527 return(outsize);
2530 /****************************************************************************
2531 Reply to a unlock.
2532 ****************************************************************************/
2534 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2535 int dum_buffsize)
2537 int outsize = set_message(outbuf,0,0,True);
2538 SMB_BIG_UINT count,offset;
2539 NTSTATUS status;
2540 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2541 START_PROFILE(SMBunlock);
2543 CHECK_FSP(fsp,conn);
2545 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2546 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2548 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2549 if (NT_STATUS_V(status)) {
2550 END_PROFILE(SMBunlock);
2551 return ERROR_NT(status);
2554 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2555 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2557 END_PROFILE(SMBunlock);
2558 return(outsize);
2561 /****************************************************************************
2562 Reply to a tdis.
2563 ****************************************************************************/
2565 int reply_tdis(connection_struct *conn,
2566 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2568 int outsize = set_message(outbuf,0,0,True);
2569 uint16 vuid;
2570 START_PROFILE(SMBtdis);
2572 vuid = SVAL(inbuf,smb_uid);
2574 if (!conn) {
2575 DEBUG(4,("Invalid connection in tdis\n"));
2576 END_PROFILE(SMBtdis);
2577 return ERROR_DOS(ERRSRV,ERRinvnid);
2580 conn->used = False;
2582 close_cnum(conn,vuid);
2584 END_PROFILE(SMBtdis);
2585 return outsize;
2588 /****************************************************************************
2589 Reply to a echo.
2590 ****************************************************************************/
2592 int reply_echo(connection_struct *conn,
2593 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2595 int smb_reverb = SVAL(inbuf,smb_vwv0);
2596 int seq_num;
2597 unsigned int data_len = smb_buflen(inbuf);
2598 int outsize = set_message(outbuf,1,data_len,True);
2599 START_PROFILE(SMBecho);
2601 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2603 /* copy any incoming data back out */
2604 if (data_len > 0)
2605 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2607 if (smb_reverb > 100) {
2608 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2609 smb_reverb = 100;
2612 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2613 SSVAL(outbuf,smb_vwv0,seq_num);
2615 smb_setlen(outbuf,outsize - 4);
2617 if (!send_smb(smbd_server_fd(),outbuf))
2618 exit_server("reply_echo: send_smb failed.");
2621 DEBUG(3,("echo %d times\n", smb_reverb));
2623 smb_echo_count++;
2625 END_PROFILE(SMBecho);
2626 return -1;
2629 /****************************************************************************
2630 Reply to a printopen.
2631 ****************************************************************************/
2633 int reply_printopen(connection_struct *conn,
2634 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2636 int outsize = 0;
2637 files_struct *fsp;
2638 START_PROFILE(SMBsplopen);
2640 if (!CAN_PRINT(conn)) {
2641 END_PROFILE(SMBsplopen);
2642 return ERROR_DOS(ERRDOS,ERRnoaccess);
2645 /* Open for exclusive use, write only. */
2646 fsp = print_fsp_open(conn, NULL);
2648 if (!fsp) {
2649 END_PROFILE(SMBsplopen);
2650 return(UNIXERROR(ERRDOS,ERRnoaccess));
2653 outsize = set_message(outbuf,1,0,True);
2654 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2656 DEBUG(3,("openprint fd=%d fnum=%d\n",
2657 fsp->fd, fsp->fnum));
2659 END_PROFILE(SMBsplopen);
2660 return(outsize);
2663 /****************************************************************************
2664 Reply to a printclose.
2665 ****************************************************************************/
2667 int reply_printclose(connection_struct *conn,
2668 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2670 int outsize = set_message(outbuf,0,0,True);
2671 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2672 int close_err = 0;
2673 START_PROFILE(SMBsplclose);
2675 CHECK_FSP(fsp,conn);
2677 if (!CAN_PRINT(conn)) {
2678 END_PROFILE(SMBsplclose);
2679 return ERROR_DOS(ERRDOS,ERRnoaccess);
2682 DEBUG(3,("printclose fd=%d fnum=%d\n",
2683 fsp->fd,fsp->fnum));
2685 close_err = close_file(fsp,True);
2687 if(close_err != 0) {
2688 errno = close_err;
2689 END_PROFILE(SMBsplclose);
2690 return(UNIXERROR(ERRHRD,ERRgeneral));
2693 END_PROFILE(SMBsplclose);
2694 return(outsize);
2697 /****************************************************************************
2698 Reply to a printqueue.
2699 ****************************************************************************/
2701 int reply_printqueue(connection_struct *conn,
2702 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2704 int outsize = set_message(outbuf,2,3,True);
2705 int max_count = SVAL(inbuf,smb_vwv0);
2706 int start_index = SVAL(inbuf,smb_vwv1);
2707 START_PROFILE(SMBsplretq);
2709 /* we used to allow the client to get the cnum wrong, but that
2710 is really quite gross and only worked when there was only
2711 one printer - I think we should now only accept it if they
2712 get it right (tridge) */
2713 if (!CAN_PRINT(conn)) {
2714 END_PROFILE(SMBsplretq);
2715 return ERROR_DOS(ERRDOS,ERRnoaccess);
2718 SSVAL(outbuf,smb_vwv0,0);
2719 SSVAL(outbuf,smb_vwv1,0);
2720 SCVAL(smb_buf(outbuf),0,1);
2721 SSVAL(smb_buf(outbuf),1,0);
2723 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2724 start_index, max_count));
2727 print_queue_struct *queue = NULL;
2728 print_status_struct status;
2729 char *p = smb_buf(outbuf) + 3;
2730 int count = print_queue_status(SNUM(conn), &queue, &status);
2731 int num_to_get = ABS(max_count);
2732 int first = (max_count>0?start_index:start_index+max_count+1);
2733 int i;
2735 if (first >= count)
2736 num_to_get = 0;
2737 else
2738 num_to_get = MIN(num_to_get,count-first);
2741 for (i=first;i<first+num_to_get;i++) {
2742 put_dos_date2(p,0,queue[i].time);
2743 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2744 SSVAL(p,5, queue[i].job);
2745 SIVAL(p,7,queue[i].size);
2746 SCVAL(p,11,0);
2747 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2748 p += 28;
2751 if (count > 0) {
2752 outsize = set_message(outbuf,2,28*count+3,False);
2753 SSVAL(outbuf,smb_vwv0,count);
2754 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2755 SCVAL(smb_buf(outbuf),0,1);
2756 SSVAL(smb_buf(outbuf),1,28*count);
2759 SAFE_FREE(queue);
2761 DEBUG(3,("%d entries returned in queue\n",count));
2764 END_PROFILE(SMBsplretq);
2765 return(outsize);
2768 /****************************************************************************
2769 Reply to a printwrite.
2770 ****************************************************************************/
2772 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2774 int numtowrite;
2775 int outsize = set_message(outbuf,0,0,True);
2776 char *data;
2777 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2779 START_PROFILE(SMBsplwr);
2781 if (!CAN_PRINT(conn)) {
2782 END_PROFILE(SMBsplwr);
2783 return ERROR_DOS(ERRDOS,ERRnoaccess);
2786 CHECK_FSP(fsp,conn);
2787 CHECK_WRITE(fsp);
2789 numtowrite = SVAL(smb_buf(inbuf),1);
2790 data = smb_buf(inbuf) + 3;
2792 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2793 END_PROFILE(SMBsplwr);
2794 return(UNIXERROR(ERRHRD,ERRdiskfull));
2797 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2799 END_PROFILE(SMBsplwr);
2800 return(outsize);
2803 /****************************************************************************
2804 The guts of the mkdir command, split out so it may be called by the NT SMB
2805 code.
2806 ****************************************************************************/
2808 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2810 BOOL bad_path = False;
2811 SMB_STRUCT_STAT sbuf;
2812 int ret= -1;
2814 unix_convert(directory,conn,0,&bad_path,&sbuf);
2816 if (check_name(directory, conn))
2817 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2819 if (ret == -1) {
2820 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
2821 if (!NT_STATUS_IS_OK(nterr))
2822 return nterr;
2823 return map_nt_error_from_unix(errno);
2826 return NT_STATUS_OK;
2829 /****************************************************************************
2830 Reply to a mkdir.
2831 ****************************************************************************/
2833 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2835 pstring directory;
2836 int outsize;
2837 NTSTATUS status;
2838 START_PROFILE(SMBmkdir);
2840 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2842 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
2844 status = mkdir_internal(conn, directory);
2845 if (!NT_STATUS_IS_OK(status))
2846 return ERROR_NT(status);
2848 outsize = set_message(outbuf,0,0,True);
2850 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2852 END_PROFILE(SMBmkdir);
2853 return(outsize);
2856 /****************************************************************************
2857 Static function used by reply_rmdir to delete an entire directory
2858 tree recursively. Return False on ok, True on fail.
2859 ****************************************************************************/
2861 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2863 char *dname = NULL;
2864 BOOL ret = False;
2865 void *dirptr = OpenDir(conn, directory, False);
2867 if(dirptr == NULL)
2868 return True;
2870 while((dname = ReadDirName(dirptr))) {
2871 pstring fullname;
2872 SMB_STRUCT_STAT st;
2874 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2875 continue;
2877 /* Construct the full name. */
2878 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2879 errno = ENOMEM;
2880 ret = True;
2881 break;
2884 pstrcpy(fullname, directory);
2885 pstrcat(fullname, "/");
2886 pstrcat(fullname, dname);
2888 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
2889 ret = True;
2890 break;
2893 if(st.st_mode & S_IFDIR) {
2894 if(recursive_rmdir(conn, fullname)!=0) {
2895 ret = True;
2896 break;
2898 if(vfs_rmdir(conn,fullname) != 0) {
2899 ret = True;
2900 break;
2902 } else if(vfs_unlink(conn,fullname) != 0) {
2903 ret = True;
2904 break;
2907 CloseDir(dirptr);
2908 return ret;
2911 /****************************************************************************
2912 The internals of the rmdir code - called elsewhere.
2913 ****************************************************************************/
2915 BOOL rmdir_internals(connection_struct *conn, char *directory)
2917 BOOL ok;
2919 ok = (vfs_rmdir(conn,directory) == 0);
2920 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2922 * Check to see if the only thing in this directory are
2923 * vetoed files/directories. If so then delete them and
2924 * retry. If we fail to delete any of them (and we *don't*
2925 * do a recursive delete) then fail the rmdir.
2927 BOOL all_veto_files = True;
2928 char *dname;
2929 void *dirptr = OpenDir(conn, directory, False);
2931 if(dirptr != NULL) {
2932 int dirpos = TellDir(dirptr);
2933 while ((dname = ReadDirName(dirptr))) {
2934 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2935 continue;
2936 if(!IS_VETO_PATH(conn, dname)) {
2937 all_veto_files = False;
2938 break;
2942 if(all_veto_files) {
2943 SeekDir(dirptr,dirpos);
2944 while ((dname = ReadDirName(dirptr))) {
2945 pstring fullname;
2946 SMB_STRUCT_STAT st;
2948 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2949 continue;
2951 /* Construct the full name. */
2952 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2953 errno = ENOMEM;
2954 break;
2957 pstrcpy(fullname, directory);
2958 pstrcat(fullname, "/");
2959 pstrcat(fullname, dname);
2961 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
2962 break;
2963 if(st.st_mode & S_IFDIR) {
2964 if(lp_recursive_veto_delete(SNUM(conn))) {
2965 if(recursive_rmdir(conn, fullname) != 0)
2966 break;
2968 if(vfs_rmdir(conn,fullname) != 0)
2969 break;
2970 } else if(vfs_unlink(conn,fullname) != 0)
2971 break;
2973 CloseDir(dirptr);
2974 /* Retry the rmdir */
2975 ok = (vfs_rmdir(conn,directory) == 0);
2976 } else {
2977 CloseDir(dirptr);
2979 } else {
2980 errno = ENOTEMPTY;
2984 if (!ok)
2985 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
2987 return ok;
2990 /****************************************************************************
2991 Reply to a rmdir.
2992 ****************************************************************************/
2994 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2996 pstring directory;
2997 int outsize = 0;
2998 BOOL ok = False;
2999 BOOL bad_path = False;
3000 SMB_STRUCT_STAT sbuf;
3001 START_PROFILE(SMBrmdir);
3003 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
3005 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3007 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3009 if (check_name(directory,conn)) {
3010 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3011 ok = rmdir_internals(conn, directory);
3014 if (!ok) {
3015 set_bad_path_error(errno, bad_path);
3016 END_PROFILE(SMBrmdir);
3017 return(UNIXERROR(ERRDOS,ERRbadpath));
3020 outsize = set_message(outbuf,0,0,True);
3022 DEBUG( 3, ( "rmdir %s\n", directory ) );
3024 END_PROFILE(SMBrmdir);
3025 return(outsize);
3028 /*******************************************************************
3029 Resolve wildcards in a filename rename.
3030 ********************************************************************/
3032 static BOOL resolve_wildcards(char *name1,char *name2)
3034 fstring root1,root2;
3035 fstring ext1,ext2;
3036 char *p,*p2;
3038 name1 = strrchr_m(name1,'/');
3039 name2 = strrchr_m(name2,'/');
3041 if (!name1 || !name2)
3042 return(False);
3044 fstrcpy(root1,name1);
3045 fstrcpy(root2,name2);
3046 p = strrchr_m(root1,'.');
3047 if (p) {
3048 *p = 0;
3049 fstrcpy(ext1,p+1);
3050 } else {
3051 fstrcpy(ext1,"");
3053 p = strrchr_m(root2,'.');
3054 if (p) {
3055 *p = 0;
3056 fstrcpy(ext2,p+1);
3057 } else {
3058 fstrcpy(ext2,"");
3061 p = root1;
3062 p2 = root2;
3063 while (*p2) {
3064 if (*p2 == '?') {
3065 *p2 = *p;
3066 p2++;
3067 } else {
3068 p2++;
3070 if (*p)
3071 p++;
3074 p = ext1;
3075 p2 = ext2;
3076 while (*p2) {
3077 if (*p2 == '?') {
3078 *p2 = *p;
3079 p2++;
3080 } else {
3081 p2++;
3083 if (*p)
3084 p++;
3087 pstrcpy(name2,root2);
3088 if (ext2[0]) {
3089 pstrcat(name2,".");
3090 pstrcat(name2,ext2);
3093 return(True);
3096 /****************************************************************************
3097 The guts of the rename command, split out so it may be called by the NT SMB
3098 code.
3099 ****************************************************************************/
3101 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3103 pstring directory;
3104 pstring mask;
3105 pstring newname_last_component;
3106 char *p;
3107 BOOL has_wild;
3108 BOOL bad_path1 = False;
3109 BOOL bad_path2 = False;
3110 int count=0;
3111 NTSTATUS error = NT_STATUS_OK;
3112 BOOL rc = True;
3113 SMB_STRUCT_STAT sbuf1, sbuf2;
3115 *directory = *mask = 0;
3117 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3118 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3121 * Split the old name into directory and last component
3122 * strings. Note that unix_convert may have stripped off a
3123 * leading ./ from both name and newname if the rename is
3124 * at the root of the share. We need to make sure either both
3125 * name and newname contain a / character or neither of them do
3126 * as this is checked in resolve_wildcards().
3129 p = strrchr_m(name,'/');
3130 if (!p) {
3131 pstrcpy(directory,".");
3132 pstrcpy(mask,name);
3133 } else {
3134 *p = 0;
3135 pstrcpy(directory,name);
3136 pstrcpy(mask,p+1);
3137 *p = '/'; /* Replace needed for exceptional test below. */
3141 * We should only check the mangled cache
3142 * here if unix_convert failed. This means
3143 * that the path in 'mask' doesn't exist
3144 * on the file system and so we need to look
3145 * for a possible mangle. This patch from
3146 * Tine Smukavec <valentin.smukavec@hermes.si>.
3149 if (!rc && mangle_is_mangled(mask))
3150 mangle_check_cache( mask );
3152 has_wild = ms_has_wild(mask);
3154 if (!has_wild) {
3156 * No wildcards - just process the one file.
3158 BOOL is_short_name = mangle_is_8_3(name, True);
3160 /* Add a terminating '/' to the directory name. */
3161 pstrcat(directory,"/");
3162 pstrcat(directory,mask);
3164 /* Ensure newname contains a '/' also */
3165 if(strrchr_m(newname,'/') == 0) {
3166 pstring tmpstr;
3168 pstrcpy(tmpstr, "./");
3169 pstrcat(tmpstr, newname);
3170 pstrcpy(newname, tmpstr);
3173 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3174 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3175 case_sensitive, case_preserve, short_case_preserve, directory,
3176 newname, newname_last_component, is_short_name));
3179 * Check for special case with case preserving and not
3180 * case sensitive, if directory and newname are identical,
3181 * and the old last component differs from the original
3182 * last component only by case, then we should allow
3183 * the rename (user is trying to change the case of the
3184 * filename).
3186 if((case_sensitive == False) &&
3187 (((case_preserve == True) &&
3188 (is_short_name == False)) ||
3189 ((short_case_preserve == True) &&
3190 (is_short_name == True))) &&
3191 strcsequal(directory, newname)) {
3192 pstring newname_modified_last_component;
3195 * Get the last component of the modified name.
3196 * Note that we guarantee that newname contains a '/'
3197 * character above.
3199 p = strrchr_m(newname,'/');
3200 pstrcpy(newname_modified_last_component,p+1);
3202 if(strcsequal(newname_modified_last_component,
3203 newname_last_component) == False) {
3205 * Replace the modified last component with
3206 * the original.
3208 pstrcpy(p+1, newname_last_component);
3212 resolve_wildcards(directory,newname);
3215 * The source object must exist.
3218 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3219 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3220 directory,newname));
3222 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3224 * Must return different errors depending on whether the parent
3225 * directory existed or not.
3228 p = strrchr_m(directory, '/');
3229 if (!p)
3230 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3231 *p = '\0';
3232 if (vfs_object_exist(conn, directory, NULL))
3233 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3234 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3236 error = map_nt_error_from_unix(errno);
3237 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3238 nt_errstr(error), directory,newname));
3240 return error;
3243 error = can_rename(directory,conn,&sbuf1);
3245 if (!NT_STATUS_IS_OK(error)) {
3246 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3247 nt_errstr(error), directory,newname));
3248 return error;
3252 * If the src and dest names are identical - including case,
3253 * don't do the rename, just return success.
3256 if (strcsequal(directory, newname)) {
3257 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3258 return NT_STATUS_OK;
3261 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3262 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3263 directory,newname));
3264 return NT_STATUS_OBJECT_NAME_COLLISION;
3267 if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
3268 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3269 directory,newname));
3270 return NT_STATUS_OK;
3273 if (errno == ENOTDIR || errno == EISDIR)
3274 error = NT_STATUS_OBJECT_NAME_COLLISION;
3275 else
3276 error = map_nt_error_from_unix(errno);
3278 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3279 nt_errstr(error), directory,newname));
3281 return error;
3282 } else {
3284 * Wildcards - process each file that matches.
3286 void *dirptr = NULL;
3287 char *dname;
3288 pstring destname;
3290 if (check_name(directory,conn))
3291 dirptr = OpenDir(conn, directory, True);
3293 if (dirptr) {
3294 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3296 if (strequal(mask,"????????.???"))
3297 pstrcpy(mask,"*");
3299 while ((dname = ReadDirName(dirptr))) {
3300 pstring fname;
3302 pstrcpy(fname,dname);
3304 if(!mask_match(fname, mask, case_sensitive))
3305 continue;
3307 error = NT_STATUS_ACCESS_DENIED;
3308 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3309 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3310 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3311 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3312 continue;
3314 error = can_rename(fname,conn,&sbuf1);
3315 if (!NT_STATUS_IS_OK(error)) {
3316 DEBUG(6,("rename %s refused\n", fname));
3317 continue;
3319 pstrcpy(destname,newname);
3321 if (!resolve_wildcards(fname,destname)) {
3322 DEBUG(6,("resolve_wildcards %s %s failed\n",
3323 fname, destname));
3324 continue;
3327 if (!replace_if_exists &&
3328 vfs_file_exist(conn,destname, NULL)) {
3329 DEBUG(6,("file_exist %s\n", destname));
3330 error = NT_STATUS_OBJECT_NAME_COLLISION;
3331 continue;
3334 if (!conn->vfs_ops.rename(conn,fname,destname))
3335 count++;
3336 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3338 CloseDir(dirptr);
3342 if (count == 0 && NT_STATUS_IS_OK(error)) {
3343 error = map_nt_error_from_unix(errno);
3346 return error;
3349 /****************************************************************************
3350 Reply to a mv.
3351 ****************************************************************************/
3353 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3354 int dum_buffsize)
3356 int outsize = 0;
3357 pstring name;
3358 pstring newname;
3359 char *p;
3360 NTSTATUS status;
3362 START_PROFILE(SMBmv);
3364 p = smb_buf(inbuf) + 1;
3365 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3366 p++;
3367 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3369 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3370 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3372 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3374 status = rename_internals(conn, name, newname, False);
3375 if (!NT_STATUS_IS_OK(status)) {
3376 return ERROR_NT(status);
3380 * Win2k needs a changenotify request response before it will
3381 * update after a rename..
3383 process_pending_change_notify_queue((time_t)0);
3384 outsize = set_message(outbuf,0,0,True);
3386 END_PROFILE(SMBmv);
3387 return(outsize);
3390 /*******************************************************************
3391 Copy a file as part of a reply_copy.
3392 ******************************************************************/
3394 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3395 int count,BOOL target_is_directory, int *err_ret)
3397 int Access,action;
3398 SMB_STRUCT_STAT src_sbuf, sbuf2;
3399 SMB_OFF_T ret=-1;
3400 files_struct *fsp1,*fsp2;
3401 pstring dest;
3403 *err_ret = 0;
3405 pstrcpy(dest,dest1);
3406 if (target_is_directory) {
3407 char *p = strrchr_m(src,'/');
3408 if (p)
3409 p++;
3410 else
3411 p = src;
3412 pstrcat(dest,"/");
3413 pstrcat(dest,p);
3416 if (!vfs_file_exist(conn,src,&src_sbuf))
3417 return(False);
3419 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3420 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3422 if (!fsp1)
3423 return(False);
3425 if (!target_is_directory && count)
3426 ofun = FILE_EXISTS_OPEN;
3428 if (vfs_stat(conn,dest,&sbuf2) == -1)
3429 ZERO_STRUCTP(&sbuf2);
3431 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3432 ofun,src_sbuf.st_mode,0,&Access,&action);
3434 if (!fsp2) {
3435 close_file(fsp1,False);
3436 return(False);
3439 if ((ofun&3) == 1) {
3440 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3441 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3443 * Stop the copy from occurring.
3445 ret = -1;
3446 src_sbuf.st_size = 0;
3450 if (src_sbuf.st_size)
3451 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3453 close_file(fsp1,False);
3455 /* Ensure the modtime is set correctly on the destination file. */
3456 fsp2->pending_modtime = src_sbuf.st_mtime;
3459 * As we are opening fsp1 read-only we only expect
3460 * an error on close on fsp2 if we are out of space.
3461 * Thus we don't look at the error return from the
3462 * close of fsp1.
3464 *err_ret = close_file(fsp2,False);
3466 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3469 /****************************************************************************
3470 Reply to a file copy.
3471 ****************************************************************************/
3473 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3475 int outsize = 0;
3476 pstring name;
3477 pstring directory;
3478 pstring mask,newname;
3479 char *p;
3480 int count=0;
3481 int error = ERRnoaccess;
3482 int err = 0;
3483 BOOL has_wild;
3484 BOOL exists=False;
3485 int tid2 = SVAL(inbuf,smb_vwv0);
3486 int ofun = SVAL(inbuf,smb_vwv1);
3487 int flags = SVAL(inbuf,smb_vwv2);
3488 BOOL target_is_directory=False;
3489 BOOL bad_path1 = False;
3490 BOOL bad_path2 = False;
3491 BOOL rc = True;
3492 SMB_STRUCT_STAT sbuf1, sbuf2;
3494 START_PROFILE(SMBcopy);
3496 *directory = *mask = 0;
3498 p = smb_buf(inbuf);
3499 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3500 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3502 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3504 if (tid2 != conn->cnum) {
3505 /* can't currently handle inter share copies XXXX */
3506 DEBUG(3,("Rejecting inter-share copy\n"));
3507 END_PROFILE(SMBcopy);
3508 return ERROR_DOS(ERRSRV,ERRinvdevice);
3511 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3512 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3514 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3515 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3517 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3519 if ((flags&1) && target_is_directory) {
3520 END_PROFILE(SMBcopy);
3521 return ERROR_DOS(ERRDOS,ERRbadfile);
3524 if ((flags&2) && !target_is_directory) {
3525 END_PROFILE(SMBcopy);
3526 return ERROR_DOS(ERRDOS,ERRbadpath);
3529 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3530 /* wants a tree copy! XXXX */
3531 DEBUG(3,("Rejecting tree copy\n"));
3532 END_PROFILE(SMBcopy);
3533 return ERROR_DOS(ERRSRV,ERRerror);
3536 p = strrchr_m(name,'/');
3537 if (!p) {
3538 pstrcpy(directory,"./");
3539 pstrcpy(mask,name);
3540 } else {
3541 *p = 0;
3542 pstrcpy(directory,name);
3543 pstrcpy(mask,p+1);
3547 * We should only check the mangled cache
3548 * here if unix_convert failed. This means
3549 * that the path in 'mask' doesn't exist
3550 * on the file system and so we need to look
3551 * for a possible mangle. This patch from
3552 * Tine Smukavec <valentin.smukavec@hermes.si>.
3555 if (!rc && mangle_is_mangled(mask))
3556 mangle_check_cache( mask );
3558 has_wild = ms_has_wild(mask);
3560 if (!has_wild) {
3561 pstrcat(directory,"/");
3562 pstrcat(directory,mask);
3563 if (resolve_wildcards(directory,newname) &&
3564 copy_file(directory,newname,conn,ofun, count,target_is_directory,&err))
3565 count++;
3566 if(!count && err) {
3567 errno = err;
3568 END_PROFILE(SMBcopy);
3569 return(UNIXERROR(ERRHRD,ERRgeneral));
3571 if (!count) {
3572 exists = vfs_file_exist(conn,directory,NULL);
3574 } else {
3575 void *dirptr = NULL;
3576 char *dname;
3577 pstring destname;
3579 if (check_name(directory,conn))
3580 dirptr = OpenDir(conn, directory, True);
3582 if (dirptr) {
3583 error = ERRbadfile;
3585 if (strequal(mask,"????????.???"))
3586 pstrcpy(mask,"*");
3588 while ((dname = ReadDirName(dirptr))) {
3589 pstring fname;
3590 pstrcpy(fname,dname);
3592 if(!mask_match(fname, mask, case_sensitive))
3593 continue;
3595 error = ERRnoaccess;
3596 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3597 pstrcpy(destname,newname);
3598 if (resolve_wildcards(fname,destname) &&
3599 copy_file(fname,destname,conn,ofun,
3600 count,target_is_directory,&err))
3601 count++;
3602 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3604 CloseDir(dirptr);
3608 if (count == 0) {
3609 if(err) {
3610 /* Error on close... */
3611 errno = err;
3612 END_PROFILE(SMBcopy);
3613 return(UNIXERROR(ERRHRD,ERRgeneral));
3616 if (exists) {
3617 END_PROFILE(SMBcopy);
3618 return ERROR_DOS(ERRDOS,error);
3619 } else {
3620 if((errno == ENOENT) && (bad_path1 || bad_path2)) {
3621 unix_ERR_class = ERRDOS;
3622 unix_ERR_code = ERRbadpath;
3624 END_PROFILE(SMBcopy);
3625 return(UNIXERROR(ERRDOS,error));
3629 outsize = set_message(outbuf,1,0,True);
3630 SSVAL(outbuf,smb_vwv0,count);
3632 END_PROFILE(SMBcopy);
3633 return(outsize);
3636 /****************************************************************************
3637 Reply to a setdir.
3638 ****************************************************************************/
3640 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3642 int snum;
3643 int outsize = 0;
3644 BOOL ok = False;
3645 pstring newdir;
3647 START_PROFILE(pathworks_setdir);
3649 snum = SNUM(conn);
3650 if (!CAN_SETDIR(snum)) {
3651 END_PROFILE(pathworks_setdir);
3652 return ERROR_DOS(ERRDOS,ERRnoaccess);
3655 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3657 if (strlen(newdir) == 0) {
3658 ok = True;
3659 } else {
3660 ok = vfs_directory_exist(conn,newdir,NULL);
3661 if (ok)
3662 string_set(&conn->connectpath,newdir);
3665 if (!ok) {
3666 END_PROFILE(pathworks_setdir);
3667 return ERROR_DOS(ERRDOS,ERRbadpath);
3670 outsize = set_message(outbuf,0,0,True);
3671 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3673 DEBUG(3,("setdir %s\n", newdir));
3675 END_PROFILE(pathworks_setdir);
3676 return(outsize);
3679 /****************************************************************************
3680 Get a lock pid, dealing with large count requests.
3681 ****************************************************************************/
3683 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3685 if(!large_file_format)
3686 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3687 else
3688 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3691 /****************************************************************************
3692 Get a lock count, dealing with large count requests.
3693 ****************************************************************************/
3695 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3697 SMB_BIG_UINT count = 0;
3699 if(!large_file_format) {
3700 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3701 } else {
3703 #if defined(HAVE_LONGLONG)
3704 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3705 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3706 #else /* HAVE_LONGLONG */
3709 * NT4.x seems to be broken in that it sends large file (64 bit)
3710 * lockingX calls even if the CAP_LARGE_FILES was *not*
3711 * negotiated. For boxes without large unsigned ints truncate the
3712 * lock count by dropping the top 32 bits.
3715 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3716 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3717 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3718 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3719 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3722 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3723 #endif /* HAVE_LONGLONG */
3726 return count;
3729 #if !defined(HAVE_LONGLONG)
3730 /****************************************************************************
3731 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3732 ****************************************************************************/
3734 static uint32 map_lock_offset(uint32 high, uint32 low)
3736 unsigned int i;
3737 uint32 mask = 0;
3738 uint32 highcopy = high;
3741 * Try and find out how many significant bits there are in high.
3744 for(i = 0; highcopy; i++)
3745 highcopy >>= 1;
3748 * We use 31 bits not 32 here as POSIX
3749 * lock offsets may not be negative.
3752 mask = (~0) << (31 - i);
3754 if(low & mask)
3755 return 0; /* Fail. */
3757 high <<= (31 - i);
3759 return (high|low);
3761 #endif /* !defined(HAVE_LONGLONG) */
3763 /****************************************************************************
3764 Get a lock offset, dealing with large offset requests.
3765 ****************************************************************************/
3767 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3769 SMB_BIG_UINT offset = 0;
3771 *err = False;
3773 if(!large_file_format) {
3774 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3775 } else {
3777 #if defined(HAVE_LONGLONG)
3778 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3779 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3780 #else /* HAVE_LONGLONG */
3783 * NT4.x seems to be broken in that it sends large file (64 bit)
3784 * lockingX calls even if the CAP_LARGE_FILES was *not*
3785 * negotiated. For boxes without large unsigned ints mangle the
3786 * lock offset by mapping the top 32 bits onto the lower 32.
3789 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3790 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3791 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3792 uint32 new_low = 0;
3794 if((new_low = map_lock_offset(high, low)) == 0) {
3795 *err = True;
3796 return (SMB_BIG_UINT)-1;
3799 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3800 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3801 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3802 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3805 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3806 #endif /* HAVE_LONGLONG */
3809 return offset;
3812 /****************************************************************************
3813 Reply to a lockingX request.
3814 ****************************************************************************/
3816 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3818 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3819 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3820 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3821 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3822 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3823 SMB_BIG_UINT count = 0, offset = 0;
3824 uint16 lock_pid;
3825 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3826 int i;
3827 char *data;
3828 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3829 BOOL err;
3830 NTSTATUS status;
3832 START_PROFILE(SMBlockingX);
3834 CHECK_FSP(fsp,conn);
3836 data = smb_buf(inbuf);
3838 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3839 /* we don't support these - and CANCEL_LOCK makes w2k
3840 and XP reboot so I don't really want to be
3841 compatible! (tridge) */
3842 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3845 /* Check if this is an oplock break on a file
3846 we have granted an oplock on.
3848 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3849 /* Client can insist on breaking to none. */
3850 BOOL break_to_none = (oplocklevel == 0);
3852 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3853 (unsigned int)oplocklevel, fsp->fnum ));
3856 * Make sure we have granted an exclusive or batch oplock on this file.
3859 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3860 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3861 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3863 /* if this is a pure oplock break request then don't send a reply */
3864 if (num_locks == 0 && num_ulocks == 0) {
3865 END_PROFILE(SMBlockingX);
3866 return -1;
3867 } else {
3868 END_PROFILE(SMBlockingX);
3869 return ERROR_DOS(ERRDOS,ERRlock);
3873 if (remove_oplock(fsp, break_to_none) == False) {
3874 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3875 fsp->fsp_name ));
3878 /* if this is a pure oplock break request then don't send a reply */
3879 if (num_locks == 0 && num_ulocks == 0) {
3880 /* Sanity check - ensure a pure oplock break is not a
3881 chained request. */
3882 if(CVAL(inbuf,smb_vwv0) != 0xff)
3883 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3884 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3885 END_PROFILE(SMBlockingX);
3886 return -1;
3891 * We do this check *after* we have checked this is not a oplock break
3892 * response message. JRA.
3895 release_level_2_oplocks_on_change(fsp);
3897 /* Data now points at the beginning of the list
3898 of smb_unlkrng structs */
3899 for(i = 0; i < (int)num_ulocks; i++) {
3900 lock_pid = get_lock_pid( data, i, large_file_format);
3901 count = get_lock_count( data, i, large_file_format);
3902 offset = get_lock_offset( data, i, large_file_format, &err);
3905 * There is no error code marked "stupid client bug".... :-).
3907 if(err) {
3908 END_PROFILE(SMBlockingX);
3909 return ERROR_DOS(ERRDOS,ERRnoaccess);
3912 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3913 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3915 status = do_unlock(fsp,conn,lock_pid,count,offset);
3916 if (NT_STATUS_V(status)) {
3917 END_PROFILE(SMBlockingX);
3918 return ERROR_NT(status);
3922 /* Setup the timeout in seconds. */
3924 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
3926 /* Now do any requested locks */
3927 data += ((large_file_format ? 20 : 10)*num_ulocks);
3929 /* Data now points at the beginning of the list
3930 of smb_lkrng structs */
3932 for(i = 0; i < (int)num_locks; i++) {
3933 lock_pid = get_lock_pid( data, i, large_file_format);
3934 count = get_lock_count( data, i, large_file_format);
3935 offset = get_lock_offset( data, i, large_file_format, &err);
3938 * There is no error code marked "stupid client bug".... :-).
3940 if(err) {
3941 END_PROFILE(SMBlockingX);
3942 return ERROR_DOS(ERRDOS,ERRnoaccess);
3945 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3946 (double)offset, (double)count, (unsigned int)lock_pid,
3947 fsp->fsp_name, (int)lock_timeout ));
3949 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
3950 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3951 if (NT_STATUS_V(status)) {
3952 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
3954 * A blocking lock was requested. Package up
3955 * this smb into a queued request and push it
3956 * onto the blocking lock queue.
3958 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
3959 END_PROFILE(SMBlockingX);
3960 return -1;
3963 break;
3967 /* If any of the above locks failed, then we must unlock
3968 all of the previous locks (X/Open spec). */
3969 if (i != num_locks && num_locks != 0) {
3971 * Ensure we don't do a remove on the lock that just failed,
3972 * as under POSIX rules, if we have a lock already there, we
3973 * will delete it (and we shouldn't) .....
3975 for(i--; i >= 0; i--) {
3976 lock_pid = get_lock_pid( data, i, large_file_format);
3977 count = get_lock_count( data, i, large_file_format);
3978 offset = get_lock_offset( data, i, large_file_format, &err);
3981 * There is no error code marked "stupid client bug".... :-).
3983 if(err) {
3984 END_PROFILE(SMBlockingX);
3985 return ERROR_DOS(ERRDOS,ERRnoaccess);
3988 do_unlock(fsp,conn,lock_pid,count,offset);
3990 END_PROFILE(SMBlockingX);
3991 return ERROR_NT(status);
3994 set_message(outbuf,2,0,True);
3996 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
3997 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
3999 END_PROFILE(SMBlockingX);
4000 return chain_reply(inbuf,outbuf,length,bufsize);
4003 /****************************************************************************
4004 Reply to a SMBreadbmpx (read block multiplex) request.
4005 ****************************************************************************/
4007 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4009 ssize_t nread = -1;
4010 ssize_t total_read;
4011 char *data;
4012 SMB_OFF_T startpos;
4013 int outsize;
4014 size_t maxcount;
4015 int max_per_packet;
4016 size_t tcount;
4017 int pad;
4018 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4019 START_PROFILE(SMBreadBmpx);
4021 /* this function doesn't seem to work - disable by default */
4022 if (!lp_readbmpx()) {
4023 END_PROFILE(SMBreadBmpx);
4024 return ERROR_DOS(ERRSRV,ERRuseSTD);
4027 outsize = set_message(outbuf,8,0,True);
4029 CHECK_FSP(fsp,conn);
4030 CHECK_READ(fsp);
4032 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv1);
4033 maxcount = SVAL(inbuf,smb_vwv3);
4035 data = smb_buf(outbuf);
4036 pad = ((long)data)%4;
4037 if (pad)
4038 pad = 4 - pad;
4039 data += pad;
4041 max_per_packet = bufsize-(outsize+pad);
4042 tcount = maxcount;
4043 total_read = 0;
4045 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4046 END_PROFILE(SMBreadBmpx);
4047 return ERROR_DOS(ERRDOS,ERRlock);
4050 do {
4051 size_t N = MIN(max_per_packet,tcount-total_read);
4053 nread = read_file(fsp,data,startpos,N);
4055 if (nread <= 0)
4056 nread = 0;
4058 if (nread < (ssize_t)N)
4059 tcount = total_read + nread;
4061 set_message(outbuf,8,nread,False);
4062 SIVAL(outbuf,smb_vwv0,startpos);
4063 SSVAL(outbuf,smb_vwv2,tcount);
4064 SSVAL(outbuf,smb_vwv6,nread);
4065 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4067 if (!send_smb(smbd_server_fd(),outbuf))
4068 exit_server("reply_readbmpx: send_smb failed.");
4070 total_read += nread;
4071 startpos += nread;
4072 } while (total_read < (ssize_t)tcount);
4074 END_PROFILE(SMBreadBmpx);
4075 return(-1);
4078 /****************************************************************************
4079 Reply to a SMBsetattrE.
4080 ****************************************************************************/
4082 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4084 struct utimbuf unix_times;
4085 int outsize = 0;
4086 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4087 START_PROFILE(SMBsetattrE);
4089 outsize = set_message(outbuf,0,0,True);
4091 if(!fsp || (fsp->conn != conn)) {
4092 END_PROFILE(SMBgetattrE);
4093 return ERROR_DOS(ERRDOS,ERRbadfid);
4097 * Convert the DOS times into unix times. Ignore create
4098 * time as UNIX can't set this.
4101 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4102 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4105 * Patch from Ray Frush <frush@engr.colostate.edu>
4106 * Sometimes times are sent as zero - ignore them.
4109 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4110 /* Ignore request */
4111 if( DEBUGLVL( 3 ) ) {
4112 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4113 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4115 END_PROFILE(SMBsetattrE);
4116 return(outsize);
4117 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4118 /* set modify time = to access time if modify time was 0 */
4119 unix_times.modtime = unix_times.actime;
4122 /* Set the date on this file */
4123 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4124 END_PROFILE(SMBsetattrE);
4125 return ERROR_DOS(ERRDOS,ERRnoaccess);
4128 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4129 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4131 END_PROFILE(SMBsetattrE);
4132 return(outsize);
4136 /* Back from the dead for OS/2..... JRA. */
4138 /****************************************************************************
4139 Reply to a SMBwritebmpx (write block multiplex primary) request.
4140 ****************************************************************************/
4142 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4144 size_t numtowrite;
4145 ssize_t nwritten = -1;
4146 int outsize = 0;
4147 SMB_OFF_T startpos;
4148 size_t tcount;
4149 BOOL write_through;
4150 int smb_doff;
4151 char *data;
4152 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4153 START_PROFILE(SMBwriteBmpx);
4155 CHECK_FSP(fsp,conn);
4156 CHECK_WRITE(fsp);
4157 CHECK_ERROR(fsp);
4159 tcount = SVAL(inbuf,smb_vwv1);
4160 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
4161 write_through = BITSETW(inbuf+smb_vwv7,0);
4162 numtowrite = SVAL(inbuf,smb_vwv10);
4163 smb_doff = SVAL(inbuf,smb_vwv11);
4165 data = smb_base(inbuf) + smb_doff;
4167 /* If this fails we need to send an SMBwriteC response,
4168 not an SMBwritebmpx - set this up now so we don't forget */
4169 SCVAL(outbuf,smb_com,SMBwritec);
4171 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4172 END_PROFILE(SMBwriteBmpx);
4173 return(ERROR_DOS(ERRDOS,ERRlock));
4176 nwritten = write_file(fsp,data,startpos,numtowrite);
4178 if(lp_syncalways(SNUM(conn)) || write_through)
4179 sync_file(conn,fsp);
4181 if(nwritten < (ssize_t)numtowrite) {
4182 END_PROFILE(SMBwriteBmpx);
4183 return(UNIXERROR(ERRHRD,ERRdiskfull));
4186 /* If the maximum to be written to this file
4187 is greater than what we just wrote then set
4188 up a secondary struct to be attached to this
4189 fd, we will use this to cache error messages etc. */
4191 if((ssize_t)tcount > nwritten) {
4192 write_bmpx_struct *wbms;
4193 if(fsp->wbmpx_ptr != NULL)
4194 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4195 else
4196 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4197 if(!wbms) {
4198 DEBUG(0,("Out of memory in reply_readmpx\n"));
4199 END_PROFILE(SMBwriteBmpx);
4200 return(ERROR_DOS(ERRSRV,ERRnoresource));
4202 wbms->wr_mode = write_through;
4203 wbms->wr_discard = False; /* No errors yet */
4204 wbms->wr_total_written = nwritten;
4205 wbms->wr_errclass = 0;
4206 wbms->wr_error = 0;
4207 fsp->wbmpx_ptr = wbms;
4210 /* We are returning successfully, set the message type back to
4211 SMBwritebmpx */
4212 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4214 outsize = set_message(outbuf,1,0,True);
4216 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4218 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4219 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4221 if (write_through && tcount==nwritten) {
4222 /* We need to send both a primary and a secondary response */
4223 smb_setlen(outbuf,outsize - 4);
4224 if (!send_smb(smbd_server_fd(),outbuf))
4225 exit_server("reply_writebmpx: send_smb failed.");
4227 /* Now the secondary */
4228 outsize = set_message(outbuf,1,0,True);
4229 SCVAL(outbuf,smb_com,SMBwritec);
4230 SSVAL(outbuf,smb_vwv0,nwritten);
4233 END_PROFILE(SMBwriteBmpx);
4234 return(outsize);
4237 /****************************************************************************
4238 Reply to a SMBwritebs (write block multiplex secondary) request.
4239 ****************************************************************************/
4241 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4243 size_t numtowrite;
4244 ssize_t nwritten = -1;
4245 int outsize = 0;
4246 SMB_OFF_T startpos;
4247 size_t tcount;
4248 BOOL write_through;
4249 int smb_doff;
4250 char *data;
4251 write_bmpx_struct *wbms;
4252 BOOL send_response = False;
4253 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4254 START_PROFILE(SMBwriteBs);
4256 CHECK_FSP(fsp,conn);
4257 CHECK_WRITE(fsp);
4259 tcount = SVAL(inbuf,smb_vwv1);
4260 startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
4261 numtowrite = SVAL(inbuf,smb_vwv6);
4262 smb_doff = SVAL(inbuf,smb_vwv7);
4264 data = smb_base(inbuf) + smb_doff;
4266 /* We need to send an SMBwriteC response, not an SMBwritebs */
4267 SCVAL(outbuf,smb_com,SMBwritec);
4269 /* This fd should have an auxiliary struct attached,
4270 check that it does */
4271 wbms = fsp->wbmpx_ptr;
4272 if(!wbms) {
4273 END_PROFILE(SMBwriteBs);
4274 return(-1);
4277 /* If write through is set we can return errors, else we must cache them */
4278 write_through = wbms->wr_mode;
4280 /* Check for an earlier error */
4281 if(wbms->wr_discard) {
4282 END_PROFILE(SMBwriteBs);
4283 return -1; /* Just discard the packet */
4286 nwritten = write_file(fsp,data,startpos,numtowrite);
4288 if(lp_syncalways(SNUM(conn)) || write_through)
4289 sync_file(conn,fsp);
4291 if (nwritten < (ssize_t)numtowrite) {
4292 if(write_through) {
4293 /* We are returning an error - we can delete the aux struct */
4294 if (wbms)
4295 free((char *)wbms);
4296 fsp->wbmpx_ptr = NULL;
4297 END_PROFILE(SMBwriteBs);
4298 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4300 END_PROFILE(SMBwriteBs);
4301 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4304 /* Increment the total written, if this matches tcount
4305 we can discard the auxiliary struct (hurrah !) and return a writeC */
4306 wbms->wr_total_written += nwritten;
4307 if(wbms->wr_total_written >= tcount) {
4308 if (write_through) {
4309 outsize = set_message(outbuf,1,0,True);
4310 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4311 send_response = True;
4314 free((char *)wbms);
4315 fsp->wbmpx_ptr = NULL;
4318 if(send_response) {
4319 END_PROFILE(SMBwriteBs);
4320 return(outsize);
4323 END_PROFILE(SMBwriteBs);
4324 return(-1);
4327 /****************************************************************************
4328 Reply to a SMBgetattrE.
4329 ****************************************************************************/
4331 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4333 SMB_STRUCT_STAT sbuf;
4334 int outsize = 0;
4335 int mode;
4336 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4337 START_PROFILE(SMBgetattrE);
4339 outsize = set_message(outbuf,11,0,True);
4341 if(!fsp || (fsp->conn != conn)) {
4342 END_PROFILE(SMBgetattrE);
4343 return ERROR_DOS(ERRDOS,ERRbadfid);
4346 /* Do an fstat on this file */
4347 if(fsp_stat(fsp, &sbuf)) {
4348 END_PROFILE(SMBgetattrE);
4349 return(UNIXERROR(ERRDOS,ERRnoaccess));
4352 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4355 * Convert the times into dos times. Set create
4356 * date to be last modify date as UNIX doesn't save
4357 * this.
4360 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4361 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4362 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4364 if (mode & aDIR) {
4365 SIVAL(outbuf,smb_vwv6,0);
4366 SIVAL(outbuf,smb_vwv8,0);
4367 } else {
4368 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4369 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4371 SSVAL(outbuf,smb_vwv10, mode);
4373 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4375 END_PROFILE(SMBgetattrE);
4376 return(outsize);