must add one to the extra_data size to transfer the 0 string terminator.
[Samba/gebeck_regimport.git] / source3 / smbd / reply.c
bloba881e135c08c1cecb4ae19f73a66e982984bed72
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 pstring global_myname;
37 extern int global_oplock_break;
38 unsigned int smb_echo_count = 0;
40 extern BOOL global_encrypted_passwords_negotiated;
42 /****************************************************************************
43 Reply to an special message.
44 ****************************************************************************/
46 int reply_special(char *inbuf,char *outbuf)
48 int outsize = 4;
49 int msg_type = CVAL(inbuf,0);
50 int msg_flags = CVAL(inbuf,1);
51 pstring name1,name2;
53 int len;
54 char name_type = 0;
56 static BOOL already_got_session = False;
58 *name1 = *name2 = 0;
60 memset(outbuf,'\0',smb_size);
62 smb_setlen(outbuf,0);
64 switch (msg_type) {
65 case 0x81: /* session request */
67 if (already_got_session) {
68 exit_server("multiple session request not permitted");
71 SCVAL(outbuf,0,0x82);
72 SCVAL(outbuf,3,0);
73 if (name_len(inbuf+4) > 50 ||
74 name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
75 DEBUG(0,("Invalid name length in session request\n"));
76 return(0);
78 name_extract(inbuf,4,name1);
79 name_extract(inbuf,4 + name_len(inbuf + 4),name2);
80 DEBUG(2,("netbios connect: name1=%s name2=%s\n",
81 name1,name2));
83 name1[15] = 0;
85 len = strlen(name2);
86 if (len == 16) {
87 name_type = name2[15];
88 name2[15] = 0;
91 set_local_machine_name(name1);
92 set_remote_machine_name(name2);
94 DEBUG(2,("netbios connect: local=%s remote=%s\n",
95 get_local_machine_name(), get_remote_machine_name() ));
97 if (name_type == 'R') {
98 /* We are being asked for a pathworks session ---
99 no thanks! */
100 SCVAL(outbuf, 0,0x83);
101 break;
104 /* only add the client's machine name to the list
105 of possibly valid usernames if we are operating
106 in share mode security */
107 if (lp_security() == SEC_SHARE) {
108 add_session_user(get_remote_machine_name());
111 reload_services(True);
112 reopen_logs();
114 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
116 already_got_session = True;
117 break;
119 case 0x89: /* session keepalive request
120 (some old clients produce this?) */
121 SCVAL(outbuf,0,SMBkeepalive);
122 SCVAL(outbuf,3,0);
123 break;
125 case 0x82: /* positive session response */
126 case 0x83: /* negative session response */
127 case 0x84: /* retarget session response */
128 DEBUG(0,("Unexpected session response\n"));
129 break;
131 case SMBkeepalive: /* session keepalive */
132 default:
133 return(0);
136 DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
137 msg_type, msg_flags));
139 return(outsize);
142 /****************************************************************************
143 Reply to a tcon.
144 ****************************************************************************/
146 int reply_tcon(connection_struct *conn,
147 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
149 const char *service;
150 pstring service_buf;
151 pstring password;
152 pstring dev;
153 int outsize = 0;
154 uint16 vuid = SVAL(inbuf,smb_uid);
155 int pwlen=0;
156 NTSTATUS nt_status;
157 char *p;
158 DATA_BLOB password_blob;
160 START_PROFILE(SMBtcon);
162 *service_buf = *password = *dev = 0;
164 p = smb_buf(inbuf)+1;
165 p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service), STR_TERMINATE) + 1;
166 pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
167 p += pwlen;
168 p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
170 p = strrchr_m(service_buf,'\\');
171 if (p) {
172 service = p+1;
173 } else {
174 service = service_buf;
177 password_blob = data_blob(password, pwlen+1);
179 conn = make_connection(service,password_blob,dev,vuid,&nt_status);
181 data_blob_clear_free(&password_blob);
183 if (!conn) {
184 END_PROFILE(SMBtcon);
185 return ERROR_NT(nt_status);
188 outsize = set_message(outbuf,2,0,True);
189 SSVAL(outbuf,smb_vwv0,max_recv);
190 SSVAL(outbuf,smb_vwv1,conn->cnum);
191 SSVAL(outbuf,smb_tid,conn->cnum);
193 DEBUG(3,("tcon service=%s cnum=%d\n",
194 service, conn->cnum));
196 END_PROFILE(SMBtcon);
197 return(outsize);
200 /****************************************************************************
201 Reply to a tcon and X.
202 ****************************************************************************/
204 int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
206 fstring service;
207 DATA_BLOB password;
208 pstring devicename;
209 NTSTATUS nt_status;
210 uint16 vuid = SVAL(inbuf,smb_uid);
211 int passlen = SVAL(inbuf,smb_vwv3);
212 pstring path;
213 char *p, *q;
214 extern BOOL global_encrypted_passwords_negotiated;
215 START_PROFILE(SMBtconX);
217 *service = *devicename = 0;
219 /* we might have to close an old one */
220 if ((SVAL(inbuf,smb_vwv2) & 0x1) && conn) {
221 close_cnum(conn,vuid);
224 if (passlen > MAX_PASS_LEN) {
225 return ERROR_DOS(ERRDOS,ERRbuftoosmall);
228 if (global_encrypted_passwords_negotiated) {
229 password = data_blob(smb_buf(inbuf),passlen);
230 } else {
231 password = data_blob(smb_buf(inbuf),passlen+1);
232 /* Ensure correct termination */
233 password.data[passlen]=0;
236 p = smb_buf(inbuf) + passlen;
237 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
240 * the service name can be either: \\server\share
241 * or share directly like on the DELL PowerVault 705
243 if (*path=='\\') {
244 q = strchr_m(path+2,'\\');
245 if (!q) {
246 END_PROFILE(SMBtconX);
247 return(ERROR_DOS(ERRDOS,ERRnosuchshare));
249 fstrcpy(service,q+1);
251 else
252 fstrcpy(service,path);
254 p += srvstr_pull(inbuf, devicename, p, sizeof(devicename), 6, STR_ASCII);
256 DEBUG(4,("Got device type %s\n",devicename));
258 conn = make_connection(service,password,devicename,vuid,&nt_status);
260 data_blob_clear_free(&password);
262 if (!conn) {
263 END_PROFILE(SMBtconX);
264 return ERROR_NT(nt_status);
267 if (Protocol < PROTOCOL_NT1) {
268 set_message(outbuf,2,0,True);
269 p = smb_buf(outbuf);
270 p += srvstr_push(outbuf, p, devicename, -1,
271 STR_TERMINATE|STR_ASCII);
272 set_message_end(outbuf,p);
273 } else {
274 /* NT sets the fstype of IPC$ to the null string */
275 char *fsname = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
277 set_message(outbuf,3,0,True);
279 p = smb_buf(outbuf);
280 p += srvstr_push(outbuf, p, devicename, -1,
281 STR_TERMINATE|STR_ASCII);
282 p += srvstr_push(outbuf, p, fsname, -1,
283 STR_TERMINATE);
285 set_message_end(outbuf,p);
287 /* what does setting this bit do? It is set by NT4 and
288 may affect the ability to autorun mounted cdroms */
289 SSVAL(outbuf, smb_vwv2, SMB_SUPPORT_SEARCH_BITS|
290 (lp_csc_policy(SNUM(conn)) << 2));
292 init_dfsroot(conn, inbuf, outbuf);
296 DEBUG(3,("tconX service=%s \n",
297 service));
299 /* set the incoming and outgoing tid to the just created one */
300 SSVAL(inbuf,smb_tid,conn->cnum);
301 SSVAL(outbuf,smb_tid,conn->cnum);
303 END_PROFILE(SMBtconX);
304 return chain_reply(inbuf,outbuf,length,bufsize);
307 /****************************************************************************
308 Reply to an unknown type.
309 ****************************************************************************/
311 int reply_unknown(char *inbuf,char *outbuf)
313 int type;
314 type = CVAL(inbuf,smb_com);
316 DEBUG(0,("unknown command type (%s): type=%d (0x%X)\n",
317 smb_fn_name(type), type, type));
319 return(ERROR_DOS(ERRSRV,ERRunknownsmb));
322 /****************************************************************************
323 Reply to an ioctl.
324 ****************************************************************************/
326 int reply_ioctl(connection_struct *conn,
327 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
329 uint16 device = SVAL(inbuf,smb_vwv1);
330 uint16 function = SVAL(inbuf,smb_vwv2);
331 uint32 ioctl_code = (device << 16) + function;
332 int replysize, outsize;
333 char *p;
334 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
335 START_PROFILE(SMBioctl);
337 DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code));
339 switch (ioctl_code) {
340 case IOCTL_QUERY_JOB_INFO:
341 replysize = 32;
342 break;
343 default:
344 END_PROFILE(SMBioctl);
345 return(ERROR_DOS(ERRSRV,ERRnosupport));
348 outsize = set_message(outbuf,8,replysize+1,True);
349 SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
350 SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
351 SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
352 p = smb_buf(outbuf) + 1; /* Allow for alignment */
354 switch (ioctl_code) {
355 case IOCTL_QUERY_JOB_INFO:
357 uint16 rap_jobid = pjobid_to_rap(SNUM(fsp->conn), fsp->print_jobid);
358 SSVAL(p,0,rap_jobid); /* Job number */
359 srvstr_push(outbuf, p+2, global_myname, 15, STR_TERMINATE|STR_ASCII);
360 srvstr_push(outbuf, p+18, lp_servicename(SNUM(conn)), 13, STR_TERMINATE|STR_ASCII);
361 break;
365 END_PROFILE(SMBioctl);
366 return outsize;
369 /****************************************************************************
370 Reply to a chkpth.
371 ****************************************************************************/
373 int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
375 int outsize = 0;
376 int mode;
377 pstring name;
378 BOOL ok = False;
379 BOOL bad_path = False;
380 SMB_STRUCT_STAT sbuf;
381 START_PROFILE(SMBchkpth);
383 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
385 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
387 unix_convert(name,conn,0,&bad_path,&sbuf);
389 mode = SVAL(inbuf,smb_vwv0);
391 if (check_name(name,conn)) {
392 if (VALID_STAT(sbuf) || vfs_stat(conn,name,&sbuf) == 0)
393 ok = S_ISDIR(sbuf.st_mode);
396 if (!ok) {
397 /* We special case this - as when a Windows machine
398 is parsing a path is steps through the components
399 one at a time - if a component fails it expects
400 ERRbadpath, not ERRbadfile.
402 if(errno == ENOENT)
403 return ERROR_NT(NT_STATUS_OBJECT_PATH_NOT_FOUND);
405 return(UNIXERROR(ERRDOS,ERRbadpath));
408 outsize = set_message(outbuf,0,0,True);
410 DEBUG(3,("chkpth %s mode=%d\n", name, mode));
412 END_PROFILE(SMBchkpth);
413 return(outsize);
416 /****************************************************************************
417 Reply to a getatr.
418 ****************************************************************************/
420 int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
422 pstring fname;
423 int outsize = 0;
424 SMB_STRUCT_STAT sbuf;
425 BOOL ok = False;
426 int mode=0;
427 SMB_OFF_T size=0;
428 time_t mtime=0;
429 BOOL bad_path = False;
430 char *p;
431 START_PROFILE(SMBgetatr);
433 p = smb_buf(inbuf) + 1;
434 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
436 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
438 /* dos smetimes asks for a stat of "" - it returns a "hidden directory"
439 under WfWg - weird! */
440 if (! (*fname))
442 mode = aHIDDEN | aDIR;
443 if (!CAN_WRITE(conn)) mode |= aRONLY;
444 size = 0;
445 mtime = 0;
446 ok = True;
448 else
450 unix_convert(fname,conn,0,&bad_path,&sbuf);
451 if (check_name(fname,conn))
453 if (VALID_STAT(sbuf) || vfs_stat(conn,fname,&sbuf) == 0)
455 mode = dos_mode(conn,fname,&sbuf);
456 size = sbuf.st_size;
457 mtime = sbuf.st_mtime;
458 if (mode & aDIR)
459 size = 0;
460 ok = True;
462 else
463 DEBUG(3,("stat of %s failed (%s)\n",fname,strerror(errno)));
467 if (!ok)
469 set_bad_path_error(errno, bad_path);
470 END_PROFILE(SMBgetatr);
471 return(UNIXERROR(ERRDOS,ERRbadfile));
474 outsize = set_message(outbuf,10,0,True);
476 SSVAL(outbuf,smb_vwv0,mode);
477 if(lp_dos_filetime_resolution(SNUM(conn)) )
478 put_dos_date3(outbuf,smb_vwv1,mtime & ~1);
479 else
480 put_dos_date3(outbuf,smb_vwv1,mtime);
481 SIVAL(outbuf,smb_vwv3,(uint32)size);
483 if (Protocol >= PROTOCOL_NT1)
484 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
486 DEBUG( 3, ( "getatr name=%s mode=%d size=%d\n", fname, mode, (uint32)size ) );
488 END_PROFILE(SMBgetatr);
489 return(outsize);
492 /****************************************************************************
493 Reply to a setatr.
494 ****************************************************************************/
496 int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
498 pstring fname;
499 int outsize = 0;
500 BOOL ok=False;
501 int mode;
502 time_t mtime;
503 SMB_STRUCT_STAT sbuf;
504 BOOL bad_path = False;
505 char *p;
507 START_PROFILE(SMBsetatr);
509 p = smb_buf(inbuf) + 1;
510 p += srvstr_pull_buf(inbuf, fname, p, sizeof(fname), STR_TERMINATE);
511 unix_convert(fname,conn,0,&bad_path,&sbuf);
513 mode = SVAL(inbuf,smb_vwv0);
514 mtime = make_unix_date3(inbuf+smb_vwv1);
516 if (VALID_STAT_OF_DIR(sbuf))
517 mode |= aDIR;
518 else
519 mode &= ~aDIR;
521 if (check_name(fname,conn))
522 ok = (file_chmod(conn,fname,mode,NULL) == 0);
523 if (ok)
524 ok = set_filetime(conn,fname,mtime);
526 if (!ok)
528 set_bad_path_error(errno, bad_path);
529 END_PROFILE(SMBsetatr);
530 return(UNIXERROR(ERRDOS,ERRnoaccess));
533 outsize = set_message(outbuf,0,0,True);
535 DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
537 END_PROFILE(SMBsetatr);
538 return(outsize);
541 /****************************************************************************
542 Reply to a dskattr.
543 ****************************************************************************/
545 int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
547 int outsize = 0;
548 SMB_BIG_UINT dfree,dsize,bsize;
549 START_PROFILE(SMBdskattr);
551 conn->vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
553 outsize = set_message(outbuf,5,0,True);
555 if (Protocol <= PROTOCOL_LANMAN2) {
556 double total_space, free_space;
557 /* we need to scale this to a number that DOS6 can handle. We
558 use floating point so we can handle large drives on systems
559 that don't have 64 bit integers
561 we end up displaying a maximum of 2G to DOS systems
563 total_space = dsize * (double)bsize;
564 free_space = dfree * (double)bsize;
566 dsize = (total_space+63*512) / (64*512);
567 dfree = (free_space+63*512) / (64*512);
569 if (dsize > 0xFFFF) dsize = 0xFFFF;
570 if (dfree > 0xFFFF) dfree = 0xFFFF;
572 SSVAL(outbuf,smb_vwv0,dsize);
573 SSVAL(outbuf,smb_vwv1,64); /* this must be 64 for dos systems */
574 SSVAL(outbuf,smb_vwv2,512); /* and this must be 512 */
575 SSVAL(outbuf,smb_vwv3,dfree);
576 } else {
577 SSVAL(outbuf,smb_vwv0,dsize);
578 SSVAL(outbuf,smb_vwv1,bsize/512);
579 SSVAL(outbuf,smb_vwv2,512);
580 SSVAL(outbuf,smb_vwv3,dfree);
583 DEBUG(3,("dskattr dfree=%d\n", (unsigned int)dfree));
585 END_PROFILE(SMBdskattr);
586 return(outsize);
589 /****************************************************************************
590 Reply to a search.
591 Can be called from SMBsearch, SMBffirst or SMBfunique.
592 ****************************************************************************/
594 int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
596 pstring mask;
597 pstring directory;
598 pstring fname;
599 SMB_OFF_T size;
600 int mode;
601 time_t date;
602 int dirtype;
603 int outsize = 0;
604 int numentries = 0;
605 BOOL finished = False;
606 int maxentries;
607 int i;
608 char *p;
609 BOOL ok = False;
610 int status_len;
611 pstring path;
612 char status[21];
613 int dptr_num= -1;
614 BOOL check_descend = False;
615 BOOL expect_close = False;
616 BOOL can_open = True;
617 BOOL bad_path = False;
618 START_PROFILE(SMBsearch);
620 *mask = *directory = *fname = 0;
622 /* If we were called as SMBffirst then we must expect close. */
623 if(CVAL(inbuf,smb_com) == SMBffirst)
624 expect_close = True;
626 outsize = set_message(outbuf,1,3,True);
627 maxentries = SVAL(inbuf,smb_vwv0);
628 dirtype = SVAL(inbuf,smb_vwv1);
629 p = smb_buf(inbuf) + 1;
630 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
631 p++;
632 status_len = SVAL(p, 0);
633 p += 2;
635 /* dirtype &= ~aDIR; */
637 if (status_len == 0)
639 SMB_STRUCT_STAT sbuf;
640 pstring dir2;
642 pstrcpy(directory,path);
643 pstrcpy(dir2,path);
644 unix_convert(directory,conn,0,&bad_path,&sbuf);
645 unix_format(dir2);
647 if (!check_name(directory,conn))
648 can_open = False;
650 p = strrchr_m(dir2,'/');
651 if (p == NULL)
653 pstrcpy(mask,dir2);
654 *dir2 = 0;
656 else
658 *p = 0;
659 pstrcpy(mask,p+1);
662 p = strrchr_m(directory,'/');
663 if (!p)
664 *directory = 0;
665 else
666 *p = 0;
668 if (strlen(directory) == 0)
669 pstrcpy(directory,"./");
670 memset((char *)status,'\0',21);
671 SCVAL(status,0,(dirtype & 0x1F));
673 else
675 int status_dirtype;
676 memcpy(status,p,21);
677 status_dirtype = CVAL(status,0) & 0x1F;
678 if (status_dirtype != (dirtype & 0x1F))
679 dirtype = status_dirtype;
681 conn->dirptr = dptr_fetch(status+12,&dptr_num);
682 if (!conn->dirptr)
683 goto SearchEmpty;
684 string_set(&conn->dirpath,dptr_path(dptr_num));
685 fstrcpy(mask, dptr_wcard(dptr_num));
688 if (can_open)
690 p = smb_buf(outbuf) + 3;
692 ok = True;
694 if (status_len == 0)
696 dptr_num = dptr_create(conn,directory,True,expect_close,SVAL(inbuf,smb_pid));
697 if (dptr_num < 0)
699 if(dptr_num == -2)
701 set_bad_path_error(errno, bad_path);
702 END_PROFILE(SMBsearch);
703 return (UNIXERROR(ERRDOS,ERRnofids));
705 END_PROFILE(SMBsearch);
706 return ERROR_DOS(ERRDOS,ERRnofids);
708 dptr_set_wcard(dptr_num, strdup(mask));
711 DEBUG(4,("dptr_num is %d\n",dptr_num));
713 if (ok)
715 if ((dirtype&0x1F) == aVOLID)
717 memcpy(p,status,21);
718 make_dir_struct(p,"???????????",volume_label(SNUM(conn)),0,aVOLID,0);
719 dptr_fill(p+12,dptr_num);
720 if (dptr_zero(p+12) && (status_len==0))
721 numentries = 1;
722 else
723 numentries = 0;
724 p += DIR_STRUCT_SIZE;
726 else
728 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
729 conn->dirpath,lp_dontdescend(SNUM(conn))));
730 if (in_list(conn->dirpath, lp_dontdescend(SNUM(conn)),True))
731 check_descend = True;
733 for (i=numentries;(i<maxentries) && !finished;i++)
735 finished =
736 !get_dir_entry(conn,mask,dirtype,fname,&size,&mode,&date,check_descend);
737 if (!finished)
739 memcpy(p,status,21);
740 make_dir_struct(p,mask,fname,size,mode,date);
741 dptr_fill(p+12,dptr_num);
742 numentries++;
744 p += DIR_STRUCT_SIZE;
747 } /* if (ok ) */
751 SearchEmpty:
753 if (numentries == 0 || !ok)
755 SCVAL(outbuf,smb_rcls,ERRDOS);
756 SSVAL(outbuf,smb_err,ERRnofiles);
757 dptr_close(&dptr_num);
760 /* If we were called as SMBffirst with smb_search_id == NULL
761 and no entries were found then return error and close dirptr
762 (X/Open spec) */
764 if(ok && expect_close && numentries == 0 && status_len == 0)
766 SCVAL(outbuf,smb_rcls,ERRDOS);
767 SSVAL(outbuf,smb_err,ERRnofiles);
768 /* Also close the dptr - we know it's gone */
769 dptr_close(&dptr_num);
772 /* If we were called as SMBfunique, then we can close the dirptr now ! */
773 if(dptr_num >= 0 && CVAL(inbuf,smb_com) == SMBfunique)
774 dptr_close(&dptr_num);
776 SSVAL(outbuf,smb_vwv0,numentries);
777 SSVAL(outbuf,smb_vwv1,3 + numentries * DIR_STRUCT_SIZE);
778 SCVAL(smb_buf(outbuf),0,5);
779 SSVAL(smb_buf(outbuf),1,numentries*DIR_STRUCT_SIZE);
781 if (Protocol >= PROTOCOL_NT1)
782 SSVAL(outbuf,smb_flg2,SVAL(outbuf, smb_flg2) | FLAGS2_IS_LONG_NAME);
784 outsize += DIR_STRUCT_SIZE*numentries;
785 smb_setlen(outbuf,outsize - 4);
787 if ((! *directory) && dptr_path(dptr_num))
788 slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
790 DEBUG( 4, ( "%s mask=%s path=%s dtype=%d nument=%d of %d\n",
791 smb_fn_name(CVAL(inbuf,smb_com)),
792 mask, directory, dirtype, numentries, maxentries ) );
794 END_PROFILE(SMBsearch);
795 return(outsize);
798 /****************************************************************************
799 Reply to a fclose (stop directory search).
800 ****************************************************************************/
802 int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
804 int outsize = 0;
805 int status_len;
806 pstring path;
807 char status[21];
808 int dptr_num= -2;
809 char *p;
811 START_PROFILE(SMBfclose);
813 outsize = set_message(outbuf,1,0,True);
814 p = smb_buf(inbuf) + 1;
815 p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
816 p++;
817 status_len = SVAL(p,0);
818 p += 2;
820 if (status_len == 0) {
821 END_PROFILE(SMBfclose);
822 return ERROR_DOS(ERRSRV,ERRsrverror);
825 memcpy(status,p,21);
827 if(dptr_fetch(status+12,&dptr_num)) {
828 /* Close the dptr - we know it's gone */
829 dptr_close(&dptr_num);
832 SSVAL(outbuf,smb_vwv0,0);
834 DEBUG(3,("search close\n"));
836 END_PROFILE(SMBfclose);
837 return(outsize);
840 /****************************************************************************
841 Reply to an open.
842 ****************************************************************************/
844 int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
846 pstring fname;
847 int outsize = 0;
848 int fmode=0;
849 int share_mode;
850 SMB_OFF_T size = 0;
851 time_t mtime=0;
852 mode_t unixmode;
853 int rmode=0;
854 SMB_STRUCT_STAT sbuf;
855 BOOL bad_path = False;
856 files_struct *fsp;
857 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
858 START_PROFILE(SMBopen);
860 share_mode = SVAL(inbuf,smb_vwv0);
862 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
864 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
866 unix_convert(fname,conn,0,&bad_path,&sbuf);
868 unixmode = unix_mode(conn,aARCH,fname);
870 fsp = open_file_shared(conn,fname,&sbuf,share_mode,(FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),
871 unixmode, oplock_request,&rmode,NULL);
873 if (!fsp)
875 set_bad_path_error(errno, bad_path);
876 END_PROFILE(SMBopen);
877 return(UNIXERROR(ERRDOS,ERRnoaccess));
880 size = sbuf.st_size;
881 fmode = dos_mode(conn,fname,&sbuf);
882 mtime = sbuf.st_mtime;
884 if (fmode & aDIR) {
885 DEBUG(3,("attempt to open a directory %s\n",fname));
886 close_file(fsp,False);
887 END_PROFILE(SMBopen);
888 return ERROR_DOS(ERRDOS,ERRnoaccess);
891 outsize = set_message(outbuf,7,0,True);
892 SSVAL(outbuf,smb_vwv0,fsp->fnum);
893 SSVAL(outbuf,smb_vwv1,fmode);
894 if(lp_dos_filetime_resolution(SNUM(conn)) )
895 put_dos_date3(outbuf,smb_vwv2,mtime & ~1);
896 else
897 put_dos_date3(outbuf,smb_vwv2,mtime);
898 SIVAL(outbuf,smb_vwv4,(uint32)size);
899 SSVAL(outbuf,smb_vwv6,rmode);
901 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
902 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
905 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
906 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
907 END_PROFILE(SMBopen);
908 return(outsize);
911 /****************************************************************************
912 Reply to an open and X.
913 ****************************************************************************/
915 int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
917 pstring fname;
918 int smb_mode = SVAL(inbuf,smb_vwv3);
919 int smb_attr = SVAL(inbuf,smb_vwv5);
920 /* Breakout the oplock request bits so we can set the
921 reply bits separately. */
922 BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
923 BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
924 BOOL oplock_request = ex_oplock_request | core_oplock_request;
925 #if 0
926 int open_flags = SVAL(inbuf,smb_vwv2);
927 int smb_sattr = SVAL(inbuf,smb_vwv4);
928 uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
929 #endif
930 int smb_ofun = SVAL(inbuf,smb_vwv8);
931 mode_t unixmode;
932 SMB_OFF_T size=0;
933 int fmode=0,mtime=0,rmode=0;
934 SMB_STRUCT_STAT sbuf;
935 int smb_action = 0;
936 BOOL bad_path = False;
937 files_struct *fsp;
938 START_PROFILE(SMBopenX);
940 /* If it's an IPC, pass off the pipe handler. */
941 if (IS_IPC(conn)) {
942 if (lp_nt_pipe_support()) {
943 END_PROFILE(SMBopenX);
944 return reply_open_pipe_and_X(conn, inbuf,outbuf,length,bufsize);
945 } else {
946 END_PROFILE(SMBopenX);
947 return ERROR_DOS(ERRSRV,ERRaccess);
951 /* XXXX we need to handle passed times, sattr and flags */
952 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
954 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
956 unix_convert(fname,conn,0,&bad_path,&sbuf);
958 unixmode = unix_mode(conn,smb_attr | aARCH, fname);
960 fsp = open_file_shared(conn,fname,&sbuf,smb_mode,smb_ofun,unixmode,
961 oplock_request, &rmode,&smb_action);
963 if (!fsp)
965 set_bad_path_error(errno, bad_path);
966 END_PROFILE(SMBopenX);
967 return(UNIXERROR(ERRDOS,ERRnoaccess));
970 size = sbuf.st_size;
971 fmode = dos_mode(conn,fname,&sbuf);
972 mtime = sbuf.st_mtime;
973 if (fmode & aDIR) {
974 close_file(fsp,False);
975 END_PROFILE(SMBopenX);
976 return ERROR_DOS(ERRDOS,ERRnoaccess);
979 /* If the caller set the extended oplock request bit
980 and we granted one (by whatever means) - set the
981 correct bit for extended oplock reply.
984 if (ex_oplock_request && lp_fake_oplocks(SNUM(conn))) {
985 smb_action |= EXTENDED_OPLOCK_GRANTED;
988 if(ex_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
989 smb_action |= EXTENDED_OPLOCK_GRANTED;
992 /* If the caller set the core oplock request bit
993 and we granted one (by whatever means) - set the
994 correct bit for core oplock reply.
997 if (core_oplock_request && lp_fake_oplocks(SNUM(conn))) {
998 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1001 if(core_oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
1002 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1005 set_message(outbuf,15,0,True);
1006 SSVAL(outbuf,smb_vwv2,fsp->fnum);
1007 SSVAL(outbuf,smb_vwv3,fmode);
1008 if(lp_dos_filetime_resolution(SNUM(conn)) )
1009 put_dos_date3(outbuf,smb_vwv4,mtime & ~1);
1010 else
1011 put_dos_date3(outbuf,smb_vwv4,mtime);
1012 SIVAL(outbuf,smb_vwv6,(uint32)size);
1013 SSVAL(outbuf,smb_vwv8,rmode);
1014 SSVAL(outbuf,smb_vwv11,smb_action);
1016 END_PROFILE(SMBopenX);
1017 return chain_reply(inbuf,outbuf,length,bufsize);
1020 /****************************************************************************
1021 Reply to a SMBulogoffX.
1022 ****************************************************************************/
1024 int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1026 uint16 vuid = SVAL(inbuf,smb_uid);
1027 user_struct *vuser = get_valid_user_struct(vuid);
1028 START_PROFILE(SMBulogoffX);
1030 if(vuser == 0) {
1031 DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
1034 /* in user level security we are supposed to close any files
1035 open by this user */
1036 if ((vuser != 0) && (lp_security() != SEC_SHARE)) {
1037 file_close_user(vuid);
1040 invalidate_vuid(vuid);
1042 set_message(outbuf,2,0,True);
1044 DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
1046 END_PROFILE(SMBulogoffX);
1047 return chain_reply(inbuf,outbuf,length,bufsize);
1050 /****************************************************************************
1051 Reply to a mknew or a create.
1052 ****************************************************************************/
1054 int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1056 pstring fname;
1057 int com;
1058 int outsize = 0;
1059 int createmode;
1060 mode_t unixmode;
1061 int ofun = 0;
1062 BOOL bad_path = False;
1063 files_struct *fsp;
1064 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1065 SMB_STRUCT_STAT sbuf;
1066 START_PROFILE(SMBcreate);
1068 com = SVAL(inbuf,smb_com);
1070 createmode = SVAL(inbuf,smb_vwv0);
1071 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), STR_TERMINATE);
1073 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1075 unix_convert(fname,conn,0,&bad_path,&sbuf);
1077 if (createmode & aVOLID) {
1078 DEBUG(0,("Attempt to create file (%s) with volid set - please report this\n",fname));
1081 unixmode = unix_mode(conn,createmode,fname);
1083 if(com == SMBmknew)
1085 /* We should fail if file exists. */
1086 ofun = FILE_CREATE_IF_NOT_EXIST;
1088 else
1090 /* SMBcreate - Create if file doesn't exist, truncate if it does. */
1091 ofun = FILE_CREATE_IF_NOT_EXIST|FILE_EXISTS_TRUNCATE;
1094 /* Open file in dos compatibility share mode. */
1095 fsp = open_file_shared(conn,fname,&sbuf,SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1096 ofun, unixmode, oplock_request, NULL, NULL);
1098 if (!fsp)
1100 set_bad_path_error(errno, bad_path);
1101 END_PROFILE(SMBcreate);
1102 return(UNIXERROR(ERRDOS,ERRnoaccess));
1105 outsize = set_message(outbuf,1,0,True);
1106 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1108 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1109 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1112 if(EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1113 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1115 DEBUG( 2, ( "new file %s\n", fname ) );
1116 DEBUG( 3, ( "mknew %s fd=%d dmode=%d umode=%o\n",
1117 fname, fsp->fd, createmode, (int)unixmode ) );
1119 END_PROFILE(SMBcreate);
1120 return(outsize);
1123 /****************************************************************************
1124 Reply to a create temporary file.
1125 ****************************************************************************/
1127 int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
1129 pstring fname;
1130 int outsize = 0;
1131 int createmode;
1132 mode_t unixmode;
1133 BOOL bad_path = False;
1134 files_struct *fsp;
1135 int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
1136 int tmpfd;
1137 SMB_STRUCT_STAT sbuf;
1138 char *p, *s;
1140 START_PROFILE(SMBctemp);
1142 createmode = SVAL(inbuf,smb_vwv0);
1143 srvstr_pull_buf(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), STR_TERMINATE);
1144 pstrcat(fname,"\\TMXXXXXX");
1146 RESOLVE_DFSPATH(fname, conn, inbuf, outbuf);
1148 unix_convert(fname,conn,0,&bad_path,&sbuf);
1150 unixmode = unix_mode(conn,createmode,fname);
1152 tmpfd = smb_mkstemp(fname);
1153 if (tmpfd == -1) {
1154 END_PROFILE(SMBctemp);
1155 return(UNIXERROR(ERRDOS,ERRnoaccess));
1158 vfs_stat(conn,fname,&sbuf);
1160 /* Open file in dos compatibility share mode. */
1161 /* We should fail if file does not exist. */
1162 fsp = open_file_shared(conn,fname,&sbuf,
1163 SET_DENY_MODE(DENY_FCB)|SET_OPEN_MODE(DOS_OPEN_FCB),
1164 FILE_EXISTS_OPEN|FILE_FAIL_IF_NOT_EXIST,
1165 unixmode, oplock_request, NULL, NULL);
1167 /* close fd from smb_mkstemp() */
1168 close(tmpfd);
1170 if (!fsp) {
1171 set_bad_path_error(errno, bad_path);
1172 END_PROFILE(SMBctemp);
1173 return(UNIXERROR(ERRDOS,ERRnoaccess));
1176 outsize = set_message(outbuf,1,0,True);
1177 SSVAL(outbuf,smb_vwv0,fsp->fnum);
1179 /* the returned filename is relative to the directory */
1180 s = strrchr_m(fname, '/');
1181 if (!s) {
1182 s = fname;
1183 } else {
1184 s++;
1187 p = smb_buf(outbuf);
1188 SSVALS(p, 0, -1); /* what is this? not in spec */
1189 SSVAL(p, 2, strlen(s));
1190 p += 4;
1191 p += srvstr_push(outbuf, p, s, -1, STR_ASCII);
1192 outsize = set_message_end(outbuf, p);
1194 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1195 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1198 if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type))
1199 SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
1201 DEBUG( 2, ( "created temp file %s\n", fname ) );
1202 DEBUG( 3, ( "ctemp %s fd=%d dmode=%d umode=%o\n",
1203 fname, fsp->fd, createmode, (int)unixmode ) );
1205 END_PROFILE(SMBctemp);
1206 return(outsize);
1209 /*******************************************************************
1210 Check if a user is allowed to rename a file.
1211 ********************************************************************/
1213 static NTSTATUS can_rename(char *fname,connection_struct *conn, SMB_STRUCT_STAT *pst)
1215 int smb_action;
1216 int access_mode;
1217 files_struct *fsp;
1219 if (!CAN_WRITE(conn))
1220 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1222 if (S_ISDIR(pst->st_mode))
1223 return NT_STATUS_OK;
1225 /* We need a better way to return NT status codes from open... */
1226 unix_ERR_class = 0;
1227 unix_ERR_code = 0;
1229 fsp = open_file_shared1(conn, fname, pst, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1230 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1232 if (!fsp) {
1233 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1234 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1235 ret = NT_STATUS_SHARING_VIOLATION;
1236 unix_ERR_class = 0;
1237 unix_ERR_code = 0;
1238 return ret;
1240 close_file(fsp,False);
1241 return NT_STATUS_OK;
1244 /*******************************************************************
1245 Check if a user is allowed to delete a file.
1246 ********************************************************************/
1248 static NTSTATUS can_delete(char *fname,connection_struct *conn, int dirtype)
1250 SMB_STRUCT_STAT sbuf;
1251 int fmode;
1252 int smb_action;
1253 int access_mode;
1254 files_struct *fsp;
1256 if (!CAN_WRITE(conn))
1257 return NT_STATUS_MEDIA_WRITE_PROTECTED;
1259 if (conn->vfs_ops.lstat(conn,fname,&sbuf) != 0)
1260 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1262 fmode = dos_mode(conn,fname,&sbuf);
1263 if (fmode & aDIR)
1264 return NT_STATUS_FILE_IS_A_DIRECTORY;
1265 if (!lp_delete_readonly(SNUM(conn))) {
1266 if (fmode & aRONLY)
1267 return NT_STATUS_CANNOT_DELETE;
1269 if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM))
1270 return NT_STATUS_CANNOT_DELETE;
1272 /* We need a better way to return NT status codes from open... */
1273 unix_ERR_class = 0;
1274 unix_ERR_code = 0;
1276 fsp = open_file_shared1(conn, fname, &sbuf, DELETE_ACCESS, SET_DENY_MODE(DENY_ALL),
1277 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN), 0, 0, &access_mode, &smb_action);
1279 if (!fsp) {
1280 NTSTATUS ret = NT_STATUS_ACCESS_DENIED;
1281 if (unix_ERR_class == ERRDOS && unix_ERR_code == ERRbadshare)
1282 ret = NT_STATUS_SHARING_VIOLATION;
1283 unix_ERR_class = 0;
1284 unix_ERR_code = 0;
1285 return ret;
1287 close_file(fsp,False);
1288 return NT_STATUS_OK;
1291 /****************************************************************************
1292 The guts of the unlink command, split out so it may be called by the NT SMB
1293 code.
1294 ****************************************************************************/
1296 NTSTATUS unlink_internals(connection_struct *conn, int dirtype, char *name)
1298 pstring directory;
1299 pstring mask;
1300 char *p;
1301 int count=0;
1302 NTSTATUS error = NT_STATUS_OK;
1303 BOOL has_wild;
1304 BOOL bad_path = False;
1305 BOOL rc = True;
1306 SMB_STRUCT_STAT sbuf;
1308 *directory = *mask = 0;
1310 rc = unix_convert(name,conn,0,&bad_path,&sbuf);
1312 p = strrchr_m(name,'/');
1313 if (!p) {
1314 pstrcpy(directory,".");
1315 pstrcpy(mask,name);
1316 } else {
1317 *p = 0;
1318 pstrcpy(directory,name);
1319 pstrcpy(mask,p+1);
1323 * We should only check the mangled cache
1324 * here if unix_convert failed. This means
1325 * that the path in 'mask' doesn't exist
1326 * on the file system and so we need to look
1327 * for a possible mangle. This patch from
1328 * Tine Smukavec <valentin.smukavec@hermes.si>.
1331 if (!rc && mangle_is_mangled(mask))
1332 mangle_check_cache( mask );
1334 has_wild = ms_has_wild(mask);
1336 if (!has_wild) {
1337 pstrcat(directory,"/");
1338 pstrcat(directory,mask);
1339 error = can_delete(directory,conn,dirtype);
1340 if (!NT_STATUS_IS_OK(error)) return error;
1342 if (vfs_unlink(conn,directory) == 0) {
1343 count++;
1345 } else {
1346 void *dirptr = NULL;
1347 char *dname;
1349 if (check_name(directory,conn))
1350 dirptr = OpenDir(conn, directory, True);
1352 /* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
1353 the pattern matches against the long name, otherwise the short name
1354 We don't implement this yet XXXX
1357 if (dirptr) {
1358 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
1360 if (strequal(mask,"????????.???"))
1361 pstrcpy(mask,"*");
1363 while ((dname = ReadDirName(dirptr))) {
1364 pstring fname;
1365 pstrcpy(fname,dname);
1367 if(!mask_match(fname, mask, case_sensitive)) continue;
1369 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
1370 error = can_delete(fname,conn,dirtype);
1371 if (!NT_STATUS_IS_OK(error)) continue;
1372 if (vfs_unlink(conn,fname) == 0) count++;
1373 DEBUG(3,("unlink_internals: succesful unlink [%s]\n",fname));
1375 CloseDir(dirptr);
1379 if (count == 0 && NT_STATUS_IS_OK(error)) {
1380 error = map_nt_error_from_unix(errno);
1383 return error;
1386 /****************************************************************************
1387 Reply to a unlink
1388 ****************************************************************************/
1390 int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
1391 int dum_buffsize)
1393 int outsize = 0;
1394 pstring name;
1395 int dirtype;
1396 NTSTATUS status;
1397 START_PROFILE(SMBunlink);
1399 dirtype = SVAL(inbuf,smb_vwv0);
1401 srvstr_pull_buf(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), STR_TERMINATE);
1403 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
1405 DEBUG(3,("reply_unlink : %s\n",name));
1407 status = unlink_internals(conn, dirtype, name);
1408 if (!NT_STATUS_IS_OK(status)) return ERROR_NT(status);
1411 * Win2k needs a changenotify request response before it will
1412 * update after a rename..
1414 process_pending_change_notify_queue((time_t)0);
1416 outsize = set_message(outbuf,0,0,True);
1418 END_PROFILE(SMBunlink);
1419 return outsize;
1422 /****************************************************************************
1423 Fail for readbraw.
1424 ****************************************************************************/
1426 void fail_readraw(void)
1428 pstring errstr;
1429 slprintf(errstr, sizeof(errstr)-1, "FAIL ! reply_readbraw: socket write fail (%s)",
1430 strerror(errno) );
1431 exit_server(errstr);
1434 /****************************************************************************
1435 Use sendfile in readbraw.
1436 ****************************************************************************/
1438 void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T startpos, size_t nread,
1439 ssize_t mincount, char *outbuf)
1441 ssize_t ret=0;
1443 #if defined(WITH_SENDFILE)
1445 * We can only use sendfile on a non-chained packet and on a file
1446 * that is exclusively oplocked. reply_readbraw has already checked the length.
1449 if ((nread > 0) && (lp_write_cache_size(SNUM(conn)) == 0) &&
1450 EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && lp_use_sendfile(SNUM(conn)) ) {
1451 DATA_BLOB header;
1453 _smb_setlen(outbuf,nread);
1454 header.data = outbuf;
1455 header.length = 4;
1456 header.free = NULL;
1458 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, nread) == -1) {
1460 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1461 * return ENOSYS then pretend we just got a normal read.
1463 if (errno == ENOSYS)
1464 goto normal_read;
1466 DEBUG(0,("send_file_readbraw: sendfile failed for file %s (%s). Terminating\n",
1467 fsp->fsp_name, strerror(errno) ));
1468 exit_server("send_file_readbraw sendfile failed");
1473 normal_read:
1474 #endif
1476 if (nread > 0) {
1477 ret = read_file(fsp,outbuf+4,startpos,nread);
1478 if (ret < mincount)
1479 ret = 0;
1482 _smb_setlen(outbuf,ret);
1483 if (write_data(smbd_server_fd(),outbuf,4+ret) != 4+ret)
1484 fail_readraw();
1487 /****************************************************************************
1488 Reply to a readbraw (core+ protocol).
1489 ****************************************************************************/
1491 int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_size, int dum_buffsize)
1493 ssize_t maxcount,mincount;
1494 size_t nread = 0;
1495 SMB_OFF_T startpos;
1496 char *header = outbuf;
1497 files_struct *fsp;
1498 START_PROFILE(SMBreadbraw);
1501 * Special check if an oplock break has been issued
1502 * and the readraw request croses on the wire, we must
1503 * return a zero length response here.
1506 if(global_oplock_break) {
1507 _smb_setlen(header,0);
1508 if (write_data(smbd_server_fd(),header,4) != 4)
1509 fail_readraw();
1510 DEBUG(5,("readbraw - oplock break finished\n"));
1511 END_PROFILE(SMBreadbraw);
1512 return -1;
1515 fsp = file_fsp(inbuf,smb_vwv0);
1517 if (!FNUM_OK(fsp,conn) || !fsp->can_read) {
1519 * fsp could be NULL here so use the value from the packet. JRA.
1521 DEBUG(3,("fnum %d not open in readbraw - cache prime?\n",(int)SVAL(inbuf,smb_vwv0)));
1522 _smb_setlen(header,0);
1523 if (write_data(smbd_server_fd(),header,4) != 4)
1524 fail_readraw();
1525 END_PROFILE(SMBreadbraw);
1526 return(-1);
1529 CHECK_FSP(fsp,conn);
1531 flush_write_cache(fsp, READRAW_FLUSH);
1533 startpos = IVAL(inbuf,smb_vwv1);
1534 if(CVAL(inbuf,smb_wct) == 10) {
1536 * This is a large offset (64 bit) read.
1538 #ifdef LARGE_SMB_OFF_T
1540 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv8)) << 32);
1542 #else /* !LARGE_SMB_OFF_T */
1545 * Ensure we haven't been sent a >32 bit offset.
1548 if(IVAL(inbuf,smb_vwv8) != 0) {
1549 DEBUG(0,("readbraw - large offset (%x << 32) used and we don't support \
1550 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv8) ));
1551 _smb_setlen(header,0);
1552 if (write_data(smbd_server_fd(),header,4) != 4)
1553 fail_readraw();
1554 END_PROFILE(SMBreadbraw);
1555 return(-1);
1558 #endif /* LARGE_SMB_OFF_T */
1560 if(startpos < 0) {
1561 DEBUG(0,("readbraw - negative 64 bit readraw offset (%.0f) !\n", (double)startpos ));
1562 _smb_setlen(header,0);
1563 if (write_data(smbd_server_fd(),header,4) != 4)
1564 fail_readraw();
1565 END_PROFILE(SMBreadbraw);
1566 return(-1);
1569 maxcount = (SVAL(inbuf,smb_vwv3) & 0xFFFF);
1570 mincount = (SVAL(inbuf,smb_vwv4) & 0xFFFF);
1572 /* ensure we don't overrun the packet size */
1573 maxcount = MIN(65535,maxcount);
1574 maxcount = MAX(mincount,maxcount);
1576 if (!is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1577 SMB_OFF_T size = fsp->size;
1578 SMB_OFF_T sizeneeded = startpos + maxcount;
1580 if (size < sizeneeded) {
1581 SMB_STRUCT_STAT st;
1582 if (vfs_fstat(fsp,fsp->fd,&st) == 0)
1583 size = st.st_size;
1584 if (!fsp->can_write)
1585 fsp->size = size;
1588 if (startpos >= size)
1589 nread = 0;
1590 else
1591 nread = MIN(maxcount,(size - startpos));
1594 if (nread < mincount)
1595 nread = 0;
1597 DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos,
1598 (int)maxcount, (int)mincount, (int)nread ) );
1600 send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf);
1602 DEBUG(5,("readbraw finished\n"));
1603 END_PROFILE(SMBreadbraw);
1604 return -1;
1607 /****************************************************************************
1608 Reply to a lockread (core+ protocol).
1609 ****************************************************************************/
1611 int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length, int dum_buffsiz)
1613 ssize_t nread = -1;
1614 char *data;
1615 int outsize = 0;
1616 SMB_OFF_T startpos;
1617 size_t numtoread;
1618 NTSTATUS status;
1619 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1620 START_PROFILE(SMBlockread);
1622 CHECK_FSP(fsp,conn);
1623 CHECK_READ(fsp);
1625 release_level_2_oplocks_on_change(fsp);
1627 numtoread = SVAL(inbuf,smb_vwv1);
1628 startpos = IVAL(inbuf,smb_vwv2);
1630 outsize = set_message(outbuf,5,3,True);
1631 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1632 data = smb_buf(outbuf) + 3;
1635 * NB. Discovered by Menny Hamburger at Mainsoft. This is a core+
1636 * protocol request that predates the read/write lock concept.
1637 * Thus instead of asking for a read lock here we need to ask
1638 * for a write lock. JRA.
1641 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid),
1642 (SMB_BIG_UINT)numtoread, (SMB_BIG_UINT)startpos, WRITE_LOCK);
1644 if (NT_STATUS_V(status)) {
1645 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
1647 * A blocking lock was requested. Package up
1648 * this smb into a queued request and push it
1649 * onto the blocking lock queue.
1651 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
1652 END_PROFILE(SMBlockread);
1653 return -1;
1656 END_PROFILE(SMBlockread);
1657 return ERROR_NT(status);
1660 nread = read_file(fsp,data,startpos,numtoread);
1662 if (nread < 0) {
1663 END_PROFILE(SMBlockread);
1664 return(UNIXERROR(ERRDOS,ERRnoaccess));
1667 outsize += nread;
1668 SSVAL(outbuf,smb_vwv0,nread);
1669 SSVAL(outbuf,smb_vwv5,nread+3);
1670 SSVAL(smb_buf(outbuf),1,nread);
1672 DEBUG(3,("lockread fnum=%d num=%d nread=%d\n",
1673 fsp->fnum, (int)numtoread, (int)nread));
1675 END_PROFILE(SMBlockread);
1676 return(outsize);
1679 /****************************************************************************
1680 Reply to a read.
1681 ****************************************************************************/
1683 int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1685 size_t numtoread;
1686 ssize_t nread = 0;
1687 char *data;
1688 SMB_OFF_T startpos;
1689 int outsize = 0;
1690 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1691 START_PROFILE(SMBread);
1693 CHECK_FSP(fsp,conn);
1694 CHECK_READ(fsp);
1696 numtoread = SVAL(inbuf,smb_vwv1);
1697 startpos = IVAL(inbuf,smb_vwv2);
1699 outsize = set_message(outbuf,5,3,True);
1700 numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
1701 data = smb_buf(outbuf) + 3;
1703 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtoread,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1704 END_PROFILE(SMBread);
1705 return ERROR_DOS(ERRDOS,ERRlock);
1708 if (numtoread > 0)
1709 nread = read_file(fsp,data,startpos,numtoread);
1711 if (nread < 0) {
1712 END_PROFILE(SMBread);
1713 return(UNIXERROR(ERRDOS,ERRnoaccess));
1716 outsize += nread;
1717 SSVAL(outbuf,smb_vwv0,nread);
1718 SSVAL(outbuf,smb_vwv5,nread+3);
1719 SCVAL(smb_buf(outbuf),0,1);
1720 SSVAL(smb_buf(outbuf),1,nread);
1722 DEBUG( 3, ( "read fnum=%d num=%d nread=%d\n",
1723 fsp->fnum, (int)numtoread, (int)nread ) );
1725 END_PROFILE(SMBread);
1726 return(outsize);
1729 /****************************************************************************
1730 Reply to a read and X - possibly using sendfile.
1731 ****************************************************************************/
1733 int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length,
1734 files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
1736 ssize_t nread = -1;
1737 char *data = smb_buf(outbuf);
1739 #if defined(WITH_SENDFILE)
1741 * We can only use sendfile on a non-chained packet and on a file
1742 * that is exclusively oplocked.
1745 if ((CVAL(inbuf,smb_vwv0) == 0xFF) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) &&
1746 lp_use_sendfile(SNUM(conn)) && (lp_write_cache_size(SNUM(conn)) == 0) ) {
1747 SMB_STRUCT_STAT sbuf;
1748 DATA_BLOB header;
1750 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1)
1751 return(UNIXERROR(ERRDOS,ERRnoaccess));
1753 if (startpos > sbuf.st_size)
1754 goto normal_read;
1756 if (smb_maxcnt > (sbuf.st_size - startpos))
1757 smb_maxcnt = (sbuf.st_size - startpos);
1759 if (smb_maxcnt == 0)
1760 goto normal_read;
1763 * Set up the packet header before send. We
1764 * assume here the sendfile will work (get the
1765 * correct amount of data).
1768 SSVAL(outbuf,smb_vwv5,smb_maxcnt);
1769 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1770 SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
1771 SCVAL(outbuf,smb_vwv0,0xFF);
1772 set_message(outbuf,12,smb_maxcnt,False);
1773 header.data = outbuf;
1774 header.length = data - outbuf;
1775 header.free = NULL;
1777 if ( conn->vfs_ops.sendfile( smbd_server_fd(), fsp, fsp->fd, &header, startpos, smb_maxcnt) == -1) {
1779 * Special hack for broken Linux with no 64 bit clean sendfile. If we
1780 * return ENOSYS then pretend we just got a normal read.
1782 if (errno == ENOSYS)
1783 goto normal_read;
1785 DEBUG(0,("send_file_readX: sendfile failed for file %s (%s). Terminating\n",
1786 fsp->fsp_name, strerror(errno) ));
1787 exit_server("send_file_readX sendfile failed");
1790 DEBUG( 3, ( "send_file_readX: sendfile fnum=%d max=%d nread=%d\n",
1791 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1792 return -1;
1795 normal_read:
1797 #endif
1799 nread = read_file(fsp,data,startpos,smb_maxcnt);
1801 if (nread < 0) {
1802 END_PROFILE(SMBreadX);
1803 return(UNIXERROR(ERRDOS,ERRnoaccess));
1806 SSVAL(outbuf,smb_vwv5,nread);
1807 SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
1808 SSVAL(smb_buf(outbuf),-2,nread);
1810 DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
1811 fsp->fnum, (int)smb_maxcnt, (int)nread ) );
1813 return nread;
1816 /****************************************************************************
1817 Reply to a read and X.
1818 ****************************************************************************/
1820 int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
1822 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
1823 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
1824 ssize_t nread = -1;
1825 size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
1826 #if 0
1827 size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
1828 #endif
1830 START_PROFILE(SMBreadX);
1832 /* If it's an IPC, pass off the pipe handler. */
1833 if (IS_IPC(conn)) {
1834 END_PROFILE(SMBreadX);
1835 return reply_pipe_read_and_X(inbuf,outbuf,length,bufsize);
1838 CHECK_FSP(fsp,conn);
1839 CHECK_READ(fsp);
1841 set_message(outbuf,12,0,True);
1843 if(CVAL(inbuf,smb_wct) == 12) {
1844 #ifdef LARGE_SMB_OFF_T
1846 * This is a large offset (64 bit) read.
1848 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv10)) << 32);
1850 #else /* !LARGE_SMB_OFF_T */
1853 * Ensure we haven't been sent a >32 bit offset.
1856 if(IVAL(inbuf,smb_vwv10) != 0) {
1857 DEBUG(0,("reply_read_and_X - large offset (%x << 32) used and we don't support \
1858 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv10) ));
1859 END_PROFILE(SMBreadX);
1860 return ERROR_DOS(ERRDOS,ERRbadaccess);
1863 #endif /* LARGE_SMB_OFF_T */
1867 if (is_locked(fsp,conn,(SMB_BIG_UINT)smb_maxcnt,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
1868 END_PROFILE(SMBreadX);
1869 return ERROR_DOS(ERRDOS,ERRlock);
1872 nread = send_file_readX(conn, inbuf, outbuf, length, fsp, startpos, smb_maxcnt);
1873 if (nread != -1)
1874 nread = chain_reply(inbuf,outbuf,length,bufsize);
1876 END_PROFILE(SMBreadX);
1877 return nread;
1880 /****************************************************************************
1881 Reply to a writebraw (core+ or LANMAN1.0 protocol).
1882 ****************************************************************************/
1884 int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
1886 ssize_t nwritten=0;
1887 ssize_t total_written=0;
1888 size_t numtowrite=0;
1889 size_t tcount;
1890 SMB_OFF_T startpos;
1891 char *data=NULL;
1892 BOOL write_through;
1893 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
1894 int outsize = 0;
1895 START_PROFILE(SMBwritebraw);
1897 CHECK_FSP(fsp,conn);
1898 CHECK_WRITE(fsp);
1900 tcount = IVAL(inbuf,smb_vwv1);
1901 startpos = IVAL(inbuf,smb_vwv3);
1902 write_through = BITSETW(inbuf+smb_vwv7,0);
1904 /* We have to deal with slightly different formats depending
1905 on whether we are using the core+ or lanman1.0 protocol */
1907 if(Protocol <= PROTOCOL_COREPLUS) {
1908 numtowrite = SVAL(smb_buf(inbuf),-2);
1909 data = smb_buf(inbuf);
1910 } else {
1911 numtowrite = SVAL(inbuf,smb_vwv10);
1912 data = smb_base(inbuf) + SVAL(inbuf, smb_vwv11);
1915 /* force the error type */
1916 SCVAL(inbuf,smb_com,SMBwritec);
1917 SCVAL(outbuf,smb_com,SMBwritec);
1919 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
1920 END_PROFILE(SMBwritebraw);
1921 return(ERROR_DOS(ERRDOS,ERRlock));
1924 if (numtowrite>0)
1925 nwritten = write_file(fsp,data,startpos,numtowrite);
1927 DEBUG(3,("writebraw1 fnum=%d start=%.0f num=%d wrote=%d sync=%d\n",
1928 fsp->fnum, (double)startpos, (int)numtowrite, (int)nwritten, (int)write_through));
1930 if (nwritten < numtowrite) {
1931 END_PROFILE(SMBwritebraw);
1932 return(UNIXERROR(ERRHRD,ERRdiskfull));
1935 total_written = nwritten;
1937 /* Return a message to the redirector to tell it to send more bytes */
1938 SCVAL(outbuf,smb_com,SMBwritebraw);
1939 SSVALS(outbuf,smb_vwv0,-1);
1940 outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
1941 if (!send_smb(smbd_server_fd(),outbuf))
1942 exit_server("reply_writebraw: send_smb failed.");
1944 /* Now read the raw data into the buffer and write it */
1945 if (read_smb_length(smbd_server_fd(),inbuf,SMB_SECONDARY_WAIT) == -1) {
1946 exit_server("secondary writebraw failed");
1949 /* Even though this is not an smb message, smb_len returns the generic length of an smb message */
1950 numtowrite = smb_len(inbuf);
1952 /* Set up outbuf to return the correct return */
1953 outsize = set_message(outbuf,1,0,True);
1954 SCVAL(outbuf,smb_com,SMBwritec);
1955 SSVAL(outbuf,smb_vwv0,total_written);
1957 if (numtowrite != 0) {
1959 if (numtowrite > BUFFER_SIZE) {
1960 DEBUG(0,("reply_writebraw: Oversize secondary write raw requested (%u). Terminating\n",
1961 (unsigned int)numtowrite ));
1962 exit_server("secondary writebraw failed");
1965 if (tcount > nwritten+numtowrite) {
1966 DEBUG(3,("Client overestimated the write %d %d %d\n",
1967 (int)tcount,(int)nwritten,(int)numtowrite));
1970 if (read_data( smbd_server_fd(), inbuf+4, numtowrite) != numtowrite ) {
1971 DEBUG(0,("reply_writebraw: Oversize secondary write raw read failed (%s). Terminating\n",
1972 strerror(errno) ));
1973 exit_server("secondary writebraw failed");
1976 nwritten = write_file(fsp,inbuf+4,startpos+nwritten,numtowrite);
1978 if (nwritten < (ssize_t)numtowrite) {
1979 SCVAL(outbuf,smb_rcls,ERRHRD);
1980 SSVAL(outbuf,smb_err,ERRdiskfull);
1983 if (nwritten > 0)
1984 total_written += nwritten;
1987 if ((lp_syncalways(SNUM(conn)) || write_through) && lp_strict_sync(SNUM(conn)))
1988 sync_file(conn,fsp);
1990 DEBUG(3,("writebraw2 fnum=%d start=%.0f num=%d wrote=%d\n",
1991 fsp->fnum, (double)startpos, (int)numtowrite,(int)total_written));
1993 /* we won't return a status if write through is not selected - this follows what WfWg does */
1994 END_PROFILE(SMBwritebraw);
1995 if (!write_through && total_written==tcount) {
1997 #if RABBIT_PELLET_FIX
1999 * Fix for "rabbit pellet" mode, trigger an early TCP ack by
2000 * sending a SMBkeepalive. Thanks to DaveCB at Sun for this. JRA.
2002 if (!send_keepalive(smbd_server_fd()))
2003 exit_server("reply_writebraw: send of keepalive failed");
2004 #endif
2005 return(-1);
2008 return(outsize);
2011 /****************************************************************************
2012 Reply to a writeunlock (core+).
2013 ****************************************************************************/
2015 int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
2016 int size, int dum_buffsize)
2018 ssize_t nwritten = -1;
2019 size_t numtowrite;
2020 SMB_OFF_T startpos;
2021 char *data;
2022 NTSTATUS status;
2023 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2024 int outsize = 0;
2025 START_PROFILE(SMBwriteunlock);
2027 CHECK_FSP(fsp,conn);
2028 CHECK_WRITE(fsp);
2030 numtowrite = SVAL(inbuf,smb_vwv1);
2031 startpos = IVAL(inbuf,smb_vwv2);
2032 data = smb_buf(inbuf) + 3;
2034 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos,
2035 WRITE_LOCK,False)) {
2036 END_PROFILE(SMBwriteunlock);
2037 return ERROR_DOS(ERRDOS,ERRlock);
2040 /* The special X/Open SMB protocol handling of
2041 zero length writes is *NOT* done for
2042 this call */
2043 if(numtowrite == 0)
2044 nwritten = 0;
2045 else
2046 nwritten = write_file(fsp,data,startpos,numtowrite);
2048 if (lp_syncalways(SNUM(conn)))
2049 sync_file(conn,fsp);
2051 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2052 END_PROFILE(SMBwriteunlock);
2053 return(UNIXERROR(ERRDOS,ERRnoaccess));
2056 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), (SMB_BIG_UINT)numtowrite,
2057 (SMB_BIG_UINT)startpos);
2058 if (NT_STATUS_V(status)) {
2059 END_PROFILE(SMBwriteunlock);
2060 return ERROR_NT(status);
2063 outsize = set_message(outbuf,1,0,True);
2065 SSVAL(outbuf,smb_vwv0,nwritten);
2067 DEBUG(3,("writeunlock fnum=%d num=%d wrote=%d\n",
2068 fsp->fnum, (int)numtowrite, (int)nwritten));
2070 END_PROFILE(SMBwriteunlock);
2071 return outsize;
2074 /****************************************************************************
2075 Reply to a write.
2076 ****************************************************************************/
2078 int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int dum_buffsize)
2080 size_t numtowrite;
2081 ssize_t nwritten = -1;
2082 SMB_OFF_T startpos;
2083 char *data;
2084 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2085 int outsize = 0;
2086 START_PROFILE(SMBwrite);
2088 /* If it's an IPC, pass off the pipe handler. */
2089 if (IS_IPC(conn)) {
2090 END_PROFILE(SMBwrite);
2091 return reply_pipe_write(inbuf,outbuf,size,dum_buffsize);
2094 CHECK_FSP(fsp,conn);
2095 CHECK_WRITE(fsp);
2097 numtowrite = SVAL(inbuf,smb_vwv1);
2098 startpos = IVAL(inbuf,smb_vwv2);
2099 data = smb_buf(inbuf) + 3;
2101 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2102 END_PROFILE(SMBwrite);
2103 return ERROR_DOS(ERRDOS,ERRlock);
2107 * X/Open SMB protocol says that if smb_vwv1 is
2108 * zero then the file size should be extended or
2109 * truncated to the size given in smb_vwv[2-3].
2112 if(numtowrite == 0) {
2114 * This is actually an allocate call, and set EOF. JRA.
2116 nwritten = vfs_allocate_file_space(fsp, (SMB_OFF_T)startpos);
2117 if (nwritten < 0) {
2118 END_PROFILE(SMBwrite);
2119 return ERROR_NT(NT_STATUS_DISK_FULL);
2121 nwritten = vfs_set_filelen(fsp, (SMB_OFF_T)startpos);
2122 if (nwritten < 0) {
2123 END_PROFILE(SMBwrite);
2124 return ERROR_NT(NT_STATUS_DISK_FULL);
2126 } else
2127 nwritten = write_file(fsp,data,startpos,numtowrite);
2129 if (lp_syncalways(SNUM(conn)))
2130 sync_file(conn,fsp);
2132 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2133 END_PROFILE(SMBwrite);
2134 return(UNIXERROR(ERRDOS,ERRnoaccess));
2137 outsize = set_message(outbuf,1,0,True);
2139 SSVAL(outbuf,smb_vwv0,nwritten);
2141 if (nwritten < (ssize_t)numtowrite) {
2142 SCVAL(outbuf,smb_rcls,ERRHRD);
2143 SSVAL(outbuf,smb_err,ERRdiskfull);
2146 DEBUG(3,("write fnum=%d num=%d wrote=%d\n", fsp->fnum, (int)numtowrite, (int)nwritten));
2148 END_PROFILE(SMBwrite);
2149 return(outsize);
2152 /****************************************************************************
2153 Reply to a write and X.
2154 ****************************************************************************/
2156 int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
2158 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
2159 SMB_OFF_T startpos = IVAL(inbuf,smb_vwv3);
2160 size_t numtowrite = SVAL(inbuf,smb_vwv10);
2161 BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
2162 ssize_t nwritten = -1;
2163 unsigned int smb_doff = SVAL(inbuf,smb_vwv11);
2164 unsigned int smblen = smb_len(inbuf);
2165 char *data;
2166 BOOL large_writeX = ((CVAL(inbuf,smb_wct) == 14) && (smblen > 0xFFFF));
2167 START_PROFILE(SMBwriteX);
2169 /* If it's an IPC, pass off the pipe handler. */
2170 if (IS_IPC(conn)) {
2171 END_PROFILE(SMBwriteX);
2172 return reply_pipe_write_and_X(inbuf,outbuf,length,bufsize);
2175 CHECK_FSP(fsp,conn);
2176 CHECK_WRITE(fsp);
2178 /* Deal with possible LARGE_WRITEX */
2179 if (large_writeX)
2180 numtowrite |= ((((size_t)SVAL(inbuf,smb_vwv9)) & 1 )<<16);
2182 if(smb_doff > smblen || (smb_doff + numtowrite > smblen)) {
2183 END_PROFILE(SMBwriteX);
2184 return ERROR_DOS(ERRDOS,ERRbadmem);
2187 data = smb_base(inbuf) + smb_doff;
2189 if(CVAL(inbuf,smb_wct) == 14) {
2190 #ifdef LARGE_SMB_OFF_T
2192 * This is a large offset (64 bit) write.
2194 startpos |= (((SMB_OFF_T)IVAL(inbuf,smb_vwv12)) << 32);
2196 #else /* !LARGE_SMB_OFF_T */
2199 * Ensure we haven't been sent a >32 bit offset.
2202 if(IVAL(inbuf,smb_vwv12) != 0) {
2203 DEBUG(0,("reply_write_and_X - large offset (%x << 32) used and we don't support \
2204 64 bit offsets.\n", (unsigned int)IVAL(inbuf,smb_vwv12) ));
2205 END_PROFILE(SMBwriteX);
2206 return ERROR_DOS(ERRDOS,ERRbadaccess);
2209 #endif /* LARGE_SMB_OFF_T */
2212 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2213 END_PROFILE(SMBwriteX);
2214 return ERROR_DOS(ERRDOS,ERRlock);
2217 /* X/Open SMB protocol says that, unlike SMBwrite
2218 if the length is zero then NO truncation is
2219 done, just a write of zero. To truncate a file,
2220 use SMBwrite. */
2221 if(numtowrite == 0)
2222 nwritten = 0;
2223 else
2224 nwritten = write_file(fsp,data,startpos,numtowrite);
2226 if(((nwritten == 0) && (numtowrite != 0))||(nwritten < 0)) {
2227 END_PROFILE(SMBwriteX);
2228 return(UNIXERROR(ERRDOS,ERRnoaccess));
2231 set_message(outbuf,6,0,True);
2233 SSVAL(outbuf,smb_vwv2,nwritten);
2234 if (large_writeX)
2235 SSVAL(outbuf,smb_vwv4,(nwritten>>16)&1);
2237 if (nwritten < (ssize_t)numtowrite) {
2238 SCVAL(outbuf,smb_rcls,ERRHRD);
2239 SSVAL(outbuf,smb_err,ERRdiskfull);
2242 DEBUG(3,("writeX fnum=%d num=%d wrote=%d\n",
2243 fsp->fnum, (int)numtowrite, (int)nwritten));
2245 if (lp_syncalways(SNUM(conn)) || write_through)
2246 sync_file(conn,fsp);
2248 END_PROFILE(SMBwriteX);
2249 return chain_reply(inbuf,outbuf,length,bufsize);
2252 /****************************************************************************
2253 Reply to a lseek.
2254 ****************************************************************************/
2256 int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2258 SMB_OFF_T startpos;
2259 SMB_OFF_T res= -1;
2260 int mode,umode;
2261 int outsize = 0;
2262 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2263 START_PROFILE(SMBlseek);
2265 CHECK_FSP(fsp,conn);
2267 flush_write_cache(fsp, SEEK_FLUSH);
2269 mode = SVAL(inbuf,smb_vwv1) & 3;
2270 startpos = IVALS(inbuf,smb_vwv2);
2272 switch (mode) {
2273 case 0: umode = SEEK_SET; break;
2274 case 1: umode = SEEK_CUR; break;
2275 case 2: umode = SEEK_END; break;
2276 default:
2277 umode = SEEK_SET; break;
2280 if((res = conn->vfs_ops.lseek(fsp,fsp->fd,startpos,umode)) == -1) {
2282 * Check for the special case where a seek before the start
2283 * of the file sets the offset to zero. Added in the CIFS spec,
2284 * section 4.2.7.
2287 if(errno == EINVAL) {
2288 SMB_OFF_T current_pos = startpos;
2290 if(umode == SEEK_CUR) {
2292 if((current_pos = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_CUR)) == -1) {
2293 END_PROFILE(SMBlseek);
2294 return(UNIXERROR(ERRDOS,ERRnoaccess));
2297 current_pos += startpos;
2299 } else if (umode == SEEK_END) {
2301 SMB_STRUCT_STAT sbuf;
2303 if(vfs_fstat(fsp,fsp->fd, &sbuf) == -1) {
2304 END_PROFILE(SMBlseek);
2305 return(UNIXERROR(ERRDOS,ERRnoaccess));
2308 current_pos += sbuf.st_size;
2311 if(current_pos < 0)
2312 res = conn->vfs_ops.lseek(fsp,fsp->fd,0,SEEK_SET);
2315 if(res == -1) {
2316 END_PROFILE(SMBlseek);
2317 return(UNIXERROR(ERRDOS,ERRnoaccess));
2321 fsp->pos = res;
2323 outsize = set_message(outbuf,2,0,True);
2324 SIVAL(outbuf,smb_vwv0,res);
2326 DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
2327 fsp->fnum, (double)startpos, (double)res, mode));
2329 END_PROFILE(SMBlseek);
2330 return(outsize);
2333 /****************************************************************************
2334 Reply to a flush.
2335 ****************************************************************************/
2337 int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
2339 int outsize = set_message(outbuf,0,0,True);
2340 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2341 START_PROFILE(SMBflush);
2343 CHECK_FSP(fsp,conn);
2345 if (!fsp) {
2346 file_sync_all(conn);
2347 } else {
2348 sync_file(conn,fsp);
2351 DEBUG(3,("flush\n"));
2352 END_PROFILE(SMBflush);
2353 return(outsize);
2356 /****************************************************************************
2357 Reply to a exit.
2358 ****************************************************************************/
2360 int reply_exit(connection_struct *conn,
2361 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2363 int outsize;
2364 START_PROFILE(SMBexit);
2365 outsize = set_message(outbuf,0,0,True);
2367 DEBUG(3,("exit\n"));
2369 END_PROFILE(SMBexit);
2370 return(outsize);
2373 /****************************************************************************
2374 Reply to a close - has to deal with closing a directory opened by NT SMB's.
2375 ****************************************************************************/
2377 int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
2378 int dum_buffsize)
2380 int outsize = 0;
2381 time_t mtime;
2382 int32 eclass = 0, err = 0;
2383 files_struct *fsp = NULL;
2384 START_PROFILE(SMBclose);
2386 outsize = set_message(outbuf,0,0,True);
2388 /* If it's an IPC, pass off to the pipe handler. */
2389 if (IS_IPC(conn)) {
2390 END_PROFILE(SMBclose);
2391 return reply_pipe_close(conn, inbuf,outbuf);
2394 fsp = file_fsp(inbuf,smb_vwv0);
2397 * We can only use CHECK_FSP if we know it's not a directory.
2400 if(!fsp || (fsp->conn != conn)) {
2401 END_PROFILE(SMBclose);
2402 return ERROR_DOS(ERRDOS,ERRbadfid);
2405 if(fsp->is_directory) {
2407 * Special case - close NT SMB directory handle.
2409 DEBUG(3,("close %s fnum=%d\n", fsp->is_directory ? "directory" : "stat file open", fsp->fnum));
2410 close_file(fsp,True);
2411 } else {
2413 * Close ordinary file.
2415 int close_err;
2416 pstring file_name;
2418 /* Save the name for time set in close. */
2419 pstrcpy( file_name, fsp->fsp_name);
2421 DEBUG(3,("close fd=%d fnum=%d (numopen=%d)\n",
2422 fsp->fd, fsp->fnum,
2423 conn->num_files_open));
2426 * close_file() returns the unix errno if an error
2427 * was detected on close - normally this is due to
2428 * a disk full error. If not then it was probably an I/O error.
2431 if((close_err = close_file(fsp,True)) != 0) {
2432 errno = close_err;
2433 END_PROFILE(SMBclose);
2434 return (UNIXERROR(ERRHRD,ERRgeneral));
2438 * Now take care of any time sent in the close.
2441 mtime = make_unix_date3(inbuf+smb_vwv1);
2443 /* try and set the date */
2444 set_filetime(conn, file_name, mtime);
2448 /* We have a cached error */
2449 if(eclass || err) {
2450 END_PROFILE(SMBclose);
2451 return ERROR_DOS(eclass,err);
2454 END_PROFILE(SMBclose);
2455 return(outsize);
2458 /****************************************************************************
2459 Reply to a writeclose (Core+ protocol).
2460 ****************************************************************************/
2462 int reply_writeclose(connection_struct *conn,
2463 char *inbuf,char *outbuf, int size, int dum_buffsize)
2465 size_t numtowrite;
2466 ssize_t nwritten = -1;
2467 int outsize = 0;
2468 int close_err = 0;
2469 SMB_OFF_T startpos;
2470 char *data;
2471 time_t mtime;
2472 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2473 START_PROFILE(SMBwriteclose);
2475 CHECK_FSP(fsp,conn);
2476 CHECK_WRITE(fsp);
2478 numtowrite = SVAL(inbuf,smb_vwv1);
2479 startpos = IVAL(inbuf,smb_vwv2);
2480 mtime = make_unix_date3(inbuf+smb_vwv4);
2481 data = smb_buf(inbuf) + 1;
2483 if (is_locked(fsp,conn,(SMB_BIG_UINT)numtowrite,(SMB_BIG_UINT)startpos, WRITE_LOCK,False)) {
2484 END_PROFILE(SMBwriteclose);
2485 return ERROR_DOS(ERRDOS,ERRlock);
2488 nwritten = write_file(fsp,data,startpos,numtowrite);
2490 set_filetime(conn, fsp->fsp_name,mtime);
2492 close_err = close_file(fsp,True);
2494 DEBUG(3,("writeclose fnum=%d num=%d wrote=%d (numopen=%d)\n",
2495 fsp->fnum, (int)numtowrite, (int)nwritten,
2496 conn->num_files_open));
2498 if (nwritten <= 0) {
2499 END_PROFILE(SMBwriteclose);
2500 return(UNIXERROR(ERRDOS,ERRnoaccess));
2503 if(close_err != 0) {
2504 errno = close_err;
2505 END_PROFILE(SMBwriteclose);
2506 return(UNIXERROR(ERRHRD,ERRgeneral));
2509 outsize = set_message(outbuf,1,0,True);
2511 SSVAL(outbuf,smb_vwv0,nwritten);
2512 END_PROFILE(SMBwriteclose);
2513 return(outsize);
2516 /****************************************************************************
2517 Reply to a lock.
2518 ****************************************************************************/
2520 int reply_lock(connection_struct *conn,
2521 char *inbuf,char *outbuf, int length, int dum_buffsize)
2523 int outsize = set_message(outbuf,0,0,True);
2524 SMB_BIG_UINT count,offset;
2525 NTSTATUS status;
2526 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2527 START_PROFILE(SMBlock);
2529 CHECK_FSP(fsp,conn);
2531 release_level_2_oplocks_on_change(fsp);
2533 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2534 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2536 DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2537 fsp->fd, fsp->fnum, (double)offset, (double)count));
2539 status = do_lock_spin(fsp, conn, SVAL(inbuf,smb_pid), count, offset, WRITE_LOCK);
2540 if (NT_STATUS_V(status)) {
2541 if (lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
2543 * A blocking lock was requested. Package up
2544 * this smb into a queued request and push it
2545 * onto the blocking lock queue.
2547 if(push_blocking_lock_request(inbuf, length, -1, 0)) {
2548 END_PROFILE(SMBlock);
2549 return -1;
2552 END_PROFILE(SMBlock);
2553 return ERROR_NT(status);
2556 END_PROFILE(SMBlock);
2557 return(outsize);
2560 /****************************************************************************
2561 Reply to a unlock.
2562 ****************************************************************************/
2564 int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
2565 int dum_buffsize)
2567 int outsize = set_message(outbuf,0,0,True);
2568 SMB_BIG_UINT count,offset;
2569 NTSTATUS status;
2570 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2571 START_PROFILE(SMBunlock);
2573 CHECK_FSP(fsp,conn);
2575 count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
2576 offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
2578 status = do_unlock(fsp, conn, SVAL(inbuf,smb_pid), count, offset);
2579 if (NT_STATUS_V(status)) {
2580 END_PROFILE(SMBunlock);
2581 return ERROR_NT(status);
2584 DEBUG( 3, ( "unlock fd=%d fnum=%d offset=%.0f count=%.0f\n",
2585 fsp->fd, fsp->fnum, (double)offset, (double)count ) );
2587 END_PROFILE(SMBunlock);
2588 return(outsize);
2591 /****************************************************************************
2592 Reply to a tdis.
2593 ****************************************************************************/
2595 int reply_tdis(connection_struct *conn,
2596 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2598 int outsize = set_message(outbuf,0,0,True);
2599 uint16 vuid;
2600 START_PROFILE(SMBtdis);
2602 vuid = SVAL(inbuf,smb_uid);
2604 if (!conn) {
2605 DEBUG(4,("Invalid connection in tdis\n"));
2606 END_PROFILE(SMBtdis);
2607 return ERROR_DOS(ERRSRV,ERRinvnid);
2610 conn->used = False;
2612 close_cnum(conn,vuid);
2614 END_PROFILE(SMBtdis);
2615 return outsize;
2618 /****************************************************************************
2619 Reply to a echo.
2620 ****************************************************************************/
2622 int reply_echo(connection_struct *conn,
2623 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2625 int smb_reverb = SVAL(inbuf,smb_vwv0);
2626 int seq_num;
2627 unsigned int data_len = smb_buflen(inbuf);
2628 int outsize = set_message(outbuf,1,data_len,True);
2629 START_PROFILE(SMBecho);
2631 data_len = MIN(data_len, (sizeof(inbuf)-(smb_buf(inbuf)-inbuf)));
2633 /* copy any incoming data back out */
2634 if (data_len > 0)
2635 memcpy(smb_buf(outbuf),smb_buf(inbuf),data_len);
2637 if (smb_reverb > 100) {
2638 DEBUG(0,("large reverb (%d)?? Setting to 100\n",smb_reverb));
2639 smb_reverb = 100;
2642 for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
2643 SSVAL(outbuf,smb_vwv0,seq_num);
2645 smb_setlen(outbuf,outsize - 4);
2647 if (!send_smb(smbd_server_fd(),outbuf))
2648 exit_server("reply_echo: send_smb failed.");
2651 DEBUG(3,("echo %d times\n", smb_reverb));
2653 smb_echo_count++;
2655 END_PROFILE(SMBecho);
2656 return -1;
2659 /****************************************************************************
2660 Reply to a printopen.
2661 ****************************************************************************/
2663 int reply_printopen(connection_struct *conn,
2664 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2666 int outsize = 0;
2667 files_struct *fsp;
2668 START_PROFILE(SMBsplopen);
2670 if (!CAN_PRINT(conn)) {
2671 END_PROFILE(SMBsplopen);
2672 return ERROR_DOS(ERRDOS,ERRnoaccess);
2675 /* Open for exclusive use, write only. */
2676 fsp = print_fsp_open(conn, NULL);
2678 if (!fsp) {
2679 END_PROFILE(SMBsplopen);
2680 return(UNIXERROR(ERRDOS,ERRnoaccess));
2683 outsize = set_message(outbuf,1,0,True);
2684 SSVAL(outbuf,smb_vwv0,fsp->fnum);
2686 DEBUG(3,("openprint fd=%d fnum=%d\n",
2687 fsp->fd, fsp->fnum));
2689 END_PROFILE(SMBsplopen);
2690 return(outsize);
2693 /****************************************************************************
2694 Reply to a printclose.
2695 ****************************************************************************/
2696 int reply_printclose(connection_struct *conn,
2697 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2699 int outsize = set_message(outbuf,0,0,True);
2700 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2701 int close_err = 0;
2702 START_PROFILE(SMBsplclose);
2704 CHECK_FSP(fsp,conn);
2706 if (!CAN_PRINT(conn)) {
2707 END_PROFILE(SMBsplclose);
2708 return ERROR_DOS(ERRDOS,ERRnoaccess);
2711 DEBUG(3,("printclose fd=%d fnum=%d\n",
2712 fsp->fd,fsp->fnum));
2714 close_err = close_file(fsp,True);
2716 if(close_err != 0) {
2717 errno = close_err;
2718 END_PROFILE(SMBsplclose);
2719 return(UNIXERROR(ERRHRD,ERRgeneral));
2722 END_PROFILE(SMBsplclose);
2723 return(outsize);
2726 /****************************************************************************
2727 Reply to a printqueue.
2728 ****************************************************************************/
2730 int reply_printqueue(connection_struct *conn,
2731 char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2733 int outsize = set_message(outbuf,2,3,True);
2734 int max_count = SVAL(inbuf,smb_vwv0);
2735 int start_index = SVAL(inbuf,smb_vwv1);
2736 START_PROFILE(SMBsplretq);
2738 /* we used to allow the client to get the cnum wrong, but that
2739 is really quite gross and only worked when there was only
2740 one printer - I think we should now only accept it if they
2741 get it right (tridge) */
2742 if (!CAN_PRINT(conn)) {
2743 END_PROFILE(SMBsplretq);
2744 return ERROR_DOS(ERRDOS,ERRnoaccess);
2747 SSVAL(outbuf,smb_vwv0,0);
2748 SSVAL(outbuf,smb_vwv1,0);
2749 SCVAL(smb_buf(outbuf),0,1);
2750 SSVAL(smb_buf(outbuf),1,0);
2752 DEBUG(3,("printqueue start_index=%d max_count=%d\n",
2753 start_index, max_count));
2756 print_queue_struct *queue = NULL;
2757 print_status_struct status;
2758 char *p = smb_buf(outbuf) + 3;
2759 int count = print_queue_status(SNUM(conn), &queue, &status);
2760 int num_to_get = ABS(max_count);
2761 int first = (max_count>0?start_index:start_index+max_count+1);
2762 int i;
2764 if (first >= count)
2765 num_to_get = 0;
2766 else
2767 num_to_get = MIN(num_to_get,count-first);
2770 for (i=first;i<first+num_to_get;i++) {
2771 put_dos_date2(p,0,queue[i].time);
2772 SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3));
2773 SSVAL(p,5, queue[i].job);
2774 SIVAL(p,7,queue[i].size);
2775 SCVAL(p,11,0);
2776 srvstr_push(outbuf, p+12, queue[i].fs_user, 16, STR_ASCII);
2777 p += 28;
2780 if (count > 0) {
2781 outsize = set_message(outbuf,2,28*count+3,False);
2782 SSVAL(outbuf,smb_vwv0,count);
2783 SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
2784 SCVAL(smb_buf(outbuf),0,1);
2785 SSVAL(smb_buf(outbuf),1,28*count);
2788 SAFE_FREE(queue);
2790 DEBUG(3,("%d entries returned in queue\n",count));
2793 END_PROFILE(SMBsplretq);
2794 return(outsize);
2797 /****************************************************************************
2798 Reply to a printwrite.
2799 ****************************************************************************/
2801 int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2803 int numtowrite;
2804 int outsize = set_message(outbuf,0,0,True);
2805 char *data;
2806 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
2807 START_PROFILE(SMBsplwr);
2809 if (!CAN_PRINT(conn)) {
2810 END_PROFILE(SMBsplwr);
2811 return ERROR_DOS(ERRDOS,ERRnoaccess);
2814 CHECK_FSP(fsp,conn);
2815 CHECK_WRITE(fsp);
2817 numtowrite = SVAL(smb_buf(inbuf),1);
2818 data = smb_buf(inbuf) + 3;
2820 if (write_file(fsp,data,-1,numtowrite) != numtowrite) {
2821 END_PROFILE(SMBsplwr);
2822 return(UNIXERROR(ERRDOS,ERRnoaccess));
2825 DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) );
2827 END_PROFILE(SMBsplwr);
2828 return(outsize);
2831 /****************************************************************************
2832 The guts of the mkdir command, split out so it may be called by the NT SMB
2833 code.
2834 ****************************************************************************/
2836 NTSTATUS mkdir_internal(connection_struct *conn, pstring directory)
2838 BOOL bad_path = False;
2839 SMB_STRUCT_STAT sbuf;
2840 int ret= -1;
2842 unix_convert(directory,conn,0,&bad_path,&sbuf);
2844 if (check_name(directory, conn))
2845 ret = vfs_mkdir(conn,directory,unix_mode(conn,aDIR,directory));
2847 if (ret == -1) {
2848 NTSTATUS nterr = set_bad_path_error(errno, bad_path);
2849 if (!NT_STATUS_IS_OK(nterr))
2850 return nterr;
2851 return map_nt_error_from_unix(errno);
2854 return NT_STATUS_OK;
2857 /****************************************************************************
2858 Reply to a mkdir.
2859 ****************************************************************************/
2861 int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
2863 pstring directory;
2864 int outsize;
2865 NTSTATUS status;
2866 START_PROFILE(SMBmkdir);
2868 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
2870 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf);
2872 status = mkdir_internal(conn, directory);
2873 if (!NT_STATUS_IS_OK(status))
2874 return ERROR_NT(status);
2876 outsize = set_message(outbuf,0,0,True);
2878 DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
2880 END_PROFILE(SMBmkdir);
2881 return(outsize);
2884 /****************************************************************************
2885 Static function used by reply_rmdir to delete an entire directory
2886 tree recursively. Return False on ok, True on fail.
2887 ****************************************************************************/
2889 static BOOL recursive_rmdir(connection_struct *conn, char *directory)
2891 char *dname = NULL;
2892 BOOL ret = False;
2893 void *dirptr = OpenDir(conn, directory, False);
2895 if(dirptr == NULL)
2896 return True;
2898 while((dname = ReadDirName(dirptr))) {
2899 pstring fullname;
2900 SMB_STRUCT_STAT st;
2902 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2903 continue;
2905 /* Construct the full name. */
2906 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2907 errno = ENOMEM;
2908 ret = True;
2909 break;
2912 pstrcpy(fullname, directory);
2913 pstrcat(fullname, "/");
2914 pstrcat(fullname, dname);
2916 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0) {
2917 ret = True;
2918 break;
2921 if(st.st_mode & S_IFDIR) {
2922 if(recursive_rmdir(conn, fullname)!=0) {
2923 ret = True;
2924 break;
2926 if(vfs_rmdir(conn,fullname) != 0) {
2927 ret = True;
2928 break;
2930 } else if(vfs_unlink(conn,fullname) != 0) {
2931 ret = True;
2932 break;
2935 CloseDir(dirptr);
2936 return ret;
2939 /****************************************************************************
2940 The internals of the rmdir code - called elsewhere.
2941 ****************************************************************************/
2943 BOOL rmdir_internals(connection_struct *conn, char *directory)
2945 BOOL ok;
2947 ok = (vfs_rmdir(conn,directory) == 0);
2948 if(!ok && ((errno == ENOTEMPTY)||(errno == EEXIST)) && lp_veto_files(SNUM(conn))) {
2950 * Check to see if the only thing in this directory are
2951 * vetoed files/directories. If so then delete them and
2952 * retry. If we fail to delete any of them (and we *don't*
2953 * do a recursive delete) then fail the rmdir.
2955 BOOL all_veto_files = True;
2956 char *dname;
2957 void *dirptr = OpenDir(conn, directory, False);
2959 if(dirptr != NULL) {
2960 int dirpos = TellDir(dirptr);
2961 while ((dname = ReadDirName(dirptr))) {
2962 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2963 continue;
2964 if(!IS_VETO_PATH(conn, dname)) {
2965 all_veto_files = False;
2966 break;
2970 if(all_veto_files) {
2971 SeekDir(dirptr,dirpos);
2972 while ((dname = ReadDirName(dirptr))) {
2973 pstring fullname;
2974 SMB_STRUCT_STAT st;
2976 if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
2977 continue;
2979 /* Construct the full name. */
2980 if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname)) {
2981 errno = ENOMEM;
2982 break;
2985 pstrcpy(fullname, directory);
2986 pstrcat(fullname, "/");
2987 pstrcat(fullname, dname);
2989 if(conn->vfs_ops.lstat(conn,fullname, &st) != 0)
2990 break;
2991 if(st.st_mode & S_IFDIR) {
2992 if(lp_recursive_veto_delete(SNUM(conn))) {
2993 if(recursive_rmdir(conn, fullname) != 0)
2994 break;
2996 if(vfs_rmdir(conn,fullname) != 0)
2997 break;
2998 } else if(vfs_unlink(conn,fullname) != 0)
2999 break;
3001 CloseDir(dirptr);
3002 /* Retry the rmdir */
3003 ok = (vfs_rmdir(conn,directory) == 0);
3004 } else {
3005 CloseDir(dirptr);
3007 } else {
3008 errno = ENOTEMPTY;
3012 if (!ok)
3013 DEBUG(3,("rmdir_internals: couldn't remove directory %s : %s\n", directory,strerror(errno)));
3015 return ok;
3018 /****************************************************************************
3019 Reply to a rmdir.
3020 ****************************************************************************/
3022 int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3024 pstring directory;
3025 int outsize = 0;
3026 BOOL ok = False;
3027 BOOL bad_path = False;
3028 SMB_STRUCT_STAT sbuf;
3029 START_PROFILE(SMBrmdir);
3031 srvstr_pull_buf(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), STR_TERMINATE);
3033 RESOLVE_DFSPATH(directory, conn, inbuf, outbuf)
3035 unix_convert(directory,conn, NULL,&bad_path,&sbuf);
3037 if (check_name(directory,conn))
3039 dptr_closepath(directory,SVAL(inbuf,smb_pid));
3040 ok = rmdir_internals(conn, directory);
3043 if (!ok)
3045 set_bad_path_error(errno, bad_path);
3046 END_PROFILE(SMBrmdir);
3047 return(UNIXERROR(ERRDOS,ERRbadpath));
3050 outsize = set_message(outbuf,0,0,True);
3052 DEBUG( 3, ( "rmdir %s\n", directory ) );
3054 END_PROFILE(SMBrmdir);
3055 return(outsize);
3058 /*******************************************************************
3059 Resolve wildcards in a filename rename.
3060 ********************************************************************/
3062 static BOOL resolve_wildcards(char *name1,char *name2)
3064 fstring root1,root2;
3065 fstring ext1,ext2;
3066 char *p,*p2;
3068 name1 = strrchr_m(name1,'/');
3069 name2 = strrchr_m(name2,'/');
3071 if (!name1 || !name2) return(False);
3073 fstrcpy(root1,name1);
3074 fstrcpy(root2,name2);
3075 p = strrchr_m(root1,'.');
3076 if (p) {
3077 *p = 0;
3078 fstrcpy(ext1,p+1);
3079 } else {
3080 fstrcpy(ext1,"");
3082 p = strrchr_m(root2,'.');
3083 if (p) {
3084 *p = 0;
3085 fstrcpy(ext2,p+1);
3086 } else {
3087 fstrcpy(ext2,"");
3090 p = root1;
3091 p2 = root2;
3092 while (*p2) {
3093 if (*p2 == '?') {
3094 *p2 = *p;
3095 p2++;
3096 } else {
3097 p2++;
3099 if (*p) p++;
3102 p = ext1;
3103 p2 = ext2;
3104 while (*p2) {
3105 if (*p2 == '?') {
3106 *p2 = *p;
3107 p2++;
3108 } else {
3109 p2++;
3111 if (*p) p++;
3114 pstrcpy(name2,root2);
3115 if (ext2[0]) {
3116 pstrcat(name2,".");
3117 pstrcat(name2,ext2);
3120 return(True);
3123 /****************************************************************************
3124 The guts of the rename command, split out so it may be called by the NT SMB
3125 code.
3126 ****************************************************************************/
3128 NTSTATUS rename_internals(connection_struct *conn, char *name, char *newname, BOOL replace_if_exists)
3130 pstring directory;
3131 pstring mask;
3132 pstring newname_last_component;
3133 char *p;
3134 BOOL has_wild;
3135 BOOL bad_path1 = False;
3136 BOOL bad_path2 = False;
3137 int count=0;
3138 NTSTATUS error = NT_STATUS_OK;
3139 BOOL rc = True;
3140 SMB_STRUCT_STAT sbuf1, sbuf2;
3142 *directory = *mask = 0;
3144 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3145 unix_convert(newname,conn,newname_last_component,&bad_path2,&sbuf2);
3148 * Split the old name into directory and last component
3149 * strings. Note that unix_convert may have stripped off a
3150 * leading ./ from both name and newname if the rename is
3151 * at the root of the share. We need to make sure either both
3152 * name and newname contain a / character or neither of them do
3153 * as this is checked in resolve_wildcards().
3156 p = strrchr_m(name,'/');
3157 if (!p) {
3158 pstrcpy(directory,".");
3159 pstrcpy(mask,name);
3160 } else {
3161 *p = 0;
3162 pstrcpy(directory,name);
3163 pstrcpy(mask,p+1);
3164 *p = '/'; /* Replace needed for exceptional test below. */
3168 * We should only check the mangled cache
3169 * here if unix_convert failed. This means
3170 * that the path in 'mask' doesn't exist
3171 * on the file system and so we need to look
3172 * for a possible mangle. This patch from
3173 * Tine Smukavec <valentin.smukavec@hermes.si>.
3176 if (!rc && mangle_is_mangled(mask))
3177 mangle_check_cache( mask );
3179 has_wild = ms_has_wild(mask);
3181 if (!has_wild) {
3183 * No wildcards - just process the one file.
3185 BOOL is_short_name = mangle_is_8_3(name, True);
3187 /* Add a terminating '/' to the directory name. */
3188 pstrcat(directory,"/");
3189 pstrcat(directory,mask);
3191 /* Ensure newname contains a '/' also */
3192 if(strrchr_m(newname,'/') == 0) {
3193 pstring tmpstr;
3195 pstrcpy(tmpstr, "./");
3196 pstrcat(tmpstr, newname);
3197 pstrcpy(newname, tmpstr);
3200 DEBUG(3,("rename_internals: case_sensitive = %d, case_preserve = %d, short case preserve = %d, \
3201 directory = %s, newname = %s, newname_last_component = %s, is_8_3 = %d\n",
3202 case_sensitive, case_preserve, short_case_preserve, directory,
3203 newname, newname_last_component, is_short_name));
3206 * Check for special case with case preserving and not
3207 * case sensitive, if directory and newname are identical,
3208 * and the old last component differs from the original
3209 * last component only by case, then we should allow
3210 * the rename (user is trying to change the case of the
3211 * filename).
3213 if((case_sensitive == False) &&
3214 (((case_preserve == True) &&
3215 (is_short_name == False)) ||
3216 ((short_case_preserve == True) &&
3217 (is_short_name == True))) &&
3218 strcsequal(directory, newname)) {
3219 pstring newname_modified_last_component;
3222 * Get the last component of the modified name.
3223 * Note that we guarantee that newname contains a '/'
3224 * character above.
3226 p = strrchr_m(newname,'/');
3227 pstrcpy(newname_modified_last_component,p+1);
3229 if(strcsequal(newname_modified_last_component,
3230 newname_last_component) == False) {
3232 * Replace the modified last component with
3233 * the original.
3235 pstrcpy(p+1, newname_last_component);
3239 resolve_wildcards(directory,newname);
3242 * The source object must exist.
3245 if (!vfs_object_exist(conn, directory, &sbuf1)) {
3246 DEBUG(3,("rename_internals: source doesn't exist doing rename %s -> %s\n",
3247 directory,newname));
3249 if (errno == ENOTDIR || errno == EISDIR || errno == ENOENT) {
3251 * Must return different errors depending on whether the parent
3252 * directory existed or not.
3255 p = strrchr_m(directory, '/');
3256 if (!p)
3257 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3258 *p = '\0';
3259 if (vfs_object_exist(conn, directory, NULL))
3260 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3261 return NT_STATUS_OBJECT_PATH_NOT_FOUND;
3263 error = map_nt_error_from_unix(errno);
3264 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3265 nt_errstr(error), directory,newname));
3267 return error;
3270 error = can_rename(directory,conn,&sbuf1);
3272 if (!NT_STATUS_IS_OK(error)) {
3273 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3274 nt_errstr(error), directory,newname));
3275 return error;
3279 * If the src and dest names are identical - including case,
3280 * don't do the rename, just return success.
3283 if (strcsequal(directory, newname)) {
3284 DEBUG(3,("rename_internals: identical names in rename %s - returning success\n", directory));
3285 return NT_STATUS_OK;
3288 if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
3289 DEBUG(3,("rename_internals: dest exists doing rename %s -> %s\n",
3290 directory,newname));
3291 return NT_STATUS_OBJECT_NAME_COLLISION;
3294 if(conn->vfs_ops.rename(conn,directory, newname) == 0) {
3295 DEBUG(3,("rename_internals: succeeded doing rename on %s -> %s\n",
3296 directory,newname));
3297 return NT_STATUS_OK;
3300 if (errno == ENOTDIR || errno == EISDIR)
3301 error = NT_STATUS_OBJECT_NAME_COLLISION;
3302 else
3303 error = map_nt_error_from_unix(errno);
3305 DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
3306 nt_errstr(error), directory,newname));
3308 return error;
3309 } else {
3311 * Wildcards - process each file that matches.
3313 void *dirptr = NULL;
3314 char *dname;
3315 pstring destname;
3317 if (check_name(directory,conn))
3318 dirptr = OpenDir(conn, directory, True);
3320 if (dirptr) {
3321 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3323 if (strequal(mask,"????????.???"))
3324 pstrcpy(mask,"*");
3326 while ((dname = ReadDirName(dirptr))) {
3327 pstring fname;
3329 pstrcpy(fname,dname);
3331 if(!mask_match(fname, mask, case_sensitive))
3332 continue;
3334 error = NT_STATUS_ACCESS_DENIED;
3335 slprintf(fname,sizeof(fname)-1,"%s/%s",directory,dname);
3336 if (!vfs_object_exist(conn, fname, &sbuf1)) {
3337 error = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3338 DEBUG(6,("rename %s failed. Error %s\n", fname, nt_errstr(error)));
3339 continue;
3341 error = can_rename(fname,conn,&sbuf1);
3342 if (!NT_STATUS_IS_OK(error)) {
3343 DEBUG(6,("rename %s refused\n", fname));
3344 continue;
3346 pstrcpy(destname,newname);
3348 if (!resolve_wildcards(fname,destname)) {
3349 DEBUG(6,("resolve_wildcards %s %s failed\n",
3350 fname, destname));
3351 continue;
3354 if (!replace_if_exists &&
3355 vfs_file_exist(conn,destname, NULL)) {
3356 DEBUG(6,("file_exist %s\n", destname));
3357 error = NT_STATUS_OBJECT_NAME_COLLISION;
3358 continue;
3361 if (!conn->vfs_ops.rename(conn,fname,destname))
3362 count++;
3363 DEBUG(3,("rename_internals: doing rename on %s -> %s\n",fname,destname));
3365 CloseDir(dirptr);
3369 if (count == 0 && NT_STATUS_IS_OK(error)) {
3370 error = map_nt_error_from_unix(errno);
3373 return error;
3376 /****************************************************************************
3377 Reply to a mv.
3378 ****************************************************************************/
3380 int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
3381 int dum_buffsize)
3383 int outsize = 0;
3384 pstring name;
3385 pstring newname;
3386 char *p;
3387 NTSTATUS status;
3389 START_PROFILE(SMBmv);
3391 p = smb_buf(inbuf) + 1;
3392 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3393 p++;
3394 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3396 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3397 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3399 DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
3401 status = rename_internals(conn, name, newname, False);
3402 if (!NT_STATUS_IS_OK(status)) {
3403 return ERROR_NT(status);
3407 * Win2k needs a changenotify request response before it will
3408 * update after a rename..
3410 process_pending_change_notify_queue((time_t)0);
3411 outsize = set_message(outbuf,0,0,True);
3413 END_PROFILE(SMBmv);
3414 return(outsize);
3417 /*******************************************************************
3418 Copy a file as part of a reply_copy.
3419 ******************************************************************/
3421 static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
3422 int count,BOOL target_is_directory, int *err_ret)
3424 int Access,action;
3425 SMB_STRUCT_STAT src_sbuf, sbuf2;
3426 SMB_OFF_T ret=-1;
3427 files_struct *fsp1,*fsp2;
3428 pstring dest;
3430 *err_ret = 0;
3432 pstrcpy(dest,dest1);
3433 if (target_is_directory) {
3434 char *p = strrchr_m(src,'/');
3435 if (p)
3436 p++;
3437 else
3438 p = src;
3439 pstrcat(dest,"/");
3440 pstrcat(dest,p);
3443 if (!vfs_file_exist(conn,src,&src_sbuf))
3444 return(False);
3446 fsp1 = open_file_shared(conn,src,&src_sbuf,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_RDONLY),
3447 (FILE_FAIL_IF_NOT_EXIST|FILE_EXISTS_OPEN),0,0,&Access,&action);
3449 if (!fsp1)
3450 return(False);
3452 if (!target_is_directory && count)
3453 ofun = FILE_EXISTS_OPEN;
3455 if (vfs_stat(conn,dest,&sbuf2) == -1)
3456 ZERO_STRUCTP(&sbuf2);
3458 fsp2 = open_file_shared(conn,dest,&sbuf2,SET_DENY_MODE(DENY_NONE)|SET_OPEN_MODE(DOS_OPEN_WRONLY),
3459 ofun,src_sbuf.st_mode,0,&Access,&action);
3461 if (!fsp2) {
3462 close_file(fsp1,False);
3463 return(False);
3466 if ((ofun&3) == 1) {
3467 if(conn->vfs_ops.lseek(fsp2,fsp2->fd,0,SEEK_END) == -1) {
3468 DEBUG(0,("copy_file: error - vfs lseek returned error %s\n", strerror(errno) ));
3470 * Stop the copy from occurring.
3472 ret = -1;
3473 src_sbuf.st_size = 0;
3477 if (src_sbuf.st_size)
3478 ret = vfs_transfer_file(fsp1, fsp2, src_sbuf.st_size);
3480 close_file(fsp1,False);
3482 /* Ensure the modtime is set correctly on the destination file. */
3483 fsp2->pending_modtime = src_sbuf.st_mtime;
3486 * As we are opening fsp1 read-only we only expect
3487 * an error on close on fsp2 if we are out of space.
3488 * Thus we don't look at the error return from the
3489 * close of fsp1.
3491 *err_ret = close_file(fsp2,False);
3493 return(ret == (SMB_OFF_T)src_sbuf.st_size);
3496 /****************************************************************************
3497 Reply to a file copy.
3498 ****************************************************************************/
3500 int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3502 int outsize = 0;
3503 pstring name;
3504 pstring directory;
3505 pstring mask,newname;
3506 char *p;
3507 int count=0;
3508 int error = ERRnoaccess;
3509 int err = 0;
3510 BOOL has_wild;
3511 BOOL exists=False;
3512 int tid2 = SVAL(inbuf,smb_vwv0);
3513 int ofun = SVAL(inbuf,smb_vwv1);
3514 int flags = SVAL(inbuf,smb_vwv2);
3515 BOOL target_is_directory=False;
3516 BOOL bad_path1 = False;
3517 BOOL bad_path2 = False;
3518 BOOL rc = True;
3519 SMB_STRUCT_STAT sbuf1, sbuf2;
3520 START_PROFILE(SMBcopy);
3522 *directory = *mask = 0;
3524 p = smb_buf(inbuf);
3525 p += srvstr_pull_buf(inbuf, name, p, sizeof(name), STR_TERMINATE);
3526 p += srvstr_pull_buf(inbuf, newname, p, sizeof(newname), STR_TERMINATE);
3528 DEBUG(3,("reply_copy : %s -> %s\n",name,newname));
3530 if (tid2 != conn->cnum) {
3531 /* can't currently handle inter share copies XXXX */
3532 DEBUG(3,("Rejecting inter-share copy\n"));
3533 END_PROFILE(SMBcopy);
3534 return ERROR_DOS(ERRSRV,ERRinvdevice);
3537 RESOLVE_DFSPATH(name, conn, inbuf, outbuf);
3538 RESOLVE_DFSPATH(newname, conn, inbuf, outbuf);
3540 rc = unix_convert(name,conn,0,&bad_path1,&sbuf1);
3541 unix_convert(newname,conn,0,&bad_path2,&sbuf2);
3543 target_is_directory = VALID_STAT_OF_DIR(sbuf2);
3545 if ((flags&1) && target_is_directory) {
3546 END_PROFILE(SMBcopy);
3547 return ERROR_DOS(ERRDOS,ERRbadfile);
3550 if ((flags&2) && !target_is_directory) {
3551 END_PROFILE(SMBcopy);
3552 return ERROR_DOS(ERRDOS,ERRbadpath);
3555 if ((flags&(1<<5)) && VALID_STAT_OF_DIR(sbuf1)) {
3556 /* wants a tree copy! XXXX */
3557 DEBUG(3,("Rejecting tree copy\n"));
3558 END_PROFILE(SMBcopy);
3559 return ERROR_DOS(ERRSRV,ERRerror);
3562 p = strrchr_m(name,'/');
3563 if (!p) {
3564 pstrcpy(directory,"./");
3565 pstrcpy(mask,name);
3566 } else {
3567 *p = 0;
3568 pstrcpy(directory,name);
3569 pstrcpy(mask,p+1);
3573 * We should only check the mangled cache
3574 * here if unix_convert failed. This means
3575 * that the path in 'mask' doesn't exist
3576 * on the file system and so we need to look
3577 * for a possible mangle. This patch from
3578 * Tine Smukavec <valentin.smukavec@hermes.si>.
3581 if (!rc && mangle_is_mangled(mask))
3582 mangle_check_cache( mask );
3584 has_wild = ms_has_wild(mask);
3586 if (!has_wild) {
3587 pstrcat(directory,"/");
3588 pstrcat(directory,mask);
3589 if (resolve_wildcards(directory,newname) &&
3590 copy_file(directory,newname,conn,ofun,
3591 count,target_is_directory,&err)) count++;
3592 if(!count && err) {
3593 errno = err;
3594 END_PROFILE(SMBcopy);
3595 return(UNIXERROR(ERRHRD,ERRgeneral));
3597 if (!count) exists = vfs_file_exist(conn,directory,NULL);
3598 } else {
3599 void *dirptr = NULL;
3600 char *dname;
3601 pstring destname;
3603 if (check_name(directory,conn))
3604 dirptr = OpenDir(conn, directory, True);
3606 if (dirptr) {
3607 error = ERRbadfile;
3609 if (strequal(mask,"????????.???"))
3610 pstrcpy(mask,"*");
3612 while ((dname = ReadDirName(dirptr))) {
3613 pstring fname;
3614 pstrcpy(fname,dname);
3616 if(!mask_match(fname, mask, case_sensitive))
3617 continue;
3619 error = ERRnoaccess;
3620 slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
3621 pstrcpy(destname,newname);
3622 if (resolve_wildcards(fname,destname) &&
3623 copy_file(fname,destname,conn,ofun,
3624 count,target_is_directory,&err)) count++;
3625 DEBUG(3,("reply_copy : doing copy on %s -> %s\n",fname,destname));
3627 CloseDir(dirptr);
3631 if (count == 0) {
3632 if(err) {
3633 /* Error on close... */
3634 errno = err;
3635 END_PROFILE(SMBcopy);
3636 return(UNIXERROR(ERRHRD,ERRgeneral));
3639 if (exists) {
3640 END_PROFILE(SMBcopy);
3641 return ERROR_DOS(ERRDOS,error);
3642 } else
3644 if((errno == ENOENT) && (bad_path1 || bad_path2))
3646 unix_ERR_class = ERRDOS;
3647 unix_ERR_code = ERRbadpath;
3649 END_PROFILE(SMBcopy);
3650 return(UNIXERROR(ERRDOS,error));
3654 outsize = set_message(outbuf,1,0,True);
3655 SSVAL(outbuf,smb_vwv0,count);
3657 END_PROFILE(SMBcopy);
3658 return(outsize);
3661 /****************************************************************************
3662 Reply to a setdir.
3663 ****************************************************************************/
3665 int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
3667 int snum;
3668 int outsize = 0;
3669 BOOL ok = False;
3670 pstring newdir;
3671 START_PROFILE(pathworks_setdir);
3673 snum = SNUM(conn);
3674 if (!CAN_SETDIR(snum)) {
3675 END_PROFILE(pathworks_setdir);
3676 return ERROR_DOS(ERRDOS,ERRnoaccess);
3679 srvstr_pull_buf(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), STR_TERMINATE);
3681 if (strlen(newdir) == 0) {
3682 ok = True;
3683 } else {
3684 ok = vfs_directory_exist(conn,newdir,NULL);
3685 if (ok) {
3686 string_set(&conn->connectpath,newdir);
3690 if (!ok) {
3691 END_PROFILE(pathworks_setdir);
3692 return ERROR_DOS(ERRDOS,ERRbadpath);
3695 outsize = set_message(outbuf,0,0,True);
3696 SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
3698 DEBUG(3,("setdir %s\n", newdir));
3700 END_PROFILE(pathworks_setdir);
3701 return(outsize);
3704 /****************************************************************************
3705 Get a lock pid, dealing with large count requests.
3706 ****************************************************************************/
3708 uint16 get_lock_pid( char *data, int data_offset, BOOL large_file_format)
3710 if(!large_file_format)
3711 return SVAL(data,SMB_LPID_OFFSET(data_offset));
3712 else
3713 return SVAL(data,SMB_LARGE_LPID_OFFSET(data_offset));
3716 /****************************************************************************
3717 Get a lock count, dealing with large count requests.
3718 ****************************************************************************/
3720 SMB_BIG_UINT get_lock_count( char *data, int data_offset, BOOL large_file_format)
3722 SMB_BIG_UINT count = 0;
3724 if(!large_file_format) {
3725 count = (SMB_BIG_UINT)IVAL(data,SMB_LKLEN_OFFSET(data_offset));
3726 } else {
3728 #if defined(HAVE_LONGLONG)
3729 count = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset))) << 32) |
3730 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)));
3731 #else /* HAVE_LONGLONG */
3734 * NT4.x seems to be broken in that it sends large file (64 bit)
3735 * lockingX calls even if the CAP_LARGE_FILES was *not*
3736 * negotiated. For boxes without large unsigned ints truncate the
3737 * lock count by dropping the top 32 bits.
3740 if(IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)) != 0) {
3741 DEBUG(3,("get_lock_count: truncating lock count (high)0x%x (low)0x%x to just low count.\n",
3742 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset)),
3743 (unsigned int)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset)) ));
3744 SIVAL(data,SMB_LARGE_LKLEN_OFFSET_HIGH(data_offset),0);
3747 count = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKLEN_OFFSET_LOW(data_offset));
3748 #endif /* HAVE_LONGLONG */
3751 return count;
3754 #if !defined(HAVE_LONGLONG)
3755 /****************************************************************************
3756 Pathetically try and map a 64 bit lock offset into 31 bits. I hate Windows :-).
3757 ****************************************************************************/
3759 static uint32 map_lock_offset(uint32 high, uint32 low)
3761 unsigned int i;
3762 uint32 mask = 0;
3763 uint32 highcopy = high;
3766 * Try and find out how many significant bits there are in high.
3769 for(i = 0; highcopy; i++)
3770 highcopy >>= 1;
3773 * We use 31 bits not 32 here as POSIX
3774 * lock offsets may not be negative.
3777 mask = (~0) << (31 - i);
3779 if(low & mask)
3780 return 0; /* Fail. */
3782 high <<= (31 - i);
3784 return (high|low);
3786 #endif /* !defined(HAVE_LONGLONG) */
3788 /****************************************************************************
3789 Get a lock offset, dealing with large offset requests.
3790 ****************************************************************************/
3792 SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_format, BOOL *err)
3794 SMB_BIG_UINT offset = 0;
3796 *err = False;
3798 if(!large_file_format) {
3799 offset = (SMB_BIG_UINT)IVAL(data,SMB_LKOFF_OFFSET(data_offset));
3800 } else {
3802 #if defined(HAVE_LONGLONG)
3803 offset = (((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset))) << 32) |
3804 ((SMB_BIG_UINT) IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset)));
3805 #else /* HAVE_LONGLONG */
3808 * NT4.x seems to be broken in that it sends large file (64 bit)
3809 * lockingX calls even if the CAP_LARGE_FILES was *not*
3810 * negotiated. For boxes without large unsigned ints mangle the
3811 * lock offset by mapping the top 32 bits onto the lower 32.
3814 if(IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset)) != 0) {
3815 uint32 low = IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3816 uint32 high = IVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset));
3817 uint32 new_low = 0;
3819 if((new_low = map_lock_offset(high, low)) == 0) {
3820 *err = True;
3821 return (SMB_BIG_UINT)-1;
3824 DEBUG(3,("get_lock_offset: truncating lock offset (high)0x%x (low)0x%x to offset 0x%x.\n",
3825 (unsigned int)high, (unsigned int)low, (unsigned int)new_low ));
3826 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_HIGH(data_offset),0);
3827 SIVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset),new_low);
3830 offset = (SMB_BIG_UINT)IVAL(data,SMB_LARGE_LKOFF_OFFSET_LOW(data_offset));
3831 #endif /* HAVE_LONGLONG */
3834 return offset;
3837 /****************************************************************************
3838 Reply to a lockingX request.
3839 ****************************************************************************/
3841 int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
3843 files_struct *fsp = file_fsp(inbuf,smb_vwv2);
3844 unsigned char locktype = CVAL(inbuf,smb_vwv3);
3845 unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
3846 uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
3847 uint16 num_locks = SVAL(inbuf,smb_vwv7);
3848 SMB_BIG_UINT count = 0, offset = 0;
3849 uint16 lock_pid;
3850 int32 lock_timeout = IVAL(inbuf,smb_vwv4);
3851 int i;
3852 char *data;
3853 BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False;
3854 BOOL err;
3855 NTSTATUS status;
3857 START_PROFILE(SMBlockingX);
3859 CHECK_FSP(fsp,conn);
3861 data = smb_buf(inbuf);
3863 if (locktype & (LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_CHANGE_LOCKTYPE)) {
3864 /* we don't support these - and CANCEL_LOCK makes w2k
3865 and XP reboot so I don't really want to be
3866 compatible! (tridge) */
3867 return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
3870 /* Check if this is an oplock break on a file
3871 we have granted an oplock on.
3873 if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) {
3874 /* Client can insist on breaking to none. */
3875 BOOL break_to_none = (oplocklevel == 0);
3877 DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n",
3878 (unsigned int)oplocklevel, fsp->fnum ));
3881 * Make sure we have granted an exclusive or batch oplock on this file.
3884 if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
3885 DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
3886 no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name));
3888 /* if this is a pure oplock break request then don't send a reply */
3889 if (num_locks == 0 && num_ulocks == 0) {
3890 END_PROFILE(SMBlockingX);
3891 return -1;
3892 } else {
3893 END_PROFILE(SMBlockingX);
3894 return ERROR_DOS(ERRDOS,ERRlock);
3898 if (remove_oplock(fsp, break_to_none) == False) {
3899 DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n",
3900 fsp->fsp_name ));
3903 /* if this is a pure oplock break request then don't send a reply */
3904 if (num_locks == 0 && num_ulocks == 0) {
3905 /* Sanity check - ensure a pure oplock break is not a
3906 chained request. */
3907 if(CVAL(inbuf,smb_vwv0) != 0xff)
3908 DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
3909 (unsigned int)CVAL(inbuf,smb_vwv0) ));
3910 END_PROFILE(SMBlockingX);
3911 return -1;
3916 * We do this check *after* we have checked this is not a oplock break
3917 * response message. JRA.
3920 release_level_2_oplocks_on_change(fsp);
3922 /* Data now points at the beginning of the list
3923 of smb_unlkrng structs */
3924 for(i = 0; i < (int)num_ulocks; i++) {
3925 lock_pid = get_lock_pid( data, i, large_file_format);
3926 count = get_lock_count( data, i, large_file_format);
3927 offset = get_lock_offset( data, i, large_file_format, &err);
3930 * There is no error code marked "stupid client bug".... :-).
3932 if(err) {
3933 END_PROFILE(SMBlockingX);
3934 return ERROR_DOS(ERRDOS,ERRnoaccess);
3937 DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n",
3938 (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name ));
3940 status = do_unlock(fsp,conn,lock_pid,count,offset);
3941 if (NT_STATUS_V(status)) {
3942 END_PROFILE(SMBlockingX);
3943 return ERROR_NT(status);
3947 /* Setup the timeout in seconds. */
3949 lock_timeout = ((lock_timeout == -1) ? -1 : (lock_timeout+999)/1000);
3951 /* Now do any requested locks */
3952 data += ((large_file_format ? 20 : 10)*num_ulocks);
3954 /* Data now points at the beginning of the list
3955 of smb_lkrng structs */
3957 for(i = 0; i < (int)num_locks; i++) {
3958 lock_pid = get_lock_pid( data, i, large_file_format);
3959 count = get_lock_count( data, i, large_file_format);
3960 offset = get_lock_offset( data, i, large_file_format, &err);
3963 * There is no error code marked "stupid client bug".... :-).
3965 if(err) {
3966 END_PROFILE(SMBlockingX);
3967 return ERROR_DOS(ERRDOS,ERRnoaccess);
3970 DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n",
3971 (double)offset, (double)count, (unsigned int)lock_pid,
3972 fsp->fsp_name, (int)lock_timeout ));
3974 status = do_lock_spin(fsp,conn,lock_pid, count,offset,
3975 ((locktype & 1) ? READ_LOCK : WRITE_LOCK));
3976 if (NT_STATUS_V(status)) {
3977 if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) {
3979 * A blocking lock was requested. Package up
3980 * this smb into a queued request and push it
3981 * onto the blocking lock queue.
3983 if(push_blocking_lock_request(inbuf, length, lock_timeout, i)) {
3984 END_PROFILE(SMBlockingX);
3985 return -1;
3988 break;
3992 /* If any of the above locks failed, then we must unlock
3993 all of the previous locks (X/Open spec). */
3994 if (i != num_locks && num_locks != 0) {
3996 * Ensure we don't do a remove on the lock that just failed,
3997 * as under POSIX rules, if we have a lock already there, we
3998 * will delete it (and we shouldn't) .....
4000 for(i--; i >= 0; i--) {
4001 lock_pid = get_lock_pid( data, i, large_file_format);
4002 count = get_lock_count( data, i, large_file_format);
4003 offset = get_lock_offset( data, i, large_file_format, &err);
4006 * There is no error code marked "stupid client bug".... :-).
4008 if(err) {
4009 END_PROFILE(SMBlockingX);
4010 return ERROR_DOS(ERRDOS,ERRnoaccess);
4013 do_unlock(fsp,conn,lock_pid,count,offset);
4015 END_PROFILE(SMBlockingX);
4016 return ERROR_NT(status);
4019 set_message(outbuf,2,0,True);
4021 DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
4022 fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) );
4024 END_PROFILE(SMBlockingX);
4025 return chain_reply(inbuf,outbuf,length,bufsize);
4028 /****************************************************************************
4029 Reply to a SMBreadbmpx (read block multiplex) request.
4030 ****************************************************************************/
4032 int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
4034 ssize_t nread = -1;
4035 ssize_t total_read;
4036 char *data;
4037 SMB_OFF_T startpos;
4038 int outsize;
4039 size_t maxcount;
4040 int max_per_packet;
4041 size_t tcount;
4042 int pad;
4043 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4044 START_PROFILE(SMBreadBmpx);
4046 /* this function doesn't seem to work - disable by default */
4047 if (!lp_readbmpx()) {
4048 END_PROFILE(SMBreadBmpx);
4049 return ERROR_DOS(ERRSRV,ERRuseSTD);
4052 outsize = set_message(outbuf,8,0,True);
4054 CHECK_FSP(fsp,conn);
4055 CHECK_READ(fsp);
4057 startpos = IVAL(inbuf,smb_vwv1);
4058 maxcount = SVAL(inbuf,smb_vwv3);
4060 data = smb_buf(outbuf);
4061 pad = ((long)data)%4;
4062 if (pad)
4063 pad = 4 - pad;
4064 data += pad;
4066 max_per_packet = bufsize-(outsize+pad);
4067 tcount = maxcount;
4068 total_read = 0;
4070 if (is_locked(fsp,conn,(SMB_BIG_UINT)maxcount,(SMB_BIG_UINT)startpos, READ_LOCK,False)) {
4071 END_PROFILE(SMBreadBmpx);
4072 return ERROR_DOS(ERRDOS,ERRlock);
4075 do {
4076 size_t N = MIN(max_per_packet,tcount-total_read);
4078 nread = read_file(fsp,data,startpos,N);
4080 if (nread <= 0)
4081 nread = 0;
4083 if (nread < (ssize_t)N)
4084 tcount = total_read + nread;
4086 set_message(outbuf,8,nread,False);
4087 SIVAL(outbuf,smb_vwv0,startpos);
4088 SSVAL(outbuf,smb_vwv2,tcount);
4089 SSVAL(outbuf,smb_vwv6,nread);
4090 SSVAL(outbuf,smb_vwv7,smb_offset(data,outbuf));
4092 if (!send_smb(smbd_server_fd(),outbuf))
4093 exit_server("reply_readbmpx: send_smb failed.");
4095 total_read += nread;
4096 startpos += nread;
4097 } while (total_read < (ssize_t)tcount);
4099 END_PROFILE(SMBreadBmpx);
4100 return(-1);
4103 /****************************************************************************
4104 Reply to a SMBsetattrE.
4105 ****************************************************************************/
4107 int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4109 struct utimbuf unix_times;
4110 int outsize = 0;
4111 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4112 START_PROFILE(SMBsetattrE);
4114 outsize = set_message(outbuf,0,0,True);
4116 if(!fsp || (fsp->conn != conn)) {
4117 END_PROFILE(SMBgetattrE);
4118 return ERROR_DOS(ERRDOS,ERRbadfid);
4122 * Convert the DOS times into unix times. Ignore create
4123 * time as UNIX can't set this.
4126 unix_times.actime = make_unix_date2(inbuf+smb_vwv3);
4127 unix_times.modtime = make_unix_date2(inbuf+smb_vwv5);
4130 * Patch from Ray Frush <frush@engr.colostate.edu>
4131 * Sometimes times are sent as zero - ignore them.
4134 if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
4135 /* Ignore request */
4136 if( DEBUGLVL( 3 ) ) {
4137 dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
4138 dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
4140 END_PROFILE(SMBsetattrE);
4141 return(outsize);
4142 } else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
4143 /* set modify time = to access time if modify time was 0 */
4144 unix_times.modtime = unix_times.actime;
4147 /* Set the date on this file */
4148 if(file_utime(conn, fsp->fsp_name, &unix_times)) {
4149 END_PROFILE(SMBsetattrE);
4150 return ERROR_DOS(ERRDOS,ERRnoaccess);
4153 DEBUG( 3, ( "reply_setattrE fnum=%d actime=%d modtime=%d\n",
4154 fsp->fnum, (int)unix_times.actime, (int)unix_times.modtime ) );
4156 END_PROFILE(SMBsetattrE);
4157 return(outsize);
4161 /* Back from the dead for OS/2..... JRA. */
4163 /****************************************************************************
4164 Reply to a SMBwritebmpx (write block multiplex primary) request.
4165 ****************************************************************************/
4167 int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4169 size_t numtowrite;
4170 ssize_t nwritten = -1;
4171 int outsize = 0;
4172 SMB_OFF_T startpos;
4173 size_t tcount;
4174 BOOL write_through;
4175 int smb_doff;
4176 char *data;
4177 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4178 START_PROFILE(SMBwriteBmpx);
4180 CHECK_FSP(fsp,conn);
4181 CHECK_WRITE(fsp);
4182 CHECK_ERROR(fsp);
4184 tcount = SVAL(inbuf,smb_vwv1);
4185 startpos = IVAL(inbuf,smb_vwv3);
4186 write_through = BITSETW(inbuf+smb_vwv7,0);
4187 numtowrite = SVAL(inbuf,smb_vwv10);
4188 smb_doff = SVAL(inbuf,smb_vwv11);
4190 data = smb_base(inbuf) + smb_doff;
4192 /* If this fails we need to send an SMBwriteC response,
4193 not an SMBwritebmpx - set this up now so we don't forget */
4194 SCVAL(outbuf,smb_com,SMBwritec);
4196 if (is_locked(fsp,conn,(SMB_BIG_UINT)tcount,(SMB_BIG_UINT)startpos,WRITE_LOCK,False)) {
4197 END_PROFILE(SMBwriteBmpx);
4198 return(ERROR_DOS(ERRDOS,ERRlock));
4201 nwritten = write_file(fsp,data,startpos,numtowrite);
4203 if(lp_syncalways(SNUM(conn)) || write_through)
4204 sync_file(conn,fsp);
4206 if(nwritten < (ssize_t)numtowrite) {
4207 END_PROFILE(SMBwriteBmpx);
4208 return(UNIXERROR(ERRHRD,ERRdiskfull));
4211 /* If the maximum to be written to this file
4212 is greater than what we just wrote then set
4213 up a secondary struct to be attached to this
4214 fd, we will use this to cache error messages etc. */
4216 if((ssize_t)tcount > nwritten) {
4217 write_bmpx_struct *wbms;
4218 if(fsp->wbmpx_ptr != NULL)
4219 wbms = fsp->wbmpx_ptr; /* Use an existing struct */
4220 else
4221 wbms = (write_bmpx_struct *)malloc(sizeof(write_bmpx_struct));
4222 if(!wbms) {
4223 DEBUG(0,("Out of memory in reply_readmpx\n"));
4224 END_PROFILE(SMBwriteBmpx);
4225 return(ERROR_DOS(ERRSRV,ERRnoresource));
4227 wbms->wr_mode = write_through;
4228 wbms->wr_discard = False; /* No errors yet */
4229 wbms->wr_total_written = nwritten;
4230 wbms->wr_errclass = 0;
4231 wbms->wr_error = 0;
4232 fsp->wbmpx_ptr = wbms;
4235 /* We are returning successfully, set the message type back to
4236 SMBwritebmpx */
4237 SCVAL(outbuf,smb_com,SMBwriteBmpx);
4239 outsize = set_message(outbuf,1,0,True);
4241 SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
4243 DEBUG( 3, ( "writebmpx fnum=%d num=%d wrote=%d\n",
4244 fsp->fnum, (int)numtowrite, (int)nwritten ) );
4246 if (write_through && tcount==nwritten) {
4247 /* We need to send both a primary and a secondary response */
4248 smb_setlen(outbuf,outsize - 4);
4249 if (!send_smb(smbd_server_fd(),outbuf))
4250 exit_server("reply_writebmpx: send_smb failed.");
4252 /* Now the secondary */
4253 outsize = set_message(outbuf,1,0,True);
4254 SCVAL(outbuf,smb_com,SMBwritec);
4255 SSVAL(outbuf,smb_vwv0,nwritten);
4258 END_PROFILE(SMBwriteBmpx);
4259 return(outsize);
4262 /****************************************************************************
4263 Reply to a SMBwritebs (write block multiplex secondary) request.
4264 ****************************************************************************/
4266 int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
4268 size_t numtowrite;
4269 ssize_t nwritten = -1;
4270 int outsize = 0;
4271 SMB_OFF_T startpos;
4272 size_t tcount;
4273 BOOL write_through;
4274 int smb_doff;
4275 char *data;
4276 write_bmpx_struct *wbms;
4277 BOOL send_response = False;
4278 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4279 START_PROFILE(SMBwriteBs);
4281 CHECK_FSP(fsp,conn);
4282 CHECK_WRITE(fsp);
4284 tcount = SVAL(inbuf,smb_vwv1);
4285 startpos = IVAL(inbuf,smb_vwv2);
4286 numtowrite = SVAL(inbuf,smb_vwv6);
4287 smb_doff = SVAL(inbuf,smb_vwv7);
4289 data = smb_base(inbuf) + smb_doff;
4291 /* We need to send an SMBwriteC response, not an SMBwritebs */
4292 SCVAL(outbuf,smb_com,SMBwritec);
4294 /* This fd should have an auxiliary struct attached,
4295 check that it does */
4296 wbms = fsp->wbmpx_ptr;
4297 if(!wbms) {
4298 END_PROFILE(SMBwriteBs);
4299 return(-1);
4302 /* If write through is set we can return errors, else we must cache them */
4303 write_through = wbms->wr_mode;
4305 /* Check for an earlier error */
4306 if(wbms->wr_discard) {
4307 END_PROFILE(SMBwriteBs);
4308 return -1; /* Just discard the packet */
4311 nwritten = write_file(fsp,data,startpos,numtowrite);
4313 if(lp_syncalways(SNUM(conn)) || write_through)
4314 sync_file(conn,fsp);
4316 if (nwritten < (ssize_t)numtowrite) {
4317 if(write_through) {
4318 /* We are returning an error - we can delete the aux struct */
4319 if (wbms)
4320 free((char *)wbms);
4321 fsp->wbmpx_ptr = NULL;
4322 END_PROFILE(SMBwriteBs);
4323 return(ERROR_DOS(ERRHRD,ERRdiskfull));
4325 END_PROFILE(SMBwriteBs);
4326 return(CACHE_ERROR(wbms,ERRHRD,ERRdiskfull));
4329 /* Increment the total written, if this matches tcount
4330 we can discard the auxiliary struct (hurrah !) and return a writeC */
4331 wbms->wr_total_written += nwritten;
4332 if(wbms->wr_total_written >= tcount) {
4333 if (write_through) {
4334 outsize = set_message(outbuf,1,0,True);
4335 SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
4336 send_response = True;
4339 free((char *)wbms);
4340 fsp->wbmpx_ptr = NULL;
4343 if(send_response) {
4344 END_PROFILE(SMBwriteBs);
4345 return(outsize);
4348 END_PROFILE(SMBwriteBs);
4349 return(-1);
4352 /****************************************************************************
4353 Reply to a SMBgetattrE.
4354 ****************************************************************************/
4356 int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
4358 SMB_STRUCT_STAT sbuf;
4359 int outsize = 0;
4360 int mode;
4361 files_struct *fsp = file_fsp(inbuf,smb_vwv0);
4362 START_PROFILE(SMBgetattrE);
4364 outsize = set_message(outbuf,11,0,True);
4366 if(!fsp || (fsp->conn != conn)) {
4367 END_PROFILE(SMBgetattrE);
4368 return ERROR_DOS(ERRDOS,ERRbadfid);
4371 /* Do an fstat on this file */
4372 if(fsp_stat(fsp, &sbuf)) {
4373 END_PROFILE(SMBgetattrE);
4374 return(UNIXERROR(ERRDOS,ERRnoaccess));
4377 mode = dos_mode(conn,fsp->fsp_name,&sbuf);
4380 * Convert the times into dos times. Set create
4381 * date to be last modify date as UNIX doesn't save
4382 * this.
4385 put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
4386 put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
4387 put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
4389 if (mode & aDIR) {
4390 SIVAL(outbuf,smb_vwv6,0);
4391 SIVAL(outbuf,smb_vwv8,0);
4392 } else {
4393 SIVAL(outbuf,smb_vwv6,(uint32)sbuf.st_size);
4394 SIVAL(outbuf,smb_vwv8,SMB_ROUNDUP(sbuf.st_size,1024));
4396 SSVAL(outbuf,smb_vwv10, mode);
4398 DEBUG( 3, ( "reply_getattrE fnum=%d\n", fsp->fnum));
4400 END_PROFILE(SMBgetattrE);
4401 return(outsize);