2 Unix SMB/Netbios implementation.
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.
24 extern int DEBUGLEVEL;
26 extern pstring sesssetup_user;
27 extern int global_oplocks_open;
28 extern uint16 oplock_port;
31 /****************************************************************************
32 fd support routines - attempt to do a dos_open
33 ****************************************************************************/
34 static int fd_attempt_open(char *fname, int flags, int mode)
36 int fd = dos_open(fname,flags,mode);
38 /* Fix for files ending in '.' */
39 if((fd == -1) && (errno == ENOENT) &&
40 (strchr(fname,'.')==NULL))
43 fd = dos_open(fname,flags,mode);
46 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
47 if ((fd == -1) && (errno == ENAMETOOLONG))
50 char *p = strrchr(fname, '/');
52 if (p == fname) /* name is "/xxx" */
54 max_len = pathconf("/", _PC_NAME_MAX);
57 else if ((p == NULL) || (p == fname))
60 max_len = pathconf(".", _PC_NAME_MAX);
65 max_len = pathconf(fname, _PC_NAME_MAX);
69 if (strlen(p) > max_len)
71 char tmp = p[max_len];
74 if ((fd = dos_open(fname,flags,mode)) == -1)
82 /****************************************************************************
83 Cache a uid_t currently with this file open. This is an optimization only
84 used when multiple sessionsetup's have been done to one smbd.
85 ****************************************************************************/
86 void fd_add_to_uid_cache(file_fd_struct *fd_ptr, uid_t u)
88 if(fd_ptr->uid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t))
90 fd_ptr->uid_users_cache[fd_ptr->uid_cache_count++] = u;
93 /****************************************************************************
94 Remove a uid_t that currently has this file open. This is an optimization only
95 used when multiple sessionsetup's have been done to one smbd.
96 ****************************************************************************/
97 static void fd_remove_from_uid_cache(file_fd_struct *fd_ptr, uid_t u)
100 for(i = 0; i < fd_ptr->uid_cache_count; i++)
101 if(fd_ptr->uid_users_cache[i] == u) {
102 if(i < (fd_ptr->uid_cache_count-1))
103 memmove((char *)&fd_ptr->uid_users_cache[i], (char *)&fd_ptr->uid_users_cache[i+1],
104 sizeof(uid_t)*(fd_ptr->uid_cache_count-1-i) );
105 fd_ptr->uid_cache_count--;
110 /****************************************************************************
111 Check if a uid_t that currently has this file open is present. This is an
112 optimization only used when multiple sessionsetup's have been done to one smbd.
113 ****************************************************************************/
114 static BOOL fd_is_in_uid_cache(file_fd_struct *fd_ptr, uid_t u)
117 for(i = 0; i < fd_ptr->uid_cache_count; i++)
118 if(fd_ptr->uid_users_cache[i] == u)
124 /****************************************************************************
125 fd support routines - attempt to re-open an already open fd as O_RDWR.
126 Save the already open fd (we cannot close due to POSIX file locking braindamage.
127 ****************************************************************************/
128 static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
130 int fd = dos_open( fname, O_RDWR, mode);
135 if(fd_ptr->real_open_flags == O_RDONLY)
136 fd_ptr->fd_readonly = fd_ptr->fd;
137 if(fd_ptr->real_open_flags == O_WRONLY)
138 fd_ptr->fd_writeonly = fd_ptr->fd;
141 fd_ptr->real_open_flags = O_RDWR;
144 /****************************************************************************
145 fd support routines - attempt to close the file referenced by this fd.
146 Decrements the ref_count and returns it.
147 ****************************************************************************/
148 int fd_attempt_close(file_fd_struct *fd_ptr)
150 extern struct current_user current_user;
152 #ifdef LARGE_SMB_INO_T
153 DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %.0f, open_flags = %d, ref_count = %d.\n",
154 fd_ptr->fd, (unsigned int)fd_ptr->dev, (double)fd_ptr->inode,
155 fd_ptr->real_open_flags,
157 #else /* LARGE_SMB_INO_T */
158 DEBUG(3,("fd_attempt_close fd = %d, dev = %x, inode = %lx, open_flags = %d, ref_count = %d.\n",
159 fd_ptr->fd, (unsigned int)fd_ptr->dev, (unsigned long)fd_ptr->inode,
160 fd_ptr->real_open_flags,
162 #endif /* LARGE_SMB_INO_T */
164 if(fd_ptr->ref_count > 0) {
166 if(fd_ptr->ref_count == 0) {
169 if(fd_ptr->fd_readonly != -1)
170 close(fd_ptr->fd_readonly);
171 if(fd_ptr->fd_writeonly != -1)
172 close(fd_ptr->fd_writeonly);
174 fd_ptr->fd_readonly = -1;
175 fd_ptr->fd_writeonly = -1;
176 fd_ptr->real_open_flags = -1;
177 fd_ptr->dev = (SMB_DEV_T)-1;
178 fd_ptr->inode = (SMB_INO_T)-1;
179 fd_ptr->uid_cache_count = 0;
181 fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
184 return fd_ptr->ref_count;
187 /****************************************************************************
188 fd support routines - check that current user has permissions
189 to open this file. Used when uid not found in optimization cache.
190 This is really ugly code, as due to POSIX locking braindamage we must
191 fork and then attempt to open the file, and return success or failure
193 ****************************************************************************/
194 static BOOL check_access_allowed_for_current_user( char *fname, int accmode )
198 if((child_pid = fork()) < 0) {
199 DEBUG(0,("check_access_allowed_for_current_user: fork failed.\n"));
209 if ((wpid = sys_waitpid(child_pid, &status_code, 0)) < 0) {
210 DEBUG(0,("check_access_allowed_for_current_user: The process is no longer waiting!\n"));
214 if (child_pid != wpid) {
215 DEBUG(0,("check_access_allowed_for_current_user: We were waiting for the wrong process ID\n"));
218 #if defined(WIFEXITED) && defined(WEXITSTATUS)
219 if (WIFEXITED(status_code) == 0) {
220 DEBUG(0,("check_access_allowed_for_current_user: The process exited while we were waiting\n"));
223 if (WEXITSTATUS(status_code) != 0) {
224 DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code));
227 #else /* defined(WIFEXITED) && defined(WEXITSTATUS) */
228 if(status_code != 0) {
229 DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access denied.\n", status_code));
232 #endif /* defined(WIFEXITED) && defined(WEXITSTATUS) */
235 * Success - the child could open the file.
237 DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access allowed.\n", status_code));
244 DEBUG(9,("check_access_allowed_for_current_user: Child - attempting to open %s with mode %d.\n", fname, accmode ));
245 if((fd = fd_attempt_open( fname, accmode, 0)) < 0) {
250 DEBUG(9,("check_access_allowed_for_current_user: Child - returning ok.\n"));
257 /****************************************************************************
258 check a filename for the pipe string
259 ****************************************************************************/
260 static void check_for_pipe(char *fname)
262 /* special case of pipe opens */
266 if (strstr(s,"pipe/")) {
267 DEBUG(3,("Rejecting named pipe open for %s\n",fname));
268 unix_ERR_class = ERRSRV;
269 unix_ERR_code = ERRaccess;
273 /****************************************************************************
275 ****************************************************************************/
276 static void open_file(files_struct *fsp,connection_struct *conn,
277 char *fname1,int flags,int mode, SMB_STRUCT_STAT *sbuf)
279 extern struct current_user current_user;
281 SMB_STRUCT_STAT statbuf;
282 file_fd_struct *fd_ptr;
283 int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
287 fsp->granted_oplock = False;
290 pstrcpy(fname,fname1);
292 /* check permissions */
295 * This code was changed after seeing a client open request
296 * containing the open mode of (DENY_WRITE/read-only) with
297 * the 'create if not exist' bit set. The previous code
298 * would fail to open the file read only on a read-only share
299 * as it was checking the flags parameter directly against O_RDONLY,
300 * this was failing as the flags parameter was set to O_RDONLY|O_CREAT.
304 if (conn->read_only && !conn->printer) {
305 /* It's a read-only share - fail if we wanted to write. */
306 if(accmode != O_RDONLY) {
307 DEBUG(3,("Permission denied opening %s\n",fname));
308 check_for_pipe(fname);
310 } else if(flags & O_CREAT) {
311 /* We don't want to write - but we must make sure that O_CREAT
312 doesn't create the file if we have write access into the
319 /* this handles a bug in Win95 - it doesn't say to create the file when it
326 if (flags == O_WRONLY)
327 DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
331 * Ensure we have a valid struct stat so we can search the
335 if(dos_stat(fname, &statbuf) < 0) {
336 if(errno != ENOENT) {
337 DEBUG(3,("Error doing stat on file %s (%s)\n",
338 fname,strerror(errno)));
340 check_for_pipe(fname);
350 * Check to see if we have this file already
351 * open. If we do, just use the already open fd and increment the
352 * reference count (fd_get_already_open increments the ref_count).
354 if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
356 * File was already open.
360 * Check it wasn't open for exclusive use.
362 if((flags & O_CREAT) && (flags & O_EXCL)) {
369 * Ensure that the user attempting to open
370 * this file has permissions to do so, if
371 * the user who originally opened the file wasn't
372 * the same as the current user.
375 if(!fd_is_in_uid_cache(fd_ptr, (uid_t)current_user.uid)) {
376 if(!check_access_allowed_for_current_user( fname, accmode )) {
377 /* Error - permission denied. */
378 DEBUG(3,("Permission denied opening file %s (flags=%d, accmode = %d)\n",
379 fname, flags, accmode));
380 /* Ensure the ref_count is decremented. */
382 fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
388 fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid);
391 * If not opened O_RDWR try
392 * and do that here - a chmod may have been done
393 * between the last open and now.
395 if(fd_ptr->real_open_flags != O_RDWR)
396 fd_attempt_reopen(fname, mode, fd_ptr);
399 * Ensure that if we wanted write access
400 * it has been opened for write, and if we wanted read it
403 if(((accmode == O_WRONLY) && (fd_ptr->real_open_flags == O_RDONLY)) ||
404 ((accmode == O_RDONLY) && (fd_ptr->real_open_flags == O_WRONLY)) ||
405 ((accmode == O_RDWR) && (fd_ptr->real_open_flags != O_RDWR))) {
406 DEBUG(3,("Error opening (already open for flags=%d) file %s (%s) (flags=%d)\n",
407 fd_ptr->real_open_flags, fname,strerror(EACCES),flags));
408 check_for_pipe(fname);
409 fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
416 /* We need to allocate a new file_fd_struct (this increments the
418 if((fd_ptr = fd_get_new()) == 0)
421 * Whatever the requested flags, attempt read/write access,
422 * as we don't know what flags future file opens may require.
423 * If this fails, try again with the required flags.
424 * Even if we open read/write when only read access was
425 * requested the setting of the can_write flag in
426 * the file_struct will protect us from errant
427 * write requests. We never need to worry about O_APPEND
428 * as this is not set anywhere in Samba.
430 fd_ptr->real_open_flags = O_RDWR;
431 /* Set the flags as needed without the read/write modes. */
432 open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
433 fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
435 * On some systems opening a file for R/W access on a read only
436 * filesystems sets errno to EROFS.
439 if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
441 if((fd_ptr->fd == -1) && (errno == EACCES)) {
443 if(accmode != O_RDWR) {
444 fd_ptr->fd = fd_attempt_open(fname, open_flags|accmode, mode);
445 fd_ptr->real_open_flags = accmode;
450 if ((fd_ptr->fd >=0) &&
451 conn->printer && lp_minprintspace(SNUM(conn))) {
455 pstrcpy(dname,fname);
456 p = strrchr(dname,'/');
458 if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
459 lp_minprintspace(SNUM(conn))) {
460 fd_attempt_close(fd_ptr);
462 if(fd_ptr->ref_count == 0)
471 DEBUG(3,("Error opening file %s (%s) (flags=%d)\n",
472 fname,strerror(errno),flags));
473 /* Ensure the ref_count is decremented. */
474 fd_attempt_close(fd_ptr);
475 check_for_pipe(fname);
483 if(sys_fstat(fd_ptr->fd, &statbuf) == -1) {
484 /* Error - backout !! */
485 DEBUG(3,("Error doing fstat on fd %d, file %s (%s)\n",
486 fd_ptr->fd, fname,strerror(errno)));
487 /* Ensure the ref_count is decremented. */
488 fd_attempt_close(fd_ptr);
494 /* Set the correct entries in fd_ptr. */
495 fd_ptr->dev = sbuf->st_dev;
496 fd_ptr->inode = sbuf->st_ino;
498 fsp->fd_ptr = fd_ptr;
499 conn->num_files_open++;
500 fsp->mode = sbuf->st_mode;
501 GetTimeOfDay(&fsp->open_time);
502 fsp->vuid = current_user.vuid;
506 fsp->mmap_ptr = NULL;
508 fsp->can_lock = True;
509 fsp->can_read = ((flags & O_WRONLY)==0);
510 fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
512 fsp->print_file = conn->printer;
513 fsp->modified = False;
514 fsp->granted_oplock = False;
515 fsp->sent_oplock_break = False;
516 fsp->is_directory = False;
519 * Note that the file name here is the *untranslated* name
520 * ie. it is still in the DOS codepage sent from the client.
521 * All use of this filename will pass though the sys_xxxx
522 * functions which will do the dos_to_unix translation before
523 * mapping into a UNIX filename. JRA.
525 string_set(&fsp->fsp_name,fname);
526 fsp->wbmpx_ptr = NULL;
529 * If the printer is marked as postscript output a leading
530 * file identifier to ensure the file is treated as a raw
532 * This has a similar effect as CtrlD=0 in WIN.INI file.
533 * tim@fsg.com 09/06/94
535 if (fsp->print_file && lp_postscript(SNUM(conn)) && fsp->can_write) {
536 DEBUG(3,("Writing postscript line\n"));
537 write_file(fsp,"%!\n",3);
540 DEBUG(2,("%s opened file %s read=%s write=%s (numopen=%d)\n",
541 *sesssetup_user ? sesssetup_user : conn->user,fsp->fsp_name,
542 BOOLSTR(fsp->can_read), BOOLSTR(fsp->can_write),
543 conn->num_files_open));
548 /* mmap it if read-only */
549 if (!fsp->can_write) {
550 fsp->mmap_size = file_size(fname);
551 fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size,
552 PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0);
554 if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr) {
555 DEBUG(3,("Failed to mmap() %s - %s\n",
556 fname,strerror(errno)));
557 fsp->mmap_ptr = NULL;
564 /****************************************************************************
566 Helper for open_file_shared.
567 Truncate a file after checking locking; close file if locked.
568 **************************************************************************/
569 static void truncate_unless_locked(files_struct *fsp, connection_struct *conn, int token,
573 #ifdef LARGE_SMB_OFF_T
574 if (is_locked(fsp,conn,0x3FFFFFFFFFFFFFFFLL,0,F_WRLCK)){
576 if (is_locked(fsp,conn,0x3FFFFFFF,0,F_WRLCK)){
578 /* If share modes are in force for this connection we
579 have the share entry locked. Unlock it before closing. */
580 if (*share_locked && lp_share_modes(SNUM(conn)))
581 unlock_share_entry( conn, fsp->fd_ptr->dev,
582 fsp->fd_ptr->inode, token);
583 close_file(fsp,False);
584 /* Share mode no longer locked. */
585 *share_locked = False;
587 unix_ERR_class = ERRDOS;
588 unix_ERR_code = ERRlock;
591 sys_ftruncate(fsp->fd_ptr->fd,0);
597 /****************************************************************************
598 open a file with a share mode
599 ****************************************************************************/
600 void open_file_shared(files_struct *fsp,connection_struct *conn,char *fname,int share_mode,int ofun,
601 int mode,int oplock_request, int *Access,int *action)
605 int deny_mode = (share_mode>>4)&7;
606 SMB_STRUCT_STAT sbuf;
607 BOOL file_existed = file_exist(fname,&sbuf);
608 BOOL share_locked = False;
609 BOOL fcbopen = False;
613 int num_share_modes = 0;
618 /* this is for OS/2 EAs - try and say we don't support them */
619 if (strstr(fname,".+,;=[]."))
621 unix_ERR_class = ERRDOS;
622 /* OS/2 Workplace shell fix may be main code stream in a later release. */
623 #if 1 /* OS2_WPS_FIX - Recent versions of OS/2 need this. */
624 unix_ERR_code = ERRcannotopen;
625 #else /* OS2_WPS_FIX */
626 unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
627 #endif /* OS2_WPS_FIX */
632 if ((ofun & 0x3) == 0 && file_existed)
640 if ((ofun & 0x3) == 2)
643 /* note that we ignore the append flag as
644 append does not mean the same thing under dos and unix */
646 switch (share_mode&0xF)
664 if (share_mode&(1<<14)) {
669 if (flags != O_RDONLY && file_existed &&
670 (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf))))
680 if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB)
682 DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
687 if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
689 if (lp_share_modes(SNUM(conn)))
692 share_mode_entry *old_shares = 0;
698 lock_share_entry(conn, dev, inode, &token);
700 num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares);
704 * Check if the share modes will give us access.
707 if(share_locked && (num_share_modes != 0))
714 broke_oplock = False;
715 for(i = 0; i < num_share_modes; i++)
717 share_mode_entry *share_entry = &old_shares[i];
720 * By observation of NetBench, oplocks are broken *before* share
721 * modes are checked. This allows a file to be closed by the client
722 * if the share mode would deny access and the client has an oplock.
723 * Check if someone has an oplock on this file. If so we must break
724 * it before continuing.
726 if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
729 #ifdef LARGE_SMB_INO_T
730 DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \
731 dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode));
732 #else /* LARGE_SMB_INO_T */
733 DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \
734 dev = %x, inode = %lx\n", share_entry->op_type, fname, (unsigned int)dev, (unsigned long)inode));
735 #endif /* LARGE_SMB_INO_T */
737 /* Oplock break.... */
738 unlock_share_entry(conn, dev, inode, token);
739 if(request_oplock_break(share_entry, dev, inode) == False)
741 free((char *)old_shares);
743 #ifdef LARGE_SMB_INO_T
744 DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \
745 dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode));
746 #else /* LARGE_SMB_INO_T */
747 DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \
748 dev = %x, inode = %lx\n", old_shares[i].op_type, fname, (unsigned int)dev, (unsigned long)inode));
749 #endif /* LARGE_SMB_INO_T */
752 unix_ERR_class = ERRDOS;
753 unix_ERR_code = ERRbadshare;
756 lock_share_entry(conn, dev, inode, &token);
761 /* someone else has a share lock on it, check to see
763 if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False)
765 free((char *)old_shares);
766 unlock_share_entry(conn, dev, inode, token);
768 unix_ERR_class = ERRDOS;
769 unix_ERR_code = ERRbadshare;
777 free((char *)old_shares);
778 num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares);
780 } while(broke_oplock);
784 free((char *)old_shares);
787 DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
790 open_file(fsp,conn,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
791 if (!fsp->open && flags==O_RDWR && errno!=ENOENT && fcbopen)
794 open_file(fsp,conn,fname,flags,mode,file_existed ? &sbuf : 0 );
801 if((share_locked == False) && lp_share_modes(SNUM(conn)))
803 /* We created the file - thus we must now lock the share entry before creating it. */
804 dev = fsp->fd_ptr->dev;
805 inode = fsp->fd_ptr->inode;
806 lock_share_entry(conn, dev, inode, &token);
823 fsp->share_mode = (deny_mode<<4) | open_mode;
826 (*Access) = open_mode;
830 if (file_existed && !(flags2 & O_TRUNC)) *action = FILE_WAS_OPENED;
831 if (!file_existed) *action = FILE_WAS_CREATED;
832 if (file_existed && (flags2 & O_TRUNC)) *action = FILE_WAS_OVERWRITTEN;
834 /* We must create the share mode entry before truncate as
835 truncate can fail due to locking and have to close the
836 file (which expects the share_mode_entry to be there).
838 if (lp_share_modes(SNUM(conn)))
841 /* JRA. Currently this only services Exlcusive and batch
842 oplocks (no other opens on this file). This needs to
843 be extended to level II oplocks (multiple reader
846 if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) &&
847 !IS_VETO_OPLOCK_PATH(conn,fname))
849 fsp->granted_oplock = True;
850 fsp->sent_oplock_break = False;
851 global_oplocks_open++;
854 #ifdef LARGE_SMB_INO_T
855 DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \
856 dev = %x, inode = %.0f\n", oplock_request, fname, (unsigned int)dev, (double)inode));
857 #else /* LARGE_SMB_INO_T */
858 DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \
859 dev = %x, inode = %lx\n", oplock_request, fname, (unsigned int)dev, (double)inode));
860 #endif /* LARGE_SMB_INO_T */
868 set_share_mode(token, fsp, port, oplock_request);
871 if ((flags2&O_TRUNC) && file_existed)
872 truncate_unless_locked(fsp,conn,token,&share_locked);
875 if (share_locked && lp_share_modes(SNUM(conn)))
876 unlock_share_entry( conn, dev, inode, token);
881 /****************************************************************************
882 Open a directory from an NT SMB call.
883 ****************************************************************************/
884 int open_directory(files_struct *fsp,connection_struct *conn,
885 char *fname, int smb_ofun, int unixmode, int *action)
887 extern struct current_user current_user;
890 if (smb_ofun & 0x10) {
892 * Create the directory.
895 if(dos_mkdir(fname, unixmode) < 0) {
896 DEBUG(0,("open_directory: unable to create %s. Error was %s\n",
897 fname, strerror(errno) ));
901 *action = FILE_WAS_CREATED;
904 * Check that it *was* a directory.
907 if(dos_stat(fname, &st) < 0) {
908 DEBUG(0,("open_directory: unable to stat name = %s. Error was %s\n",
909 fname, strerror(errno) ));
913 if(!S_ISDIR(st.st_mode)) {
914 DEBUG(0,("open_directory: %s is not a directory !\n", fname ));
917 *action = FILE_WAS_OPENED;
920 DEBUG(5,("open_directory: opening directory %s\n",
924 * Setup the files_struct for it.
928 conn->num_files_open++;
930 GetTimeOfDay(&fsp->open_time);
931 fsp->vuid = current_user.vuid;
935 fsp->mmap_ptr = NULL;
937 fsp->can_lock = True;
938 fsp->can_read = False;
939 fsp->can_write = False;
941 fsp->print_file = False;
942 fsp->modified = False;
943 fsp->granted_oplock = False;
944 fsp->sent_oplock_break = False;
945 fsp->is_directory = True;
948 * Note that the file name here is the *untranslated* name
949 * ie. it is still in the DOS codepage sent from the client.
950 * All use of this filename will pass though the sys_xxxx
951 * functions which will do the dos_to_unix translation before
952 * mapping into a UNIX filename. JRA.
954 string_set(&fsp->fsp_name,fname);
955 fsp->wbmpx_ptr = NULL;
960 enum {AFAIL,AREAD,AWRITE,AALL};
962 /*******************************************************************
963 reproduce the share mode access table
964 ********************************************************************/
965 static int access_table(int new_deny,int old_deny,int old_mode,
966 int share_pid,char *fname)
968 if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
970 if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
972 if (old_deny == new_deny && share_pid == pid)
975 if (old_mode == 0) return(AREAD);
977 /* the new smbpub.zip spec says that if the file extension is
978 .com, .dll, .exe or .sym then allow the open. I will force
979 it to read-only as this seems sensible although the spec is
980 a little unclear on this. */
981 if ((fname = strrchr(fname,'.'))) {
982 if (strequal(fname,".com") ||
983 strequal(fname,".dll") ||
984 strequal(fname,".exe") ||
985 strequal(fname,".sym"))
995 if (old_deny==DENY_WRITE && old_mode==0) return(AREAD);
996 if (old_deny==DENY_READ && old_mode==0) return(AWRITE);
997 if (old_deny==DENY_NONE && old_mode==0) return(AALL);
1000 if (old_deny==DENY_WRITE && old_mode==1) return(AREAD);
1001 if (old_deny==DENY_READ && old_mode==1) return(AWRITE);
1002 if (old_deny==DENY_NONE && old_mode==1) return(AALL);
1005 if (old_deny==DENY_WRITE) return(AREAD);
1006 if (old_deny==DENY_READ) return(AWRITE);
1007 if (old_deny==DENY_NONE) return(AALL);
1013 /*******************************************************************
1014 check if the share mode on a file allows it to be deleted or unlinked
1015 return True if sharing doesn't prevent the operation
1016 ********************************************************************/
1017 BOOL check_file_sharing(connection_struct *conn,char *fname, BOOL rename_op)
1021 share_mode_entry *old_shares = 0;
1022 int num_share_modes;
1023 SMB_STRUCT_STAT sbuf;
1029 if(!lp_share_modes(SNUM(conn)))
1032 if (dos_stat(fname,&sbuf) == -1) return(True);
1035 inode = sbuf.st_ino;
1037 lock_share_entry(conn, dev, inode, &token);
1038 num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares);
1041 * Check if the share modes will give us access.
1044 if(num_share_modes != 0)
1051 broke_oplock = False;
1052 for(i = 0; i < num_share_modes; i++)
1054 share_mode_entry *share_entry = &old_shares[i];
1057 * Break oplocks before checking share modes. See comment in
1058 * open_file_shared for details.
1059 * Check if someone has an oplock on this file. If so we must
1060 * break it before continuing.
1062 if(share_entry->op_type & BATCH_OPLOCK)
1066 * It appears that the NT redirector may have a bug, in that
1067 * it tries to do an SMBmv on a file that it has open with a
1068 * batch oplock, and then fails to respond to the oplock break
1069 * request. This only seems to occur when the client is doing an
1070 * SMBmv to the smbd it is using - thus we try and detect this
1071 * condition by checking if the file being moved is open and oplocked by
1072 * this smbd process, and then not sending the oplock break in this
1073 * special case. If the file was open with a deny mode that
1074 * prevents the move the SMBmv will fail anyway with a share
1075 * violation error. JRA.
1077 if(rename_op && (share_entry->pid == pid))
1080 #ifdef LARGE_SMB_INO_T
1081 DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \
1082 batch oplocked file %s, dev = %x, inode = %.0f\n", fname, (unsigned int)dev, (double)inode));
1083 #else /* LARGE_SMB_INO_T */
1084 DEBUG(0,("check_file_sharing: NT redirector workaround - rename attempted on \
1085 batch oplocked file %s, dev = %x, inode = %lx\n", fname, (unsigned int)dev, (unsigned long)inode));
1086 #endif /* LARGE_SMB_INO_T */
1089 * This next line is a test that allows the deny-mode
1090 * processing to be skipped. This seems to be needed as
1091 * NT insists on the rename succeeding (in Office 9x no less !).
1092 * This should be removed as soon as (a) MS fix the redirector
1093 * bug or (b) NT SMB support in Samba makes NT not issue the
1094 * call (as is my fervent hope). JRA.
1101 #ifdef LARGE_SMB_INO_T
1102 DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \
1103 dev = %x, inode = %.0f\n", share_entry->op_type, fname, (unsigned int)dev, (double)inode));
1104 #else /* LARGE_SMB_INO_T */
1105 DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \
1106 dev = %x, inode = %lx\n", share_entry->op_type, fname, (unsigned int)dev, (unsigned long)inode));
1107 #endif /* LARGE_SMB_INO_T */
1109 /* Oplock break.... */
1110 unlock_share_entry(conn, dev, inode, token);
1111 if(request_oplock_break(share_entry, dev, inode) == False)
1113 free((char *)old_shares);
1115 #ifdef LARGE_SMB_INO_T
1116 DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \
1117 dev = %x, inode = %.0f\n", old_shares[i].op_type, fname, (unsigned int)dev, (double)inode));
1118 #else /* LARGE_SMB_INO_T */
1119 DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \
1120 dev = %x, inode = %lx\n", old_shares[i].op_type, fname, (unsigned int)dev, (unsigned long)inode));
1121 #endif /* LARGE_SMB_INO_T */
1125 lock_share_entry(conn, dev, inode, &token);
1126 broke_oplock = True;
1131 /* someone else has a share lock on it, check to see
1133 if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid))
1140 free((char *)old_shares);
1141 num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares);
1143 } while(broke_oplock);
1146 /* XXXX exactly what share mode combinations should be allowed for
1147 deleting/renaming? */
1148 /* If we got here then either there were no share modes or
1149 all share modes were DENY_DOS and the pid == getpid() */
1154 unlock_share_entry(conn, dev, inode, token);
1155 if(old_shares != NULL)
1156 free((char *)old_shares);
1160 /****************************************************************************
1161 check if we can open a file with a share mode
1162 ****************************************************************************/
1163 int check_share_mode( share_mode_entry *share, int deny_mode, char *fname,
1164 BOOL fcbopen, int *flags)
1166 int old_open_mode = share->share_mode &0xF;
1167 int old_deny_mode = (share->share_mode >>4)&7;
1169 if (old_deny_mode > 4 || old_open_mode > 2)
1171 DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
1172 deny_mode,old_deny_mode,old_open_mode,fname));
1177 int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1180 if ((access_allowed == AFAIL) ||
1181 (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) ||
1182 (access_allowed == AREAD && *flags == O_WRONLY) ||
1183 (access_allowed == AWRITE && *flags == O_RDONLY))
1185 DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n",
1186 deny_mode,old_deny_mode,old_open_mode,
1187 share->pid,fname, fcbopen, *flags, access_allowed));
1191 if (access_allowed == AREAD)
1194 if (access_allowed == AWRITE)