1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-25 06:04:04 +03:00
Jeremy Allison 389b700a26 Now that fsp's are created on successful file open, the structure member
fsp->open is no longer needed (if an fsp pointer is valid, then it's open :-).

NB for Luke, this patch also did not apply to TNG. TNG is not yet
identical w.r.t file serving with HEAD. This makes it impossible for
me to help maintain TNG. Please fix asap.

lib/substitute.c: Removed unused variable (pidstr).

Jeremy.
-

366 lines
9.5 KiB
C

/*
Unix SMB/Netbios implementation.
Version 1.9.
Files[] structure handling
Copyright (C) Andrew Tridgell 1998
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
extern int DEBUGLEVEL;
static int real_max_open_files;
#define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < real_max_open_files))
#define FILE_HANDLE_OFFSET 0x1000
static struct bitmap *file_bmap;
static files_struct *Files;
/* a fsp to use when chaining */
static files_struct *chain_fsp = NULL;
/* a fsp to use to save when breaking an oplock. */
static files_struct *oplock_save_chain_fsp = NULL;
static int files_used;
/****************************************************************************
find first available file slot
****************************************************************************/
files_struct *file_new(void )
{
int i;
static int first_file;
files_struct *fsp, *next;
/* we want to give out file handles differently on each new
connection because of a common bug in MS clients where they try to
reuse a file descriptor from an earlier smb connection. This code
increases the chance that the errant client will get an error rather
than causing corruption */
if (first_file == 0) {
first_file = (getpid() ^ (int)time(NULL)) % real_max_open_files;
}
i = bitmap_find(file_bmap, first_file);
if (i == -1) {
/*
* Before we give up, go through the open files
* and see if there are any files opened with a
* batch oplock. If so break the oplock and then
* re-use that entry (if it becomes closed).
* This may help as NT/95 clients tend to keep
* files batch oplocked for quite a long time
* after they have finished with them.
*/
for (fsp=Files;fsp;fsp=next) {
next=fsp->next;
if (attempt_close_oplocked_file(fsp)) {
return file_new();
}
}
DEBUG(0,("ERROR! Out of file structures\n"));
unix_ERR_class = ERRSRV;
unix_ERR_code = ERRnofids;
return NULL;
}
fsp = (files_struct *)malloc(sizeof(*fsp));
if (!fsp) {
unix_ERR_class = ERRSRV;
unix_ERR_code = ERRnofids;
return NULL;
}
ZERO_STRUCTP(fsp);
fsp->fd = -1;
first_file = (i+1) % real_max_open_files;
bitmap_set(file_bmap, i);
files_used++;
fsp->fnum = i + FILE_HANDLE_OFFSET;
string_set(&fsp->fsp_name,"");
DLIST_ADD(Files, fsp);
DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
i, fsp->fnum, files_used));
chain_fsp = fsp;
return fsp;
}
/****************************************************************************
close all open files for a connection
****************************************************************************/
void file_close_conn(connection_struct *conn)
{
files_struct *fsp, *next;
for (fsp=Files;fsp;fsp=next) {
next = fsp->next;
if (fsp->conn == conn) {
close_file(fsp,False);
}
}
}
/****************************************************************************
initialise file structures
****************************************************************************/
#define MAX_OPEN_FUDGEFACTOR 10
void file_init(void)
{
int request_max_open_files = lp_max_open_files();
int real_lim;
/*
* Set the max_open files to be the requested
* max plus a fudgefactor to allow for the extra
* fd's we need such as log files etc...
*/
real_lim = set_maxfiles(request_max_open_files + MAX_OPEN_FUDGEFACTOR);
real_max_open_files = real_lim - MAX_OPEN_FUDGEFACTOR;
if(real_max_open_files != request_max_open_files) {
DEBUG(1,("file_init: Information only: requested %d \
open files, %d are available.\n", request_max_open_files, real_max_open_files));
}
file_bmap = bitmap_allocate(real_max_open_files);
if (!file_bmap) {
exit_server("out of memory in file_init");
}
/*
* Ensure that pipe_handle_oppset is set correctly.
*/
set_pipe_handle_offset(real_max_open_files);
}
/****************************************************************************
close files open by a specified vuid
****************************************************************************/
void file_close_user(int vuid)
{
files_struct *fsp, *next;
for (fsp=Files;fsp;fsp=next) {
next=fsp->next;
if (fsp->vuid == vuid) {
close_file(fsp,False);
}
}
}
/****************************************************************************
Find a fsp given a device, inode and timevalue
If this is from a kernel oplock break request then tval may be NULL.
****************************************************************************/
files_struct *file_find_dit(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
{
int count=0;
files_struct *fsp;
for (fsp=Files;fsp;fsp=fsp->next,count++) {
if (fsp->fd != -1 &&
fsp->dev == dev &&
fsp->inode == inode &&
(tval ? (fsp->open_time.tv_sec == tval->tv_sec) : True ) &&
(tval ? (fsp->open_time.tv_usec == tval->tv_usec) : True )) {
if (count > 10) {
DLIST_PROMOTE(Files, fsp);
}
return fsp;
}
}
return NULL;
}
/****************************************************************************
Check if an fsp still exists.
****************************************************************************/
files_struct *file_find_fsp(files_struct *orig_fsp)
{
files_struct *fsp;
for (fsp=Files;fsp;fsp=fsp->next) {
if (fsp == orig_fsp)
return fsp;
}
return NULL;
}
/****************************************************************************
Find the first fsp given a device and inode.
****************************************************************************/
files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
{
files_struct *fsp;
for (fsp=Files;fsp;fsp=fsp->next) {
if ( fsp->fd != -1 &&
fsp->dev == dev &&
fsp->inode == inode )
return fsp;
}
return NULL;
}
/****************************************************************************
Find the next fsp having the same device and inode.
****************************************************************************/
files_struct *file_find_di_next(files_struct *start_fsp)
{
files_struct *fsp;
for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
if ( fsp->fd != -1 &&
fsp->dev == start_fsp->dev &&
fsp->inode == start_fsp->inode )
return fsp;
}
return NULL;
}
/****************************************************************************
find a fsp that is open for printing
****************************************************************************/
files_struct *file_find_print(void)
{
files_struct *fsp;
for (fsp=Files;fsp;fsp=fsp->next) {
if (fsp->print_file) return fsp;
}
return NULL;
}
/****************************************************************************
sync open files on a connection
****************************************************************************/
void file_sync_all(connection_struct *conn)
{
files_struct *fsp, *next;
for (fsp=Files;fsp;fsp=next) {
next=fsp->next;
if ((conn == fsp->conn) && (fsp->fd != -1)) {
conn->vfs_ops.fsync(fsp->fd);
}
}
}
/****************************************************************************
free up a fsp
****************************************************************************/
void file_free(files_struct *fsp)
{
DLIST_REMOVE(Files, fsp);
string_free(&fsp->fsp_name);
bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
files_used--;
DEBUG(5,("freed files structure %d (%d used)\n",
fsp->fnum, files_used));
/* this is paranoia, just in case someone tries to reuse the
information */
ZERO_STRUCTP(fsp);
if (fsp == chain_fsp) chain_fsp = NULL;
free(fsp);
}
/****************************************************************************
get a fsp from a packet given the offset of a 16 bit fnum
****************************************************************************/
files_struct *file_fsp(char *buf, int where)
{
int fnum, count=0;
files_struct *fsp;
if (chain_fsp) return chain_fsp;
fnum = SVAL(buf, where);
for (fsp=Files;fsp;fsp=fsp->next, count++) {
if (fsp->fnum == fnum) {
chain_fsp = fsp;
if (count > 10) {
DLIST_PROMOTE(Files, fsp);
}
return fsp;
}
}
return NULL;
}
/****************************************************************************
Reset the chained fsp - done at the start of a packet reply
****************************************************************************/
void file_chain_reset(void)
{
chain_fsp = NULL;
}
/****************************************************************************
Save the chained fsp - done when about to do an oplock break.
****************************************************************************/
void file_chain_save(void)
{
oplock_save_chain_fsp = chain_fsp;
}
/****************************************************************************
Restore the chained fsp - done after an oplock break.
****************************************************************************/
void file_chain_restore(void)
{
chain_fsp = oplock_save_chain_fsp;
}