Unix SMB/Netbios implementation.
Version 1.9.
Main SMB server routines
- Copyright (C) Andrew Tridgell 1992-1995
+ Copyright (C) Andrew Tridgell 1992-1997
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
pstring servicesf = CONFIGFILE;
extern pstring debugf;
extern pstring sesssetup_user;
+extern fstring myworkgroup;
char *InBuffer = NULL;
char *OutBuffer = NULL;
int am_parent = 1;
int atexit_set = 0;
-BOOL share_mode_pending = False;
-
/* the last message the was processed */
int last_message = -1;
extern int Protocol;
-int maxxmit = BUFFER_SIZE;
+/*
+ * Size of data we can send to client. Set
+ * by the client for all protocols above CORE.
+ * Set by us for CORE protocol.
+ */
+int max_send = BUFFER_SIZE;
+/*
+ * Size of the data we can receive. Set by us.
+ * Can be modified by the max xmit parameter.
+ */
+int max_recv = BUFFER_SIZE;
/* a fnum to use when chaining */
int chain_fnum = -1;
void *dflt_sig(void)
{
exit_server("caught signal");
+ return 0; /* Keep -Wall happy :-) */
}
/****************************************************************************
Send a SIGTERM to our process group.
dos archive is represented in unix by the user's execute bit
dos system is represented in unix by the group's execute bit
dos hidden is represented in unix by the other's execute bit
+ Then apply create mask,
+ then add force bits.
base permission for directories:
dos directory is represented in unix by unix's dir bit and the exec bit
+ Then apply create mask,
+ then add force bits.
****************************************************************************/
mode_t unix_mode(int cnum,int dosmode)
{
if ( !IS_DOS_READONLY(dosmode) )
result |= (S_IWUSR | S_IWGRP | S_IWOTH);
- if (IS_DOS_DIR(dosmode))
+ if (IS_DOS_DIR(dosmode)) {
+ /* We never make directories read only for the owner as under DOS a user
+ can always create a file in a read-only directory. */
result |= (S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH | S_IWUSR);
+ /* Apply directory mask */
+ result &= lp_dir_mode(SNUM(cnum));
+ /* Add in force bits */
+ result |= lp_force_dir_mode(SNUM(cnum));
+ } else {
+ if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
+ result |= S_IXUSR;
+
+ if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
+ result |= S_IXGRP;
- if (MAP_ARCHIVE(cnum) && IS_DOS_ARCHIVE(dosmode))
- result |= S_IXUSR;
-
- if (MAP_SYSTEM(cnum) && IS_DOS_SYSTEM(dosmode))
- result |= S_IXGRP;
-
- if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
- result |= S_IXOTH;
+ if (MAP_HIDDEN(cnum) && IS_DOS_HIDDEN(dosmode))
+ result |= S_IXOTH;
- result &= CREATE_MODE(cnum);
+ /* Apply mode mask */
+ result &= lp_create_mode(SNUM(cnum));
+ /* Add in force bits */
+ result |= lp_force_create_mode(SNUM(cnum));
+ }
return(result);
}
int result = 0;
extern struct current_user current_user;
+ DEBUG(5,("dos_mode: %d %s\n", cnum, path));
+
if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
if (!((sbuf->st_mode & S_IWOTH) ||
Connections[cnum].admin_user ||
result |= aHIDDEN;
}
+ /* Optimization : Only call is_hidden_path if it's not already
+ hidden. */
+ if (!(result & aHIDDEN) && is_hidden_path(SNUM(cnum), path))
+ {
+ result |= aHIDDEN;
+ }
+
+ DEBUG(5,("dos_mode returning "));
+
+ if (result & aHIDDEN) DEBUG(5, ("h"));
+ if (result & aRONLY ) DEBUG(5, ("r"));
+ if (result & aSYSTEM) DEBUG(5, ("s"));
+ if (result & aDIR ) DEBUG(5, ("d"));
+ if (result & aARCH ) DEBUG(5, ("a"));
+
+ DEBUG(5,("\n"));
+
return(result);
}
{
pstring tmpname;
- if (is_8_3(name2))
+ if (is_8_3(name2, True))
return(False);
strcpy(tmpname,name2);
check_mangled_stack(name);
/* open the directory */
- if (!(cur_dir = OpenDir(path)))
+ if (!(cur_dir = OpenDir(snum, path, True)))
{
DEBUG(3,("scan dir didn't open dir [%s]\n",path));
return(False);
if (!name_map_mangle(name2,False,snum)) continue;
if ((mangled && mangled_equal(name,name2))
- || fname_equal(name, name2))
+ || fname_equal(name, dname))
{
/* we've found the file, change it's name and return */
if (docache) DirCacheAdd(path,name,dname,snum);
unix_format(name);
unix_clean_name(name);
- if (!case_sensitive &&
- (!case_preserve || (is_8_3(name) && !short_case_preserve)))
- strnorm(name);
-
/* names must be relative to the root of the service - trim any leading /.
also trim trailing /'s */
trim_string(name,"/","/");
+ /*
+ * Ensure saved_last_component is valid even if file exists.
+ */
+ if(saved_last_component) {
+ end = strrchr(name, '/');
+ if(end)
+ strcpy(saved_last_component, end + 1);
+ else
+ strcpy(saved_last_component, name);
+ }
+
+ if (!case_sensitive &&
+ (!case_preserve || (is_8_3(name, False) && !short_case_preserve)))
+ strnorm(name);
+
/* check if it's a printer file */
if (Connections[cnum].printer)
{
- if ((! *name) || strchr(name,'/') || !is_8_3(name))
+ if ((! *name) || strchr(name,'/') || !is_8_3(name, True))
{
char *s;
fstring name2;
return(True);
}
- /*
- * Ensure saved_last_component is valid even if file exists.
- */
- if(saved_last_component) {
- end = strrchr(name, '/');
- if(end)
- strcpy(saved_last_component, end + 1);
- else
- strcpy(saved_last_component, name);
- }
-
/* stat the name - if it exists then we are all done! */
if (sys_stat(name,&st) == 0)
return(True);
int disk_free(char *path,int *bsize,int *dfree,int *dsize)
{
char *df_command = lp_dfree_command();
+ int dfree_retval;
+#ifdef QUOTAS
+ int dfreeq_retval;
+ int dfreeq = 0;
+ int bsizeq = *bsize;
+ int dsizeq = *dsize;
+#endif
+
#ifndef NO_STATFS
#ifdef USE_STATVFS
struct statvfs fs;
#endif
#endif
-#ifdef QUOTAS
- if (disk_quotas(path, bsize, dfree, dsize))
- {
- disk_norm(bsize,dfree,dsize);
- return(((*bsize)/1024)*(*dfree));
- }
-#endif
-
-
/* possibly use system() to get the result */
if (df_command && *df_command)
{
DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));
{
- FILE *f = fopen(outfile,"r");
- *dsize = 0;
- *dfree = 0;
- *bsize = 1024;
- if (f)
- {
- fscanf(f,"%d %d %d",dsize,dfree,bsize);
- fclose(f);
- }
- else
- DEBUG(0,("Can't open %s\n",outfile));
+ FILE *f = fopen(outfile,"r");
+ *dsize = 0;
+ *dfree = 0;
+ *bsize = 1024;
+ if (f)
+ {
+ fscanf(f,"%d %d %d",dsize,dfree,bsize);
+ fclose(f);
+ }
+ else
+ DEBUG(0,("Can't open %s\n",outfile));
}
unlink(outfile);
disk_norm(bsize,dfree,dsize);
- return(((*bsize)/1024)*(*dfree));
+ dfree_retval = ((*bsize)/1024)*(*dfree);
+#ifdef QUOTAS
+ /* Ensure we return the min value between the users quota and
+ what's free on the disk. Thanks to Albrecht Gebhardt
+ <albrecht.gebhardt@uni-klu.ac.at> for this fix.
+ */
+ if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
+ {
+ disk_norm(&bsizeq, &dfreeq, &dsizeq);
+ dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
+ dfree_retval = ( dfree_retval < dfreeq_retval ) ?
+ dfree_retval : dfreeq_retval ;
+ /* maybe dfree and dfreeq are calculated using different bsizes
+ so convert dfree from bsize into bsizeq */
+ *dfree = ((*dfree) * (*bsize)) / (bsizeq);
+ *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
+ *bsize = bsizeq;
+ *dsize = dsizeq;
+ }
+#endif
+ return(dfree_retval);
}
#ifdef NO_STATFS
*dsize = 20*1024*1024/(*bsize);
*dfree = MAX(1,*dfree);
}
- return(((*bsize)/1024)*(*dfree));
+ dfree_retval = ((*bsize)/1024)*(*dfree);
+#ifdef QUOTAS
+ /* Ensure we return the min value between the users quota and
+ what's free on the disk. Thanks to Albrecht Gebhardt
+ <albrecht.gebhardt@uni-klu.ac.at> for this fix.
+ */
+ if (disk_quotas(path, &bsizeq, &dfreeq, &dsizeq))
+ {
+ disk_norm(&bsizeq, &dfreeq, &dsizeq);
+ dfreeq_retval = ((bsizeq)/1024)*(dfreeq);
+ dfree_retval = ( dfree_retval < dfreeq_retval ) ?
+ dfree_retval : dfreeq_retval ;
+ /* maybe dfree and dfreeq are calculated using different bsizes
+ so convert dfree from bsize into bsizeq */
+ *dfree = ((*dfree) * (*bsize)) / (bsizeq);
+ *dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
+ *bsize = bsizeq;
+ *dsize = dsizeq;
+ }
+#endif
+ return(dfree_retval);
#endif
}
errno = 0;
- if( is_vetoed_path(name))
+ if( is_vetoed_name(SNUM(cnum), name))
{
DEBUG(5,("file path name %s vetoed\n",name));
return(0);
for(i = 0; i <= max_file_fd_used; i++) {
fd_ptr = &FileFd[i];
if((fd_ptr->ref_count > 0) &&
- (((int32)sbuf->st_dev) == fd_ptr->dev) &&
- (((int32)sbuf->st_ino) == fd_ptr->inode)) {
+ (((uint32)sbuf->st_dev) == fd_ptr->dev) &&
+ (((uint32)sbuf->st_ino) == fd_ptr->inode)) {
fd_ptr->ref_count++;
DEBUG(3,
("Re-used file_fd_struct %d, dev = %x, inode = %x, ref_count = %d\n",
for(i = 0; i < MAX_OPEN_FILES; i++) {
fd_ptr = &FileFd[i];
if(fd_ptr->ref_count == 0) {
- fd_ptr->dev = (int32)-1;
- fd_ptr->inode = (int32)-1;
+ fd_ptr->dev = (uint32)-1;
+ fd_ptr->inode = (uint32)-1;
fd_ptr->fd = -1;
fd_ptr->fd_readonly = -1;
fd_ptr->fd_writeonly = -1;
fd_ptr->fd_readonly = -1;
fd_ptr->fd_writeonly = -1;
fd_ptr->real_open_flags = -1;
- fd_ptr->dev = -1;
- fd_ptr->inode = -1;
+ fd_ptr->dev = (uint32)-1;
+ fd_ptr->inode = (uint32)-1;
}
}
return fd_ptr->ref_count;
/****************************************************************************
open a file
****************************************************************************/
-void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
+static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct stat *sbuf)
{
extern struct current_user current_user;
pstring fname;
return;
}
- /*
- * If O_TRUNC was set, ensure we truncate the file.
- * open_file_shared explicitly clears this flag before
- * calling open_file, so we can safely do this here.
- */
- if(flags & O_TRUNC)
- ftruncate(fd_ptr->fd, 0);
-
} else {
int open_flags;
/* We need to allocate a new file_fd_struct (this increments the
/* Set the flags as needed without the read/write modes. */
open_flags = flags & ~(O_RDWR|O_WRONLY|O_RDONLY);
fd_ptr->fd = fd_attempt_open(fname, open_flags|O_RDWR, mode);
+ /*
+ * On some systems opening a file for R/W access on a read only
+ * filesystems sets errno to EROFS.
+ */
+#ifdef EROFS
+ if((fd_ptr->fd == -1) && ((errno == EACCES) || (errno == EROFS))) {
+#else /* No EROFS */
if((fd_ptr->fd == -1) && (errno == EACCES)) {
+#endif /* EROFS */
if(flags & O_WRONLY) {
fd_ptr->fd = fd_attempt_open(fname, open_flags|O_WRONLY, mode);
fd_ptr->real_open_flags = O_WRONLY;
sbuf = &statbuf;
}
/* Set the correct entries in fd_ptr. */
- fd_ptr->dev = (int32)sbuf->st_dev;
- fd_ptr->inode = (int32)sbuf->st_ino;
+ fd_ptr->dev = (uint32)sbuf->st_dev;
+ fd_ptr->inode = (uint32)sbuf->st_ino;
Files[fnum].fd_ptr = fd_ptr;
Connections[cnum].num_files_open++;
Files[fnum].can_read = ((flags & O_WRONLY)==0);
Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
Files[fnum].share_mode = 0;
- Files[fnum].share_pending = False;
Files[fnum].print_file = Connections[cnum].printer;
Files[fnum].modified = False;
Files[fnum].cnum = cnum;
{
Files[fnum].mmap_size = file_size(fname);
Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
- PROT_READ,MAP_SHARED,Files[fnum].fd,0);
+ PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0);
if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
{
****************************************************************************/
void close_file(int fnum)
{
- int cnum = Files[fnum].cnum;
- invalidate_read_prediction(Files[fnum].fd_ptr->fd);
- Files[fnum].open = False;
+ files_struct *fs_p = &Files[fnum];
+ int cnum = fs_p->cnum;
+ uint32 dev = fs_p->fd_ptr->dev;
+ uint32 inode = fs_p->fd_ptr->inode;
+ share_lock_token token;
+
+ invalidate_read_prediction(fs_p->fd_ptr->fd);
+ fs_p->open = False;
Connections[cnum].num_files_open--;
- if(Files[fnum].wbmpx_ptr)
+ if(fs_p->wbmpx_ptr)
{
- free((char *)Files[fnum].wbmpx_ptr);
- Files[fnum].wbmpx_ptr = NULL;
+ free((char *)fs_p->wbmpx_ptr);
+ fs_p->wbmpx_ptr = NULL;
}
#if USE_MMAP
- if(Files[fnum].mmap_ptr)
+ if(fs_p->mmap_ptr)
{
- munmap(Files[fnum].mmap_ptr,Files[fnum].mmap_size);
- Files[fnum].mmap_ptr = NULL;
+ munmap(fs_p->mmap_ptr,fs_p->mmap_size);
+ fs_p->mmap_ptr = NULL;
}
#endif
if (lp_share_modes(SNUM(cnum)))
- del_share_mode(fnum);
+ {
+ lock_share_entry( cnum, dev, inode, &token);
+ del_share_mode(token, fnum);
+ }
+
+ fd_attempt_close(fs_p->fd_ptr);
- fd_attempt_close(Files[fnum].fd_ptr);
+ if (lp_share_modes(SNUM(cnum)))
+ unlock_share_entry( cnum, dev, inode, token);
/* NT uses smbclose to start a print - weird */
- if (Files[fnum].print_file)
+ if (fs_p->print_file)
print_file(fnum);
/* check for magic scripts */
check_magic(fnum,cnum);
DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
- timestring(),Connections[cnum].user,Files[fnum].name,
+ timestring(),Connections[cnum].user,fs_p->name,
Connections[cnum].num_files_open));
}
********************************************************************/
BOOL check_file_sharing(int cnum,char *fname)
{
- int pid=0;
- int share_mode = get_share_mode_byname(cnum,fname,&pid);
+ int i;
+ int ret = False;
+ min_share_mode_entry *old_shares = 0;
+ int num_share_modes;
+ struct stat sbuf;
+ share_lock_token token;
+ int pid = getpid();
- if (!pid || !share_mode) return(True);
-
- if (share_mode == DENY_DOS)
- return(pid == getpid());
+ if(!lp_share_modes(SNUM(cnum)))
+ return True;
+
+ if (stat(fname,&sbuf) == -1) return(True);
+
+ lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token);
+ num_share_modes = get_share_modes(cnum, token,
+ (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares);
+
+ for( i = 0; i < num_share_modes; i++)
+ {
+ if (old_shares[i].share_mode != DENY_DOS)
+ goto free_and_exit;
+
+ if(old_shares[i].pid != pid)
+ goto free_and_exit;
+ }
/* XXXX exactly what share mode combinations should be allowed for
deleting/renaming? */
- return(False);
+ /* If we got here then either there were no share modes or
+ all share modes were DENY_DOS and the pid == getpid() */
+ ret = True;
+
+free_and_exit:
+
+ unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token);
+ if(old_shares != NULL)
+ free((char *)old_shares);
+ return(ret);
}
/****************************************************************************
Helper for open_file_shared.
Truncate a file after checking locking; close file if locked.
**************************************************************************/
-static void truncate_unless_locked(int fnum, int cnum)
+static void truncate_unless_locked(int fnum, int cnum, share_lock_token token,
+ BOOL *share_locked)
{
if (Files[fnum].can_write){
if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
+ /* If share modes are in force for this connection we
+ have the share entry locked. Unlock it before closing. */
+ if (*share_locked && lp_share_modes(SNUM(cnum)))
+ unlock_share_entry( cnum, Files[fnum].fd_ptr->dev,
+ Files[fnum].fd_ptr->inode, token);
close_file(fnum);
+ /* Share mode no longer locked. */
+ *share_locked = False;
errno = EACCES;
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRlock;
void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
int mode,int *Access,int *action)
{
+ files_struct *fs_p = &Files[fnum];
int flags=0;
int flags2=0;
int deny_mode = (share_mode>>4)&7;
struct stat sbuf;
BOOL file_existed = file_exist(fname,&sbuf);
+ BOOL share_locked = False;
BOOL fcbopen = False;
- int share_pid=0;
+ share_lock_token token;
+ uint32 dev = 0;
+ uint32 inode = 0;
- Files[fnum].open = False;
- Files[fnum].fd_ptr = 0;
+ fs_p->open = False;
+ fs_p->fd_ptr = 0;
/* this is for OS/2 EAs - try and say we don't support them */
- if (strstr(fname,".+,;=[].")) {
+ if (strstr(fname,".+,;=[]."))
+ {
unix_ERR_class = ERRDOS;
unix_ERR_code = ERROR_EAS_NOT_SUPPORTED;
return;
}
- if ((ofun & 0x3) == 0 && file_existed) {
+ if ((ofun & 0x3) == 0 && file_existed)
+ {
errno = EEXIST;
return;
}
append does not mean the same thing under dos and unix */
switch (share_mode&0xF)
- {
+ {
case 1:
flags = O_WRONLY;
break;
default:
flags = O_RDONLY;
break;
- }
+ }
if (flags != O_RDONLY && file_existed &&
- (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf)))) {
- if (!fcbopen) {
+ (!CAN_WRITE(cnum) || IS_DOS_READONLY(dos_mode(cnum,fname,&sbuf))))
+ {
+ if (!fcbopen)
+ {
errno = EACCES;
return;
}
flags = O_RDONLY;
}
- if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB) {
+ if (deny_mode > DENY_NONE && deny_mode!=DENY_FCB)
+ {
DEBUG(2,("Invalid deny mode %d on file %s\n",deny_mode,fname));
errno = EINVAL;
return;
if (deny_mode == DENY_FCB) deny_mode = DENY_DOS;
- if (lp_share_modes(SNUM(cnum))) {
- int old_share=0;
+ if (lp_share_modes(SNUM(cnum)))
+ {
+ int num_shares = 0;
+ int i;
+ min_share_mode_entry *old_shares = 0;
+
if (file_existed)
- old_share = get_share_mode(cnum,&sbuf,&share_pid);
+ {
+ dev = (uint32)sbuf.st_dev;
+ inode = (uint32)sbuf.st_ino;
+ lock_share_entry(cnum, dev, inode, &token);
+ share_locked = True;
+ num_shares = get_share_modes(cnum, token, dev, inode, &old_shares);
+ }
- if (share_pid) {
+ for(i = 0; i < num_shares; i++)
+ {
/* someone else has a share lock on it, check to see
if we can too */
- int old_open_mode = old_share&0xF;
- int old_deny_mode = (old_share>>4)&7;
+ int old_open_mode = old_shares[i].share_mode &0xF;
+ int old_deny_mode = (old_shares[i].share_mode >>4)&7;
- if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2) {
+ if (deny_mode > 4 || old_deny_mode > 4 || old_open_mode > 2)
+ {
DEBUG(2,("Invalid share mode (%d,%d,%d) on file %s\n",
deny_mode,old_deny_mode,old_open_mode,fname));
+ free((char *)old_shares);
+ if(share_locked)
+ unlock_share_entry(cnum, dev, inode, token);
errno = EACCES;
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRbadshare;
{
int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
- share_pid,fname);
+ old_shares[i].pid,fname);
if ((access_allowed == AFAIL) ||
(!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
(access_allowed == AREAD && flags == O_WRONLY) ||
- (access_allowed == AWRITE && flags == O_RDONLY)) {
+ (access_allowed == AWRITE && flags == O_RDONLY))
+ {
DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
deny_mode,old_deny_mode,old_open_mode,
- share_pid,fname,
+ old_shares[i].pid,fname,
access_allowed));
+ free((char *)old_shares);
+ if(share_locked)
+ unlock_share_entry(cnum, dev, inode, token);
errno = EACCES;
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRbadshare;
return;
- }
+ }
if (access_allowed == AREAD)
flags = O_RDONLY;
flags = O_WRONLY;
}
}
+ if(old_shares != 0)
+ free((char *)old_shares);
}
DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n",
flags,flags2,mode));
open_file(fnum,cnum,fname,flags|(flags2&~(O_TRUNC)),mode,file_existed ? &sbuf : 0);
- if (!Files[fnum].open && flags==O_RDWR && errno!=ENOENT && fcbopen) {
+ if (!fs_p->open && flags==O_RDWR && errno!=ENOENT && fcbopen)
+ {
flags = O_RDONLY;
open_file(fnum,cnum,fname,flags,mode,file_existed ? &sbuf : 0 );
}
- if (Files[fnum].open) {
+ if (fs_p->open)
+ {
int open_mode=0;
- switch (flags) {
- case O_RDONLY:
- open_mode = 0;
- break;
- case O_RDWR:
- open_mode = 2;
- break;
- case O_WRONLY:
- open_mode = 1;
- break;
+
+ if((share_locked == False) && lp_share_modes(SNUM(cnum)))
+ {
+ /* We created the file - thus we must now lock the share entry before creating it. */
+ dev = fs_p->fd_ptr->dev;
+ inode = fs_p->fd_ptr->inode;
+ lock_share_entry(cnum, dev, inode, &token);
+ share_locked = True;
}
- Files[fnum].share_mode = (deny_mode<<4) | open_mode;
- Files[fnum].share_pending = True;
+ switch (flags)
+ {
+ case O_RDONLY:
+ open_mode = 0;
+ break;
+ case O_RDWR:
+ open_mode = 2;
+ break;
+ case O_WRONLY:
+ open_mode = 1;
+ break;
+ }
+
+ fs_p->share_mode = (deny_mode<<4) | open_mode;
- if (Access) {
+ if (Access)
(*Access) = open_mode;
- }
-
- if (action) {
+
+ if (action)
+ {
if (file_existed && !(flags2 & O_TRUNC)) *action = 1;
if (!file_existed) *action = 2;
if (file_existed && (flags2 & O_TRUNC)) *action = 3;
}
-
- if (!share_pid)
- share_mode_pending = True;
+ /* We must create the share mode entry before truncate as
+ truncate can fail due to locking and have to close the
+ file (which expects the share_mode_entry to be there).
+ */
+ if (lp_share_modes(SNUM(cnum)))
+ set_share_mode(token, fnum);
if ((flags2&O_TRUNC) && file_existed)
- truncate_unless_locked(fnum,cnum);
+ truncate_unless_locked(fnum,cnum,token,&share_locked);
}
-}
-
-
-/*******************************************************************
-check for files that we should now set our share modes on
-********************************************************************/
-static void check_share_modes(void)
-{
- int i;
- for (i=0;i<MAX_OPEN_FILES;i++)
- if(Files[i].open && Files[i].share_pending) {
- if (lp_share_modes(SNUM(Files[i].cnum))) {
- int pid=0;
- get_share_mode_by_fnum(Files[i].cnum,i,&pid);
- if (!pid) {
- set_share_mode(i,Files[i].share_mode);
- Files[i].share_pending = False;
- }
- } else {
- Files[i].share_pending = False;
- }
- }
+ if (share_locked && lp_share_modes(SNUM(cnum)))
+ unlock_share_entry( cnum, dev, inode, token);
}
-
/****************************************************************************
seek a file. Try to avoid the seek if possible
****************************************************************************/
/* ready to listen */
if (listen(s, 5) == -1)
{
- DEBUG(0,("listen: %s",strerror(errno)));
+ DEBUG(0,("listen: %s\n",strerror(errno)));
close(s);
return False;
}
if (Client == -1)
{
- DEBUG(0,("accept: %s",strerror(errno)));
+ DEBUG(0,("accept: %s\n",strerror(errno)));
continue;
}
#else
if (Client != -1 && fork()==0)
{
+ /* Child code ... */
#ifndef NO_SIGNAL_TEST
signal(SIGPIPE, SIGNAL_CAST sig_pipe);
signal(SIGCLD, SIGNAL_CAST SIG_DFL);
set_socket_options(Client,"SO_KEEPALIVE");
set_socket_options(Client,user_socket_options);
+ /* Reset global variables in util.c so that
+ client substitutions will be done correctly
+ in the process.
+ */
+ reset_globals_after_fork();
return True;
}
close(Client); /* The parent doesn't need this socket */
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
+ /* We need to save and restore this as it can be destroyed
+ if we call another server if security=server
+ Thanks to Paul Nelson @ Thursby for pointing this out.
+ */
+ uint16 mid = SVAL(outbuf, smb_mid);
if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
}
CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
- SSVAL(outbuf,smb_vwv2,maxxmit);
+ SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
+ SSVAL(outbuf,smb_vwv2,max_recv);
SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
SSVAL(outbuf,smb_vwv4,1);
SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
+ /* We need to save and restore this as it can be destroyed
+ if we call another server if security=server
+ Thanks to Paul Nelson @ Thursby for pointing this out.
+ */
+ uint16 mid = SVAL(outbuf, smb_mid);
if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
}
CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
- SSVAL(outbuf,smb_vwv2,maxxmit);
+ SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
+ SSVAL(outbuf,smb_vwv2,max_recv);
SSVAL(outbuf,smb_vwv3,lp_maxmux());
SSVAL(outbuf,smb_vwv4,1);
SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
return (smb_len(outbuf)+4);
}
+
/****************************************************************************
reply for the nt protocol
****************************************************************************/
int reply_nt1(char *outbuf)
{
- int capabilities=0x300; /* has dual names + lock_and_read */
+ /* dual names + lock_and_read + nt SMBs + remote API calls */
+ int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ;
+/*
+ other valid capabilities which we may support at some time...
+ CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
+ CAP_LARGE_FILES|CAP_LARGE_READX|
+ CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
+ */
+
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
+ int data_len;
+ int encrypt_len;
+ char challenge_len = 8;
+ /* We need to save and restore this as it can be destroyed
+ if we call another server if security=server
+ Thanks to Paul Nelson @ Thursby for pointing this out.
+ */
+ uint16 mid = SVAL(outbuf, smb_mid);
+
+ if (lp_readraw() && lp_writeraw())
+ {
+ capabilities |= CAP_RAW_MODE;
+ }
if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
- set_message(outbuf,17,doencrypt?8:0,True);
+ /* decide where (if) to put the encryption challenge, and
+ follow it with the OEM'd domain name
+ */
+ encrypt_len = doencrypt?challenge_len:0;
+#if UNICODE
+ data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
+#else
+ data_len = encrypt_len + strlen(myworkgroup) + 1;
+#endif
+
+ set_message(outbuf,17,data_len,True);
+
+#if UNICODE
+ /* put the OEM'd domain name */
+ PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
+#else
+ strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
+#endif
+
CVAL(outbuf,smb_vwv1) = secword;
#ifdef SMB_PASSWD
/* Create a token value and add it to the outgoing packet. */
- if (doencrypt) {
+ if (doencrypt)
+ {
generate_next_challenge(smb_buf(outbuf));
+
/* Tell the nt machine how long the challenge is. */
- SSVALS(outbuf,smb_vwv16+1,8);
+ SSVALS(outbuf,smb_vwv16+1,challenge_len);
}
#endif
- SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
-
Protocol = PROTOCOL_NT1;
if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
#endif
}
- if (lp_readraw() && lp_writeraw())
- capabilities |= 1;
-
+ SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
- SIVAL(outbuf,smb_vwv3+1,0xFFFF); /* max buffer */
- SIVAL(outbuf,smb_vwv5+1,0xFFFF); /* raw size */
+ SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
+ SIVAL(outbuf,smb_vwv5+1,0xffff); /* raw size. LOTS! */
+ SIVAL(outbuf,smb_vwv7+1,getpid()); /* session key */
SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
put_long_date(outbuf+smb_vwv11+1,t);
SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
+ SSVAL(outbuf,smb_vwv17,data_len); /* length of challenge+domain strings */
return (smb_len(outbuf)+4);
}
-
/* these are the protocol lists used for auto architecture detection:
WinNT 3.51:
f = fopen(fname,"r+");
if (!f)
{
- DEBUG(2,("Coudn't open lock file %s (%s)\n",fname,strerror(errno)));
+ DEBUG(2,("Couldn't open lock file %s (%s)\n",fname,strerror(errno)));
return(False);
}
#endif
}
-#if FAST_SHARE_MODES
+#ifdef FAST_SHARE_MODES
stop_share_mode_mgmt();
-#endif
+#endif /* FAST_SHARE_MODES */
DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
exit(0);
int deadtime = lp_deadtime()*60;
int counter;
int last_keepalive=0;
+ int service_load_counter = 0;
if (deadtime <= 0)
deadtime = DEFAULT_SMBD_TIMEOUT;
if (lp_readprediction())
do_read_prediction();
- {
- extern pstring share_del_pending;
- if (*share_del_pending) {
- unbecome_user();
- if (!unlink(share_del_pending))
- DEBUG(3,("Share file deleted %s\n",share_del_pending));
- else
- DEBUG(2,("Share del failed of %s\n",share_del_pending));
- share_del_pending[0] = 0;
- }
- }
-
- if (share_mode_pending) {
- unbecome_user();
- check_share_modes();
- share_mode_pending=False;
- }
-
errno = 0;
for (counter=SMBD_SELECT_LOOP;
BOOL allidle = True;
extern int keepalive;
+ if (counter > 365 * 3600) /* big number of seconds. */
+ {
+ counter = 0;
+ service_load_counter = 0;
+ }
+
if (smb_read_error == READ_EOF) {
DEBUG(3,("end of file from client\n"));
return;
unbecome_user();
/* check for smb.conf reload */
- if (!(counter%SMBD_RELOAD_CHECK))
- reload_services(True);
+ if (counter >= service_load_counter + SMBD_RELOAD_CHECK)
+ {
+ service_load_counter = counter;
- /* check the share modes every 10 secs */
- if (!(counter%SHARE_MODES_CHECK))
- check_share_modes();
+ /* remove all unused services. reduce some of that memory overhead. */
+ lp_killunused(snum_used);
- /* clean the share modes every 5 minutes */
- if (!(counter%SHARE_MODES_CLEAN))
- clean_share_modes();
+ /* reload services, if files have changed. */
+ reload_services(True);
+ }
/* automatic timeout if all connections are closed */
if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
if (msg_type == 0)
show_msg(InBuffer);
- nread = construct_reply(InBuffer,OutBuffer,nread,maxxmit);
+ nread = construct_reply(InBuffer,OutBuffer,nread,max_send);
if(nread > 0) {
if (CVAL(OutBuffer,0) == 0)
setup_logging(argv[0],False);
- charset_initialise();
+ charset_initialise(-1);
/* make absolutely sure we run as root - to handle cases whre people
are crazy enough to have it setuid */
reopen_logs();
DEBUG(2,("%s smbd version %s started\n",timestring(),VERSION));
- DEBUG(2,("Copyright Andrew Tridgell 1992-1995\n"));
+ DEBUG(2,("Copyright Andrew Tridgell 1992-1997\n"));
#ifndef NO_GETRLIMIT
#ifdef RLIMIT_NOFILE
if (!reload_services(False))
return(-1);
+ charset_initialise(lp_client_code_page());
+
+ strcpy(myworkgroup, lp_workgroup());
+
#ifndef NO_SIGNAL_TEST
signal(SIGHUP,SIGNAL_CAST sig_hup);
#endif
if (!open_sockets(is_daemon,port))
exit(1);
-#if FAST_SHARE_MODES
+#ifdef FAST_SHARE_MODES
if (!start_share_mode_mgmt())
exit(1);
-#endif
+#endif /* FAST_SHARE_MODES */
/* possibly reload the services file. */
reload_services(True);
- maxxmit = MIN(lp_maxxmit(),BUFFER_SIZE);
+ max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
if (*lp_rootdir())
{