Modified dev_t and ino_t code to be 64 bit clean (including changes
[samba.git] / source3 / smbd / open.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    file opening and share modes
5    Copyright (C) Andrew Tridgell 1992-1998
6    
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.
11    
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.
16    
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.
20 */
21
22 #include "includes.h"
23
24 extern int DEBUGLEVEL;
25
26 extern pstring sesssetup_user;
27 extern int global_oplocks_open;
28 extern uint16 oplock_port;
29
30
31 /****************************************************************************
32 fd support routines - attempt to do a dos_open
33 ****************************************************************************/
34 static int fd_attempt_open(char *fname, int flags, int mode)
35 {
36   int fd = dos_open(fname,flags,mode);
37
38   /* Fix for files ending in '.' */
39   if((fd == -1) && (errno == ENOENT) &&
40      (strchr(fname,'.')==NULL))
41     {
42       pstrcat(fname,".");
43       fd = dos_open(fname,flags,mode);
44     }
45
46 #if (defined(ENAMETOOLONG) && defined(HAVE_PATHCONF))
47   if ((fd == -1) && (errno == ENAMETOOLONG))
48     {
49       int max_len;
50       char *p = strrchr(fname, '/');
51
52       if (p == fname)   /* name is "/xxx" */
53         {
54           max_len = pathconf("/", _PC_NAME_MAX);
55           p++;
56         }
57       else if ((p == NULL) || (p == fname))
58         {
59           p = fname;
60           max_len = pathconf(".", _PC_NAME_MAX);
61         }
62       else
63         {
64           *p = '\0';
65           max_len = pathconf(fname, _PC_NAME_MAX);
66           *p = '/';
67           p++;
68         }
69       if (strlen(p) > max_len)
70         {
71           char tmp = p[max_len];
72
73           p[max_len] = '\0';
74           if ((fd = dos_open(fname,flags,mode)) == -1)
75             p[max_len] = tmp;
76         }
77     }
78 #endif
79   return fd;
80 }
81
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)
87 {
88   if(fd_ptr->uid_cache_count >= sizeof(fd_ptr->uid_users_cache)/sizeof(uid_t))
89     return;
90   fd_ptr->uid_users_cache[fd_ptr->uid_cache_count++] = u;
91 }
92
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)
98 {
99   int i;
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--;
106     }
107   return;
108 }
109
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)
115 {
116   int i;
117   for(i = 0; i < fd_ptr->uid_cache_count; i++)
118     if(fd_ptr->uid_users_cache[i] == u)
119       return True;
120   return False;
121 }
122
123
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)
129 {
130   int fd = dos_open( fname, O_RDWR, mode);
131
132   if(fd == -1)
133     return;
134
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;
139
140   fd_ptr->fd = fd;
141   fd_ptr->real_open_flags = O_RDWR;
142 }
143
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)
149 {
150   extern struct current_user current_user;
151
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,
156           fd_ptr->ref_count));
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,
161           fd_ptr->ref_count));
162 #endif /* LARGE_SMB_INO_T */
163
164   if(fd_ptr->ref_count > 0) {
165     fd_ptr->ref_count--;
166     if(fd_ptr->ref_count == 0) {
167       if(fd_ptr->fd != -1)
168         close(fd_ptr->fd);
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);
173       fd_ptr->fd = -1;
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;
180     } else {
181       fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
182     }
183   } 
184  return fd_ptr->ref_count;
185 }
186
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
192 via an exit code.
193 ****************************************************************************/
194 static BOOL check_access_allowed_for_current_user( char *fname, int accmode )
195 {
196   pid_t child_pid;
197
198   if((child_pid = fork()) < 0) {
199     DEBUG(0,("check_access_allowed_for_current_user: fork failed.\n"));
200     return False;
201   }
202
203   if(child_pid) {
204     /*
205      * Parent.
206      */
207     pid_t wpid;
208     int status_code;
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"));
211       return(False);
212     }
213
214     if (child_pid != wpid) {
215       DEBUG(0,("check_access_allowed_for_current_user: We were waiting for the wrong process ID\n"));
216       return(False);
217     }
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"));
221       return(False);
222     }
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));
225       return(False);
226     }
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));
230       return(False);
231     }
232 #endif /* defined(WIFEXITED) && defined(WEXITSTATUS) */
233
234     /*
235      * Success - the child could open the file.
236      */
237     DEBUG(9,("check_access_allowed_for_current_user: The status of the process exiting was %d. Returning access allowed.\n", status_code));
238     return True;
239   } else {
240     /*
241      * Child.
242      */
243     int fd;
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) {
246       /* Access denied. */
247       _exit(EACCES);
248     }
249     close(fd);
250     DEBUG(9,("check_access_allowed_for_current_user: Child - returning ok.\n"));
251     _exit(0);
252   }
253
254   return False;
255 }
256
257 /****************************************************************************
258 check a filename for the pipe string
259 ****************************************************************************/
260 static void check_for_pipe(char *fname)
261 {
262         /* special case of pipe opens */
263         char s[10];
264         StrnCpy(s,fname,9);
265         strlower(s);
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;
270         }
271 }
272
273 /****************************************************************************
274 open a file
275 ****************************************************************************/
276 static void open_file(files_struct *fsp,connection_struct *conn,
277                       char *fname1,int flags,int mode, SMB_STRUCT_STAT *sbuf)
278 {
279   extern struct current_user current_user;
280   pstring fname;
281   SMB_STRUCT_STAT statbuf;
282   file_fd_struct *fd_ptr;
283   int accmode = (flags & (O_RDONLY | O_WRONLY | O_RDWR));
284
285   fsp->open = False;
286   fsp->fd_ptr = 0;
287   fsp->granted_oplock = False;
288   errno = EPERM;
289
290   pstrcpy(fname,fname1);
291
292   /* check permissions */
293
294   /*
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.
301    * JRA.
302    */
303
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);
309       return;
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
313          directory.
314        */
315       flags &= ~O_CREAT;
316     }
317   }
318
319   /* this handles a bug in Win95 - it doesn't say to create the file when it 
320      should */
321   if (conn->printer) {
322           flags |= O_CREAT;
323   }
324
325 /*
326   if (flags == O_WRONLY)
327     DEBUG(3,("Bug in client? Set O_WRONLY without O_CREAT\n"));
328 */
329
330   /*
331    * Ensure we have a valid struct stat so we can search the
332    * open fd table.
333    */
334   if(sbuf == 0) {
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)));
339
340         check_for_pipe(fname);
341         return;
342       }
343       sbuf = 0;
344     } else {
345       sbuf = &statbuf;
346     }
347   }
348
349   /*
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).
353    */
354   if((fd_ptr = fd_get_already_open(sbuf))!= 0) {
355     /*
356      * File was already open.
357      */
358
359     /* 
360      * Check it wasn't open for exclusive use.
361      */
362     if((flags & O_CREAT) && (flags & O_EXCL)) {
363       fd_ptr->ref_count--;
364       errno = EEXIST;
365       return;
366     }
367
368     /*
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.
373      */
374
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. */
381         fd_ptr->ref_count--;
382         fd_remove_from_uid_cache(fd_ptr, (uid_t)current_user.uid);
383         errno = EACCES;
384         return;
385       }
386     }
387
388     fd_add_to_uid_cache(fd_ptr, (uid_t)current_user.uid);
389
390     /* 
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. 
394      */
395     if(fd_ptr->real_open_flags != O_RDWR)
396       fd_attempt_reopen(fname, mode, fd_ptr);
397
398     /*
399      * Ensure that if we wanted write access
400      * it has been opened for write, and if we wanted read it
401      * was open for read. 
402      */
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);
410       fd_ptr->ref_count--;
411       return;
412     }
413
414   } else {
415     int open_flags;
416     /* We need to allocate a new file_fd_struct (this increments the
417        ref_count). */
418     if((fd_ptr = fd_get_new()) == 0)
419       return;
420     /*
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.
429      */
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);
434     /*
435      * On some systems opening a file for R/W access on a read only
436      * filesystems sets errno to EROFS.
437      */
438 #ifdef EROFS
439     if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
440 #else /* No EROFS */
441     if((fd_ptr->fd == -1) && (errno == EACCES)) {
442 #endif /* EROFS */
443       if(accmode != O_RDWR) {
444         fd_ptr->fd = fd_attempt_open(fname, open_flags|accmode, mode);
445         fd_ptr->real_open_flags = accmode;
446       }
447     }
448   }
449
450   if ((fd_ptr->fd >=0) && 
451       conn->printer && lp_minprintspace(SNUM(conn))) {
452     pstring dname;
453     int dum1,dum2,dum3;
454     char *p;
455     pstrcpy(dname,fname);
456     p = strrchr(dname,'/');
457     if (p) *p = 0;
458     if (sys_disk_free(dname,&dum1,&dum2,&dum3) < 
459         lp_minprintspace(SNUM(conn))) {
460       fd_attempt_close(fd_ptr);
461       fsp->fd_ptr = 0;
462       if(fd_ptr->ref_count == 0)
463         dos_unlink(fname);
464       errno = ENOSPC;
465       return;
466     }
467   }
468     
469   if (fd_ptr->fd < 0)
470   {
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);
476     return;
477   }
478
479   if (fd_ptr->fd >= 0)
480   {
481     if(sbuf == 0) {
482       /* Do the fstat */
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);
489         return;
490       }
491       sbuf = &statbuf;
492     }
493
494     /* Set the correct entries in fd_ptr. */
495     fd_ptr->dev = sbuf->st_dev;
496     fd_ptr->inode = sbuf->st_ino;
497
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;
503     fsp->size = 0;
504     fsp->pos = -1;
505     fsp->open = True;
506     fsp->mmap_ptr = NULL;
507     fsp->mmap_size = 0;
508     fsp->can_lock = True;
509     fsp->can_read = ((flags & O_WRONLY)==0);
510     fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
511     fsp->share_mode = 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;
517     fsp->conn = conn;
518     /*
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.
524      */
525     string_set(&fsp->fsp_name,fname);
526     fsp->wbmpx_ptr = NULL;      
527
528     /*
529      * If the printer is marked as postscript output a leading
530      * file identifier to ensure the file is treated as a raw
531      * postscript file.
532      * This has a similar effect as CtrlD=0 in WIN.INI file.
533      * tim@fsg.com 09/06/94
534      */
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);
538     }
539       
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));
544
545   }
546
547 #if WITH_MMAP
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);
553
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;
558           }
559   }
560 #endif
561 }
562
563
564 /****************************************************************************
565   C. Hoch 11/22/95
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, 
570                                    BOOL *share_locked)
571 {
572   if (fsp->can_write){
573 #ifdef LARGE_SMB_OFF_T
574     if (is_locked(fsp,conn,0x3FFFFFFFFFFFFFFFLL,0,F_WRLCK)){
575 #else
576     if (is_locked(fsp,conn,0x3FFFFFFF,0,F_WRLCK)){
577 #endif
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;
586       errno = EACCES;
587       unix_ERR_class = ERRDOS;
588       unix_ERR_code = ERRlock;
589     }
590     else
591       sys_ftruncate(fsp->fd_ptr->fd,0); 
592   }
593 }
594
595
596
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)
602 {
603   int flags=0;
604   int flags2=0;
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;
610   int token;
611   SMB_DEV_T dev = 0;
612   SMB_INO_T inode = 0;
613   int num_share_modes = 0;
614
615   fsp->open = False;
616   fsp->fd_ptr = 0;
617
618   /* this is for OS/2 EAs - try and say we don't support them */
619   if (strstr(fname,".+,;=[].")) 
620   {
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 */
628
629     return;
630   }
631
632   if ((ofun & 0x3) == 0 && file_existed)  
633   {
634     errno = EEXIST;
635     return;
636   }
637       
638   if (ofun & 0x10)
639     flags2 |= O_CREAT;
640   if ((ofun & 0x3) == 2)
641     flags2 |= O_TRUNC;
642
643   /* note that we ignore the append flag as 
644      append does not mean the same thing under dos and unix */
645
646   switch (share_mode&0xF)
647   {
648     case 1: 
649       flags = O_WRONLY; 
650       break;
651     case 0xF: 
652       fcbopen = True;
653       flags = O_RDWR; 
654       break;
655     case 2: 
656       flags = O_RDWR; 
657       break;
658     default:
659       flags = O_RDONLY;
660       break;
661   }
662
663 #if defined(O_SYNC)
664   if (share_mode&(1<<14)) {
665           flags2 |= O_SYNC;
666   }
667 #endif /* O_SYNC */
668   
669   if (flags != O_RDONLY && file_existed && 
670       (!CAN_WRITE(conn) || IS_DOS_READONLY(dos_mode(conn,fname,&sbuf)))) 
671   {
672     if (!fcbopen) 
673     {
674       errno = EACCES;
675       return;
676     }
677     flags = O_RDONLY;
678   }
679
680   if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) 
681   {
682     DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
683     errno = EINVAL;
684     return;
685   }
686
687   if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
688
689   if (lp_share_modes(SNUM(conn))) 
690   {
691     int i;
692     share_mode_entry *old_shares = 0;
693
694     if (file_existed)
695     {
696       dev = sbuf.st_dev;
697       inode = sbuf.st_ino;
698       lock_share_entry(conn, dev, inode, &token);
699       share_locked = True;
700       num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares);
701     }
702
703     /*
704      * Check if the share modes will give us access.
705      */
706
707     if(share_locked && (num_share_modes != 0))
708     {
709       BOOL broke_oplock;
710
711       do
712       {
713
714         broke_oplock = False;
715         for(i = 0; i < num_share_modes; i++)
716         {
717           share_mode_entry *share_entry = &old_shares[i];
718
719           /* 
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. 
725            */
726           if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
727           {
728
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 */
736
737             /* Oplock break.... */
738             unlock_share_entry(conn, dev, inode, token);
739             if(request_oplock_break(share_entry, dev, inode) == False)
740             {
741               free((char *)old_shares);
742
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 */
750
751               errno = EACCES;
752               unix_ERR_class = ERRDOS;
753               unix_ERR_code = ERRbadshare;
754               return;
755             }
756             lock_share_entry(conn, dev, inode, &token);
757             broke_oplock = True;
758             break;
759           }
760
761           /* someone else has a share lock on it, check to see 
762              if we can too */
763           if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False)
764           {
765             free((char *)old_shares);
766             unlock_share_entry(conn, dev, inode, token);
767             errno = EACCES;
768             unix_ERR_class = ERRDOS;
769             unix_ERR_code = ERRbadshare;
770             return;
771           }
772
773         } /* end for */
774
775         if(broke_oplock)
776         {
777           free((char *)old_shares);
778           num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares);
779         }
780       } while(broke_oplock);
781     }
782
783     if(old_shares != 0)
784       free((char *)old_shares);
785   }
786
787   DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
788            flags,flags2,mode));
789
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) 
792   {
793     flags = O_RDONLY;
794     open_file(fsp,conn,fname,flags,mode,file_existed ? &sbuf : 0 );
795   }
796
797   if (fsp->open) 
798   {
799     int open_mode=0;
800
801     if((share_locked == False) && lp_share_modes(SNUM(conn)))
802     {
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);
807       share_locked = True;
808     }
809
810     switch (flags) 
811     {
812       case O_RDONLY:
813         open_mode = 0;
814         break;
815       case O_RDWR:
816         open_mode = 2;
817         break;
818       case O_WRONLY:
819         open_mode = 1;
820         break;
821     }
822
823     fsp->share_mode = (deny_mode<<4) | open_mode;
824
825     if (Access)
826       (*Access) = open_mode;
827
828     if (action) 
829     {
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;
833     }
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).
837      */
838     if (lp_share_modes(SNUM(conn)))
839     {
840       uint16 port = 0;
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
844          oplocks). */
845
846       if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(conn)) && 
847               !IS_VETO_OPLOCK_PATH(conn,fname))
848       {
849         fsp->granted_oplock = True;
850         fsp->sent_oplock_break = False;
851         global_oplocks_open++;
852         port = oplock_port;
853
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 */
861
862       }
863       else
864       {
865         port = 0;
866         oplock_request = 0;
867       }
868       set_share_mode(token, fsp, port, oplock_request);
869     }
870
871     if ((flags2&O_TRUNC) && file_existed)
872       truncate_unless_locked(fsp,conn,token,&share_locked);
873   }
874
875   if (share_locked && lp_share_modes(SNUM(conn)))
876     unlock_share_entry( conn, dev, inode, token);
877 }
878
879
880
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)
886 {
887         extern struct current_user current_user;
888         SMB_STRUCT_STAT st;
889
890         if (smb_ofun & 0x10) {
891                 /*
892                  * Create the directory.
893                  */
894
895                 if(dos_mkdir(fname, unixmode) < 0) {
896                         DEBUG(0,("open_directory: unable to create %s. Error was %s\n",
897                                  fname, strerror(errno) ));
898                         return -1;
899                 }
900
901                 *action = FILE_WAS_CREATED;
902         } else {
903                 /*
904                  * Check that it *was* a directory.
905                  */
906
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) ));
910                         return -1;
911                 }
912
913                 if(!S_ISDIR(st.st_mode)) {
914                         DEBUG(0,("open_directory: %s is not a directory !\n", fname ));
915                         return -1;
916                 }
917                 *action = FILE_WAS_OPENED;
918         }
919         
920         DEBUG(5,("open_directory: opening directory %s\n",
921                  fname));
922
923         /*
924          * Setup the files_struct for it.
925          */
926         
927         fsp->fd_ptr = NULL;
928         conn->num_files_open++;
929         fsp->mode = 0;
930         GetTimeOfDay(&fsp->open_time);
931         fsp->vuid = current_user.vuid;
932         fsp->size = 0;
933         fsp->pos = -1;
934         fsp->open = True;
935         fsp->mmap_ptr = NULL;
936         fsp->mmap_size = 0;
937         fsp->can_lock = True;
938         fsp->can_read = False;
939         fsp->can_write = False;
940         fsp->share_mode = 0;
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;
946         fsp->conn = conn;
947         /*
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.
953          */
954         string_set(&fsp->fsp_name,fname);
955         fsp->wbmpx_ptr = NULL;
956
957         return 0;
958 }
959
960 enum {AFAIL,AREAD,AWRITE,AALL};
961
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)
967 {
968   if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
969
970   if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
971     int pid = getpid();
972     if (old_deny == new_deny && share_pid == pid) 
973         return(AALL);    
974
975     if (old_mode == 0) return(AREAD);
976
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"))
986         return(AREAD);
987     }
988
989     return(AFAIL);
990   }
991
992   switch (new_deny) 
993     {
994     case DENY_WRITE:
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);
998       return(AFAIL);
999     case DENY_READ:
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);
1003       return(AFAIL);
1004     case DENY_NONE:
1005       if (old_deny==DENY_WRITE) return(AREAD);
1006       if (old_deny==DENY_READ) return(AWRITE);
1007       if (old_deny==DENY_NONE) return(AALL);
1008       return(AFAIL);      
1009     }
1010   return(AFAIL);      
1011 }
1012
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)
1018 {
1019   int i;
1020   int ret = False;
1021   share_mode_entry *old_shares = 0;
1022   int num_share_modes;
1023   SMB_STRUCT_STAT sbuf;
1024   int token;
1025   int pid = getpid();
1026   SMB_DEV_T dev;
1027   SMB_INO_T inode;
1028
1029   if(!lp_share_modes(SNUM(conn)))
1030     return True;
1031
1032   if (dos_stat(fname,&sbuf) == -1) return(True);
1033
1034   dev = sbuf.st_dev;
1035   inode = sbuf.st_ino;
1036
1037   lock_share_entry(conn, dev, inode, &token);
1038   num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares);
1039
1040   /*
1041    * Check if the share modes will give us access.
1042    */
1043
1044   if(num_share_modes != 0)
1045   {
1046     BOOL broke_oplock;
1047
1048     do
1049     {
1050
1051       broke_oplock = False;
1052       for(i = 0; i < num_share_modes; i++)
1053       {
1054         share_mode_entry *share_entry = &old_shares[i];
1055
1056         /* 
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. 
1061          */
1062         if(share_entry->op_type & BATCH_OPLOCK)
1063         {
1064
1065           /*
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.
1076            */
1077           if(rename_op && (share_entry->pid == pid))
1078           {
1079
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 */
1087
1088             /* 
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.
1095              */ 
1096             continue;
1097           }
1098           else
1099           {
1100
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 */
1108
1109             /* Oplock break.... */
1110             unlock_share_entry(conn, dev, inode, token);
1111             if(request_oplock_break(share_entry, dev, inode) == False)
1112             {
1113               free((char *)old_shares);
1114
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 */
1122
1123               return False;
1124             }
1125             lock_share_entry(conn, dev, inode, &token);
1126             broke_oplock = True;
1127             break;
1128           }
1129         }
1130
1131         /* someone else has a share lock on it, check to see 
1132            if we can too */
1133         if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid))
1134           goto free_and_exit;
1135
1136       } /* end for */
1137
1138       if(broke_oplock)
1139       {
1140         free((char *)old_shares);
1141         num_share_modes = get_share_modes(conn, token, dev, inode, &old_shares);
1142       }
1143     } while(broke_oplock);
1144   }
1145
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() */
1150   ret = True;
1151
1152 free_and_exit:
1153
1154   unlock_share_entry(conn, dev, inode, token);
1155   if(old_shares != NULL)
1156     free((char *)old_shares);
1157   return(ret);
1158 }
1159
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)
1165 {
1166   int old_open_mode = share->share_mode &0xF;
1167   int old_deny_mode = (share->share_mode >>4)&7;
1168
1169   if (old_deny_mode > 4 || old_open_mode > 2)
1170   {
1171     DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
1172                deny_mode,old_deny_mode,old_open_mode,fname));
1173     return False;
1174   }
1175
1176   {
1177     int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
1178                                 share->pid,fname);
1179
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))
1184     {
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));
1188       return False;
1189     }
1190
1191     if (access_allowed == AREAD)
1192       *flags = O_RDONLY;
1193
1194     if (access_allowed == AWRITE)
1195       *flags = O_WRONLY;
1196
1197   }
1198   return True;
1199 }
1200