oops, I ot the return type of putenv() wrong
[Samba/gbeck.git] / source / smbd / open.c
blob311c494a97cf129a1ac517082b3278b4724df7f2
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 file opening and share modes
5 Copyright (C) Andrew Tridgell 1992-1998
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 #include "includes.h"
24 extern int DEBUGLEVEL;
26 extern pstring sesssetup_user;
27 extern uint16 global_oplock_port;
30 /****************************************************************************
31 fd support routines - attempt to do a dos_open
32 ****************************************************************************/
33 static int fd_attempt_open(char *fname, int flags, mode_t mode)
35 int fd = dos_open(fname,flags,mode);
37 /* Fix for files ending in '.' */
38 if((fd == -1) && (errno == ENOENT) &&
39 (strchr(fname,'.')==NULL))
41 pstrcat(fname,".");
42 fd = dos_open(fname,flags,mode);
45 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
46 if ((fd == -1) && (errno == ENAMETOOLONG))
48 int max_len;
49 char *p = strrchr(fname, '/');
51 if (p == fname) /* name is "/xxx" */
53 max_len = pathconf("/", _PC_NAME_MAX);
54 p++;
56 else if ((p == NULL) || (p == fname))
58 p = fname;
59 max_len = pathconf(".", _PC_NAME_MAX);
61 else
63 *p = '\0';
64 max_len = pathconf(fname, _PC_NAME_MAX);
65 *p = '/';
66 p++;
68 if (strlen(p) > max_len)
70 char tmp = p[max_len];
72 p[max_len] = '\0';
73 if ((fd = dos_open(fname,flags,mode)) == -1)
74 p[max_len] = tmp;
77 #endif
78 return fd;
81 /****************************************************************************
82 Cache a uid_t currently with this file open. This is an optimization only
83 used when multiple sessionsetup's have been done to one smbd.
84 ****************************************************************************/
85 void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u)
87 if(fd_ptr->uid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t))
88 return;
89 fd_ptr->uid_users_cache[fd_ptr->uid_cache_count++] = u;
92 /****************************************************************************
93 Remove a uid_t that currently has this file open. This is an optimization only
94 used when multiple sessionsetup's have been done to one smbd.
95 ****************************************************************************/
96 static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u)
98 int i;
99 for(i = 0; i < fd_ptr->uid_cache_count; i++)
100 if(fd_ptr->uid_users_cache[i] == u) {
101 if(i < (fd_ptr->uid_cache_count-1))
102 memmove((char *)&fd_ptr->uid_users_cache[i], (char *)&fd_ptr->uid_users_cache[i+1],
103 sizeof(uid_t)*(fd_ptr->uid_cache_count-1-i) );
104 fd_ptr->uid_cache_count--;
106 return;
109 /****************************************************************************
110 Check if a uid_t that currently has this file open is present. This is an
111 optimization only used when multiple sessionsetup's have been done to one smbd.
112 ****************************************************************************/
113 static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u)
115 int i;
116 for(i = 0; i < fd_ptr->uid_cache_count; i++)
117 if(fd_ptr->uid_users_cache[i] == u)
118 return True;
119 return False;
123 /****************************************************************************
124 fd support routines - attempt to re-open an already open fd as O_RDWR.
125 Save the already open fd (we cannot close due to POSIX file locking braindamage.
126 ****************************************************************************/
127 static void fd_attempt_reopen(char *fname, mode_t mode, file_fd_struct *fd_ptr)
129 int fd = dos_open( fname, O_RDWR, mode);
131 if(fd == -1)
132 return;
134 if(fd_ptr->real_open_flags == O_RDONLY)
135 fd_ptr->fd_readonly = fd_ptr->fd;
136 if(fd_ptr->real_open_flags == O_WRONLY)
137 fd_ptr->fd_writeonly = fd_ptr->fd;
139 fd_ptr->fd = fd;
140 fd_ptr->real_open_flags = O_RDWR;
143 /****************************************************************************
144 fd support routines - attempt to close the file referenced by this fd.
145 Decrements the ref_count and returns it.
146 ****************************************************************************/
147 uint16 fd_attempt_close(file_fd_struct *fd_ptr)
149 extern struct current_user current_user;
150 uint16 ret_ref = fd_ptr->ref_count;
152 DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %.0f, open_flags = %d, ref_count = %d.\n",
153 fd_ptr->fd, (unsigned int)fd_ptr->dev, (double)fd_ptr->inode,
154 fd_ptr->real_open_flags,
155 fd_ptr->ref_count));
157 SMB_ASSERT(fd_ptr->ref_count != 0);
159 fd_ptr->ref_count--;
160 ret_ref = fd_ptr->ref_count;
162 if(fd_ptr->ref_count == 0) {
163 if(fd_ptr->fd != -1)
164 close(fd_ptr->fd);
165 if(fd_ptr->fd_readonly != -1)
166 close(fd_ptr->fd_readonly);
167 if(fd_ptr->fd_writeonly != -1)
168 close(fd_ptr->fd_writeonly);
170 * Delete this fd_ptr.
172 fd_ptr_free(fd_ptr);
173 } else {
174 fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
177 return ret_ref;
180 /****************************************************************************
181 fd support routines - check that current user has permissions
182 to open this file. Used when uid not found in optimization cache.
183 This is really ugly code, as due to POSIX locking braindamage we must
184 fork and then attempt to open the file, and return success or failure
185 via an exit code.
186 ****************************************************************************/
187 static BOOL check_access_allowed_for_current_user( char *fname, int accmode )
189 pid_t child_pid;
191 if((child_pid = fork()) < 0) {
192 DEBUG(0,("check_access_allowed_for_current_user: fork failed.\n"));
193 return False;
196 if(child_pid) {
198 * Parent.
200 pid_t wpid;
201 int status_code;
202 if ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) {
203 DEBUG(0,("check_access_allowed_for_current_user: The process is no longer waiting!\n"));
204 return(False);
207 if (child_pid != wpid) {
208 DEBUG(0,("check_access_allowed_for_current_user: We were waiting for the wrong process ID\n"));
209 return(False);
211 #if defined(WIFEXITED) && defined(WEXITSTATUS)
212 if (WIFEXITED(status_code) == 0) {
213 DEBUG(0,("check_access_allowed_for_current_user: The process exited while we were waiting\n"));
214 return(False);
216 if (WEXITSTATUS(status_code) != 0) {
217 DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code));
218 return(False);
220 #else /* defined(WIFEXITED) && defined(WEXITSTATUS) */
221 if(status_code != 0) {
222 DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code));
223 return(False);
225 #endif /* defined(WIFEXITED) && defined(WEXITSTATUS) */
228 * Success - the child could open the file.
230 DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access allowed.\n", status_code));
231 return True;
232 } else {
234 * Child.
236 int fd;
237 DEBUG(9,("check_access_allowed_for_current_user: Child - attempting to open %s with mode %d.\n", fname, accmode ));
238 if((fd = fd_attempt_open( fname, accmode, 0)) < 0) {
239 /* Access denied. */
240 _exit(EACCES);
242 close(fd);
243 DEBUG(9,("check_access_allowed_for_current_user: Child - returning ok.\n"));
244 _exit(0);
247 return False;
250 /****************************************************************************
251 check a filename for the pipe string
252 ****************************************************************************/
253 static void check_for_pipe(char *fname)
255 /* special case of pipe opens */
256 char s[10];
257 StrnCpy(s,fname,9);
258 strlower(s);
259 if (strstr(s,"pipe/")) {
260 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
261 unix_ERR_class = ERRSRV;
262 unix_ERR_code = ERRaccess;
266 /****************************************************************************
267 open a file
268 ****************************************************************************/
269 static void open_file(files_struct *fsp,connection_struct *conn,
270 char *fname1,int flags,mode_t mode, SMB_STRUCT_STAT *sbuf)
272 extern struct current_user current_user;
273 pstring fname;
274 SMB_STRUCT_STAT statbuf;
275 file_fd_struct *fd_ptr;
276 int accmode = (flags & O_ACCMODE);
278 fsp->open = False;
279 fsp->fd_ptr = 0;
280 fsp->granted_oplock = False;
281 errno = EPERM;
283 pstrcpy(fname,fname1);
285 /* check permissions */
288 * This code was changed after seeing a client open request
289 * containing the open mode of (DENY_WRITE/read-only) with
290 * the 'create if not exist' bit set. The previous code
291 * would fail to open the file read only on a read-only share
292 * as it was checking the flags parameter directly against O_RDONLY,
293 * this was failing as the flags parameter was set to O_RDONLY|O_CREAT.
294 * JRA.
297 if (conn->read_only && !conn->printer) {
298 /* It's a read-only share - fail if we wanted to write. */
299 if(accmode != O_RDONLY) {
300 DEBUG(3,("Permission denied opening %s\n",fname));
301 check_for_pipe(fname);
302 return;
303 } else if(flags & O_CREAT) {
304 /* We don't want to write - but we must make sure that O_CREAT
305 doesn't create the file if we have write access into the
306 directory.
308 flags &= ~O_CREAT;
312 /* this handles a bug in Win95 - it doesn't say to create the file when it
313 should */
314 if (conn->printer) {
315 flags |= O_CREAT;
319 if (flags == O_WRONLY)
320 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
324 * Ensure we have a valid struct stat so we can search the
325 * open fd table.
327 if(sbuf == 0) {
328 if(dos_stat(fname, &statbuf) < 0) {
329 if(errno != ENOENT) {
330 DEBUG(3,("Error doing stat on file %s (%s)\n",
331 fname,strerror(errno)));
333 check_for_pipe(fname);
334 return;
336 sbuf = 0;
337 } else {
338 sbuf = &statbuf;
343 * Check to see if we have this file already
344 * open. If we do, just use the already open fd and increment the
345 * reference count (fd_get_already_open increments the ref_count).
347 if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
349 * File was already open.
353 * Check it wasn't open for exclusive use.
355 if((flags & O_CREAT) && (flags & O_EXCL)) {
356 fd_ptr->ref_count--;
357 errno = EEXIST;
358 return;
362 * Ensure that the user attempting to open
363 * this file has permissions to do so, if
364 * the user who originally opened the file wasn't
365 * the same as the current user.
368 if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) {
369 if(!check_access_allowed_for_current_user( fname, accmode )) {
370 /* Error - permission denied. */
371 DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n",
372 fname, flags, accmode));
373 /* Ensure the ref_count is decremented. */
374 fd_ptr->ref_count--;
375 fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
376 errno = EACCES;
377 return;
381 fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid);
384 * If not opened O_RDWR try
385 * and do that here - a chmod may have been done
386 * between the last open and now.
388 if(fd_ptr->real_open_flags != O_RDWR)
389 fd_attempt_reopen(fname, mode, fd_ptr);
392 * Ensure that if we wanted write access
393 * it has been opened for write, and if we wanted read it
394 * was open for read.
396 if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
397 ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
398 ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
399 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
400 fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
401 check_for_pipe(fname);
402 fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
403 fd_ptr->ref_count--;
404 return;
407 } else {
408 int open_flags;
409 /* We need to allocate a new file_fd_struct (this increments the
410 ref_count). */
411 if((fd_ptr = fd_get_new()) == 0)
412 return;
414 * Whatever the requested flags, attempt read/write access,
415 * as we don't know what flags future file opens may require.
416 * If this fails, try again with the required flags.
417 * Even if we open read/write when only read access was
418 * requested the setting of the can_write flag in
419 * the file_struct will protect us from errant
420 * write requests. We never need to worry about O_APPEND
421 * as this is not set anywhere in Samba.
423 fd_ptr->real_open_flags = O_RDWR;
424 /* Set the flags as needed without the read/write modes. */
425 open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
426 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
428 * On some systems opening a file for R/W access on a read only
429 * filesystems sets errno to EROFS.
431 #ifdef EROFS
432 if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
433 #else /* No EROFS */
434 if((fd_ptr->fd == -1) && (errno == EACCES)) {
435 #endif /* EROFS */
436 if(accmode != O_RDWR) {
437 fd_ptr->fd = fd_attempt_open(fname, open_flags|accmode, mode);
438 fd_ptr->real_open_flags = accmode;
443 if ((fd_ptr->fd >=0) &&
444 conn->printer && lp_minprintspace(SNUM(conn))) {
445 pstring dname;
446 SMB_BIG_UINT dum1,dum2,dum3;
447 char *p;
448 pstrcpy(dname,fname);
449 p = strrchr(dname,'/');
450 if (p) *p = 0;
451 if (sys_disk_free(dname,&dum1,&dum2,&dum3) < (SMB_BIG_UINT)lp_minprintspace(SNUM(conn))) {
452 if(fd_attempt_close(fd_ptr) == 0)
453 dos_unlink(fname);
454 fsp->fd_ptr = 0;
455 errno = ENOSPC;
456 return;
460 if (fd_ptr->fd < 0)
462 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
463 fname,strerror(errno),flags));
464 /* Ensure the ref_count is decremented. */
465 fd_attempt_close(fd_ptr);
466 check_for_pipe(fname);
467 return;
470 if (fd_ptr->fd >= 0)
472 if(sbuf == 0) {
473 /* Do the fstat */
474 if(sys_fstat(fd_ptr->fd, &statbuf) == -1) {
475 /* Error - backout !! */
476 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
477 fd_ptr->fd, fname,strerror(errno)));
478 /* Ensure the ref_count is decremented. */
479 fd_attempt_close(fd_ptr);
480 return;
482 sbuf = &statbuf;
485 /* Set the correct entries in fd_ptr. */
486 fd_ptr->dev = sbuf->st_dev;
487 fd_ptr->inode = sbuf->st_ino;
489 fsp->fd_ptr = fd_ptr;
490 conn->num_files_open++;
491 fsp->mode = sbuf->st_mode;
492 GetTimeOfDay(&fsp->open_time);
493 fsp->vuid = current_user.vuid;
494 fsp->size = 0;
495 fsp->pos = -1;
496 fsp->open = True;
497 fsp->mmap_ptr = NULL;
498 fsp->mmap_size = 0;
499 fsp->can_lock = True;
500 fsp->can_read = ((flags & O_WRONLY)==0);
501 fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
502 fsp->share_mode = 0;
503 fsp->print_file = conn->printer;
504 fsp->modified = False;
505 fsp->granted_oplock = False;
506 fsp->sent_oplock_break = False;
507 fsp->is_directory = False;
508 fsp->delete_on_close = False;
509 fsp->conn = conn;
511 * Note that the file name here is the *untranslated* name
512 * ie. it is still in the DOS codepage sent from the client.
513 * All use of this filename will pass though the sys_xxxx
514 * functions which will do the dos_to_unix translation before
515 * mapping into a UNIX filename. JRA.
517 string_set(&fsp->fsp_name,fname);
518 fsp->wbmpx_ptr = NULL;
521 * If the printer is marked as postscript output a leading
522 * file identifier to ensure the file is treated as a raw
523 * postscript file.
524 * This has a similar effect as CtrlD=0 in WIN.INI file.
525 * tim@fsg.com 09/06/94
527 if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) {
528 DEBUG(3,("Writing postscript line\n"));
529 write_file(fsp,"%!\n",3);
532 DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
533 *sesssetup_user ? sesssetup_user : conn->user,fsp->fsp_name,
534 BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
535 conn->num_files_open));
540 /****************************************************************************
541 If it's a read-only file, and we were compiled with mmap enabled,
542 try and mmap the file. This is split out from open_file() above
543 as mmap'ing the file can cause the kernel reference count to
544 be incremented, which can cause kernel oplocks to be refused.
545 Splitting this call off allows the kernel oplock to be granted, then
546 the file mmap'ed.
547 ****************************************************************************/
549 static void mmap_open_file(files_struct *fsp)
551 #if WITH_MMAP
552 /* mmap it if read-only */
553 if (!fsp->can_write) {
554 fsp->mmap_size = file_size(fsp->fsp_name);
555 if (fsp->mmap_size < MAX_MMAP_SIZE) {
556 fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size,
557 PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0);
559 if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) {
560 DEBUG(3,("Failed to mmap() %s - %s\n",
561 fsp->fsp_name,strerror(errno)));
562 fsp->mmap_ptr = NULL;
566 #endif
569 /****************************************************************************
570 C. Hoch 11/22/95
571 Helper for open_file_shared.
572 Truncate a file after checking locking; close file if locked.
573 **************************************************************************/
574 static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token,
575 BOOL *share_locked)
577 if (fsp->can_write){
578 SMB_OFF_T mask = ((SMB_OFF_T)0xC) << (SMB_OFF_T_BITS-4);
580 if (is_locked(fsp,conn,~mask,0,F_WRLCK)){
581 /* If share modes are in force for this connection we
582 have the share entry locked. Unlock it before closing. */
583 if (*share_locked && lp_share_modes(SNUM(conn)))
584 unlock_share_entry( conn, fsp->fd_ptr->dev,
585 fsp->fd_ptr->inode, token);
586 close_file(fsp,False);
587 /* Share mode no longer locked. */
588 *share_locked = False;
589 errno = EACCES;
590 unix_ERR_class = ERRDOS;
591 unix_ERR_code = ERRlock;
592 } else {
593 sys_ftruncate(fsp->fd_ptr->fd,0);
599 enum {AFAIL,AREAD,AWRITE,AALL};
601 /*******************************************************************
602 reproduce the share mode access table
603 ********************************************************************/
604 static int access_table(int new_deny,int old_deny,int old_mode,
605 int share_pid,char *fname)
607 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
609 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
610 int pid = getpid();
611 if (old_deny == new_deny && share_pid == pid)
612 return(AALL);
614 if (old_mode == 0) return(AREAD);
616 /* the new smbpub.zip spec says that if the file extension is
617 .com, .dll, .exe or .sym then allow the open. I will force
618 it to read-only as this seems sensible although the spec is
619 a little unclear on this. */
620 if ((fname = strrchr(fname,'.'))) {
621 if (strequal(fname,".com") ||
622 strequal(fname,".dll") ||
623 strequal(fname,".exe") ||
624 strequal(fname,".sym"))
625 return(AREAD);
628 return(AFAIL);
631 switch (new_deny)
633 case DENY_WRITE:
634 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
635 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
636 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
637 return(AFAIL);
638 case DENY_READ:
639 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
640 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
641 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
642 return(AFAIL);
643 case DENY_NONE:
644 if (old_deny==DENY_WRITE) return(AREAD);
645 if (old_deny==DENY_READ) return(AWRITE);
646 if (old_deny==DENY_NONE) return(AALL);
647 return(AFAIL);
649 return(AFAIL);
653 /****************************************************************************
654 check if we can open a file with a share mode
655 ****************************************************************************/
656 static int check_share_mode( share_mode_entry *share, int deny_mode,
657 char *fname,
658 BOOL fcbopen, int *flags)
660 int old_open_mode = share->share_mode &0xF;
661 int old_deny_mode = (share->share_mode >>4)&7;
663 if (old_deny_mode > 4 || old_open_mode > 2)
665 DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
666 deny_mode,old_deny_mode,old_open_mode,fname));
667 return False;
671 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
672 share->pid,fname);
674 if ((access_allowed == AFAIL) ||
675 (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) ||
676 (access_allowed == AREAD && *flags == O_WRONLY) ||
677 (access_allowed == AWRITE && *flags == O_RDONLY))
679 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n",
680 deny_mode,old_deny_mode,old_open_mode,
681 share->pid,fname, fcbopen, *flags, access_allowed));
682 return False;
685 if (access_allowed == AREAD)
686 *flags = O_RDONLY;
688 if (access_allowed == AWRITE)
689 *flags = O_WRONLY;
692 return True;
696 /****************************************************************************
697 open a file with a share mode
698 ****************************************************************************/
699 void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun,
700 mode_t mode,int oplock_request, int *Access,int *action)
702 int flags=0;
703 int flags2=0;
704 int deny_mode = (share_mode>>4)&7;
705 SMB_STRUCT_STAT sbuf;
706 BOOL file_existed = file_exist(fname,&sbuf);
707 BOOL share_locked = False;
708 BOOL fcbopen = False;
709 int token;
710 SMB_DEV_T dev = 0;
711 SMB_INO_T inode = 0;
712 int num_share_modes = 0;
714 fsp->open = False;
715 fsp->fd_ptr = 0;
717 /* this is for OS/2 EAs - try and say we don't support them */
718 if (strstr(fname,".+,;=[]."))
720 unix_ERR_class = ERRDOS;
721 /* OS/2 Workplace shell fix may be main code stream in a later release. */
722 #if 1 /* OS2_WPS_FIX - Recent versions of OS/2 need this. */
723 unix_ERR_code = ERRcannotopen;
724 #else /* OS2_WPS_FIX */
725 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
726 #endif /* OS2_WPS_FIX */
728 return;
731 if ((ofun & 0x3) == 0 && file_existed)
733 errno = EEXIST;
734 return;
737 if (ofun & 0x10)
738 flags2 |= O_CREAT;
739 if ((ofun & 0x3) == 2)
740 flags2 |= O_TRUNC;
742 /* note that we ignore the append flag as
743 append does not mean the same thing under dos and unix */
745 switch (share_mode&0xF)
747 case 1:
748 flags = O_WRONLY;
749 break;
750 case 0xF:
751 fcbopen = True;
752 flags = O_RDWR;
753 break;
754 case 2:
755 flags = O_RDWR;
756 break;
757 default:
758 flags = O_RDONLY;
759 break;
762 #if defined(O_SYNC)
763 if (share_mode&(1<<14)) {
764 flags2 |= O_SYNC;
766 #endif /* O_SYNC */
768 if (flags != O_RDONLY && file_existed &&
769 (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf))))
771 if (!fcbopen)
773 errno = EACCES;
774 return;
776 flags = O_RDONLY;
779 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB)
781 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
782 errno = EINVAL;
783 return;
786 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
788 if (lp_share_modes(SNUM(conn)))
790 int i;
791 share_mode_entry *old_shares = 0;
793 if (file_existed)
795 dev = sbuf.st_dev;
796 inode = sbuf.st_ino;
797 lock_share_entry(conn, dev, inode, &token);
798 share_locked = True;
799 num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares);
803 * Check if the share modes will give us access.
806 if(share_locked && (num_share_modes != 0))
808 BOOL broke_oplock;
813 broke_oplock = False;
814 for(i = 0; i < num_share_modes; i++)
816 share_mode_entry *share_entry = &old_shares[i];
819 * By observation of NetBench, oplocks are broken *before* share
820 * modes are checked. This allows a file to be closed by the client
821 * if the share mode would deny access and the client has an oplock.
822 * Check if someone has an oplock on this file. If so we must break
823 * it before continuing.
825 if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
828 DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \
829 dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode));
831 /* Oplock break.... */
832 unlock_share_entry(conn, dev, inode, token);
833 if(request_oplock_break(share_entry, dev, inode) == False)
835 free((char *)old_shares);
837 DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \
838 dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode));
840 errno = EACCES;
841 unix_ERR_class = ERRDOS;
842 unix_ERR_code = ERRbadshare;
843 return;
845 lock_share_entry(conn, dev, inode, &token);
846 broke_oplock = True;
847 break;
850 /* someone else has a share lock on it, check to see
851 if we can too */
852 if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False)
854 free((char *)old_shares);
855 unlock_share_entry(conn, dev, inode, token);
856 errno = EACCES;
857 unix_ERR_class = ERRDOS;
858 unix_ERR_code = ERRbadshare;
859 return;
862 } /* end for */
864 if(broke_oplock)
866 free((char *)old_shares);
867 num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares);
869 } while(broke_oplock);
872 if(old_shares != 0)
873 free((char *)old_shares);
876 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
877 flags,flags2,(int)mode));
879 open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
880 if (!fsp->open && flags==O_RDWR && errno!=ENOENT && fcbopen)
882 flags = O_RDONLY;
883 open_file(fsp,conn,fname,flags,mode,file_existed ? &sbuf : 0 );
886 if (fsp->open)
888 int open_mode=0;
890 if((share_locked == False) && lp_share_modes(SNUM(conn)))
892 /* We created the file - thus we must now lock the share entry before creating it. */
893 dev = fsp->fd_ptr->dev;
894 inode = fsp->fd_ptr->inode;
895 lock_share_entry(conn, dev, inode, &token);
896 share_locked = True;
899 switch (flags)
901 case O_RDONLY:
902 open_mode = 0;
903 break;
904 case O_RDWR:
905 open_mode = 2;
906 break;
907 case O_WRONLY:
908 open_mode = 1;
909 break;
912 fsp->share_mode = (deny_mode<<4) | open_mode;
914 if (Access)
915 (*Access) = open_mode;
917 if (action)
919 if (file_existed && !(flags2 & O_TRUNC)) *action = FILE_WAS_OPENED;
920 if (!file_existed) *action = FILE_WAS_CREATED;
921 if (file_existed && (flags2 & O_TRUNC)) *action = FILE_WAS_OVERWRITTEN;
923 /* We must create the share mode entry before truncate as
924 truncate can fail due to locking and have to close the
925 file (which expects the share_mode_entry to be there).
927 if (lp_share_modes(SNUM(conn)))
929 uint16 port = 0;
931 /* JRA. Currently this only services Exlcusive and batch
932 oplocks (no other opens on this file). This needs to
933 be extended to level II oplocks (multiple reader
934 oplocks). */
936 if((oplock_request) && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) &&
937 !IS_VETO_OPLOCK_PATH(conn,fname) && set_file_oplock(fsp) )
939 port = global_oplock_port;
941 else
943 port = 0;
944 oplock_request = 0;
947 set_share_mode(token, fsp, port, oplock_request);
950 if ((flags2&O_TRUNC) && file_existed)
951 truncate_unless_locked(fsp,conn,token,&share_locked);
954 * Attempt to mmap a read only file.
955 * Moved until after a kernel oplock may
956 * be granted due to reference count issues. JRA.
958 mmap_open_file(fsp);
961 if (share_locked && lp_share_modes(SNUM(conn)))
962 unlock_share_entry( conn, dev, inode, token);
967 /****************************************************************************
968 Open a directory from an NT SMB call.
969 ****************************************************************************/
970 int open_directory(files_struct *fsp,connection_struct *conn,
971 char *fname, int smb_ofun, mode_t unixmode, int *action)
973 extern struct current_user current_user;
974 SMB_STRUCT_STAT st;
976 if (smb_ofun & 0x10) {
978 * Create the directory.
981 if(dos_mkdir(fname, unixmode) < 0) {
982 DEBUG(0,("open_directory: unable to create %s. Error was %s\n",
983 fname, strerror(errno) ));
984 return -1;
987 *action = FILE_WAS_CREATED;
988 } else {
990 * Check that it *was* a directory.
993 if(dos_stat(fname, &st) < 0) {
994 DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n",
995 fname, strerror(errno) ));
996 return -1;
999 if(!S_ISDIR(st.st_mode)) {
1000 DEBUG(0,("open_directory: %s is not a directory !\n", fname ));
1001 return -1;
1003 *action = FILE_WAS_OPENED;
1006 DEBUG(5,("open_directory: opening directory %s\n",
1007 fname));
1010 * Setup the files_struct for it.
1013 fsp->fd_ptr = NULL;
1014 conn->num_files_open++;
1015 fsp->mode = 0;
1016 GetTimeOfDay(&fsp->open_time);
1017 fsp->vuid = current_user.vuid;
1018 fsp->size = 0;
1019 fsp->pos = -1;
1020 fsp->open = True;
1021 fsp->mmap_ptr = NULL;
1022 fsp->mmap_size = 0;
1023 fsp->can_lock = True;
1024 fsp->can_read = False;
1025 fsp->can_write = False;
1026 fsp->share_mode = 0;
1027 fsp->print_file = False;
1028 fsp->modified = False;
1029 fsp->granted_oplock = False;
1030 fsp->sent_oplock_break = False;
1031 fsp->is_directory = True;
1032 fsp->conn = conn;
1034 * Note that the file name here is the *untranslated* name
1035 * ie. it is still in the DOS codepage sent from the client.
1036 * All use of this filename will pass though the sys_xxxx
1037 * functions which will do the dos_to_unix translation before
1038 * mapping into a UNIX filename. JRA.
1040 string_set(&fsp->fsp_name,fname);
1041 fsp->wbmpx_ptr = NULL;
1043 return 0;
1047 /*******************************************************************
1048 check if the share mode on a file allows it to be deleted or unlinked
1049 return True if sharing doesn't prevent the operation
1050 ********************************************************************/
1051 BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op)
1053 int i;
1054 int ret = False;
1055 share_mode_entry *old_shares = 0;
1056 int num_share_modes;
1057 SMB_STRUCT_STAT sbuf;
1058 int token;
1059 int pid = getpid();
1060 SMB_DEV_T dev;
1061 SMB_INO_T inode;
1063 if(!lp_share_modes(SNUM(conn)))
1064 return True;
1066 if (dos_stat(fname,&sbuf) == -1) return(True);
1068 dev = sbuf.st_dev;
1069 inode = sbuf.st_ino;
1071 lock_share_entry(conn, dev, inode, &token);
1072 num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares);
1075 * Check if the share modes will give us access.
1078 if(num_share_modes != 0)
1080 BOOL broke_oplock;
1085 broke_oplock = False;
1086 for(i = 0; i < num_share_modes; i++)
1088 share_mode_entry *share_entry = &old_shares[i];
1091 * Break oplocks before checking share modes. See comment in
1092 * open_file_shared for details.
1093 * Check if someone has an oplock on this file. If so we must
1094 * break it before continuing.
1096 if(share_entry->op_type & BATCH_OPLOCK)
1100 * It appears that the NT redirector may have a bug, in that
1101 * it tries to do an SMBmv on a file that it has open with a
1102 * batch oplock, and then fails to respond to the oplock break
1103 * request. This only seems to occur when the client is doing an
1104 * SMBmv to the smbd it is using - thus we try and detect this
1105 * condition by checking if the file being moved is open and oplocked by
1106 * this smbd process, and then not sending the oplock break in this
1107 * special case. If the file was open with a deny mode that
1108 * prevents the move the SMBmv will fail anyway with a share
1109 * violation error. JRA.
1111 if(rename_op && (share_entry->pid == pid))
1114 DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \
1115 batch oplocked file %s, dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode));
1118 * This next line is a test that allows the deny-mode
1119 * processing to be skipped. This seems to be needed as
1120 * NT insists on the rename succeeding (in Office 9x no less !).
1121 * This should be removed as soon as (a) MS fix the redirector
1122 * bug or (b) NT SMB support in Samba makes NT not issue the
1123 * call (as is my fervent hope). JRA.
1125 continue;
1127 else
1130 DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \
1131 dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode));
1133 /* Oplock break.... */
1134 unlock_share_entry(conn, dev, inode, token);
1135 if(request_oplock_break(share_entry, dev, inode) == False)
1137 free((char *)old_shares);
1139 DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \
1140 dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode));
1142 return False;
1144 lock_share_entry(conn, dev, inode, &token);
1145 broke_oplock = True;
1146 break;
1150 /* someone else has a share lock on it, check to see
1151 if we can too */
1152 if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid))
1153 goto free_and_exit;
1155 } /* end for */
1157 if(broke_oplock)
1159 free((char *)old_shares);
1160 num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares);
1162 } while(broke_oplock);
1165 /* XXXX exactly what share mode combinations should be allowed for
1166 deleting/renaming? */
1167 /* If we got here then either there were no share modes or
1168 all share modes were DENY_DOS and the pid == getpid() */
1169 ret = True;
1171 free_and_exit:
1173 unlock_share_entry(conn, dev, inode, token);
1174 if(old_shares != NULL)
1175 free((char *)old_shares);
1176 return(ret);