mirror of
https://github.com/reactos/reactos.git
synced 2024-10-31 11:56:26 +00:00
239 lines
6.1 KiB
C
239 lines
6.1 KiB
C
|
/* $Id: fdtable.c,v 1.6 2002/10/29 04:45:31 rex Exp $
|
||
|
*/
|
||
|
/*
|
||
|
* COPYRIGHT: See COPYING in the top level directory
|
||
|
* PROJECT: ReactOS POSIX+ Subsystem
|
||
|
* FILE: subsys/psx/lib/psxdll/misc/fdtable.c
|
||
|
* PURPOSE: File descriptors table functions
|
||
|
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
|
||
|
* UPDATE HISTORY:
|
||
|
* 12/02/2002: Created
|
||
|
*/
|
||
|
|
||
|
#include <string.h>
|
||
|
#include <errno.h>
|
||
|
#include <psx/fdtable.h>
|
||
|
#include <psx/stdlib.h>
|
||
|
#include <psx/debug.h>
|
||
|
#include <psx/safeobj.h>
|
||
|
|
||
|
int __fdtable_init(__fdtable_t * fdtable)
|
||
|
{
|
||
|
if(fdtable == 0)
|
||
|
{
|
||
|
errno = EINVAL;
|
||
|
return (-1);
|
||
|
}
|
||
|
|
||
|
memset(fdtable, 0, sizeof(*fdtable));
|
||
|
|
||
|
fdtable->Signature = __FDTABLE_MAGIC;
|
||
|
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
int __fdtable_free(__fdtable_t * fdtable)
|
||
|
{
|
||
|
if(fdtable == 0)
|
||
|
{
|
||
|
errno = EINVAL;
|
||
|
return (-1);
|
||
|
}
|
||
|
|
||
|
__free(&fdtable->Descriptors);
|
||
|
|
||
|
memset(fdtable, 0, sizeof(*fdtable));
|
||
|
|
||
|
fdtable->Signature = MAGIC('B', 'A', 'A', 'D');
|
||
|
|
||
|
return (0);
|
||
|
}
|
||
|
|
||
|
int __fdtable_entry_isavail(__fdtable_t * fdtable, int fileno)
|
||
|
{
|
||
|
return ((fdtable->DescriptorsBitmap[fileno / 32] >> (fileno % 32)) % 2);
|
||
|
}
|
||
|
|
||
|
int __fdtable_entry_nextavail(__fdtable_t * fdtable, int fileno)
|
||
|
{
|
||
|
int nCurMapIndex;
|
||
|
int nUnusedIndex;
|
||
|
uint32_t nCurMapCell;
|
||
|
|
||
|
nUnusedIndex = fileno;
|
||
|
|
||
|
/* The file descriptors bitmap is an array of 32 bit unsigned integers (32 bit
|
||
|
integers were chosen for proper data alignment without padding). The array is
|
||
|
big enough to hold at least OPEN_MAX bits, that is it has OPEN_MAX / 32 cells
|
||
|
(see also the __fdtable_t definition in psx/fdtable.h). Bits correspond to
|
||
|
file numbers: if a bit is 1, the corresponding file number is in use, else
|
||
|
it's unused. Bit numbering is right-to-left wise, that is the rightmost (least
|
||
|
significative) bit of cell 0 corresponds to file number 0, the leftmost (most
|
||
|
significative) bit of cell 0 to file number 7, the leftmost bit of cell 1 to
|
||
|
file number 8, and so on
|
||
|
*/
|
||
|
/* NOTE: I'm sure the algorytm can be greatly optimized, but I prefer to privilege
|
||
|
readability - it allows for more maintenable code. Please don't pretend to
|
||
|
outsmart the compiler: such optimizations as performing divisions as bit shifts
|
||
|
are useless */
|
||
|
|
||
|
/* index of the bitmap cell containing nUnusedIndex */
|
||
|
nCurMapIndex = nUnusedIndex / 32;
|
||
|
|
||
|
/* get a copy of the bitmap cell containg nUnusedIndex, and shift it to the right
|
||
|
so that the rightmost (least significative) bit is the one referencing nUnusedIndex */
|
||
|
nCurMapCell = fdtable->DescriptorsBitmap[nCurMapIndex] >> (nUnusedIndex % 32);
|
||
|
|
||
|
while(1)
|
||
|
{
|
||
|
/* if the least significative bit of the current cell is 0, we've found an unused
|
||
|
fileno, and we return it */
|
||
|
if((nCurMapCell % 2) == 0)
|
||
|
return (nUnusedIndex);
|
||
|
|
||
|
/* on to next fileno */
|
||
|
nUnusedIndex ++;
|
||
|
|
||
|
/* this is NOT a failure. -1 with undefined errno means that no unused file
|
||
|
number exists */
|
||
|
if(nUnusedIndex >= OPEN_MAX)
|
||
|
return (-1);
|
||
|
|
||
|
/* this fileno is referenced in the next cell */
|
||
|
if((nUnusedIndex % 32) == 0)
|
||
|
{
|
||
|
nCurMapIndex ++;
|
||
|
nCurMapCell = fdtable->DescriptorsBitmap[nCurMapIndex];
|
||
|
}
|
||
|
/* on to next fileno (bit) in the current cell */
|
||
|
else
|
||
|
nCurMapCell >>= 1;
|
||
|
}
|
||
|
|
||
|
return (-1);
|
||
|
}
|
||
|
|
||
|
int __fdtable_entry_add(__fdtable_t * fdtable, int fileno, __fildes_t * fildes, __fildes_t ** newfd)
|
||
|
{
|
||
|
int nFileNo;
|
||
|
|
||
|
/* descriptors count reached OPEN_MAX */
|
||
|
if(fdtable->UsedDescriptors >= OPEN_MAX)
|
||
|
{
|
||
|
ERR("file descriptor table full");
|
||
|
errno = EMFILE;
|
||
|
return (-1);
|
||
|
}
|
||
|
|
||
|
/* base fileno less than zero: use the lowest unused fileno */
|
||
|
if(fileno < 0)
|
||
|
nFileNo = fdtable->LowestUnusedFileNo;
|
||
|
/* base fileno greater than or equal to zero: use the next available fileno */
|
||
|
else
|
||
|
nFileNo = __fdtable_entry_nextavail(fdtable, fileno);
|
||
|
|
||
|
INFO("lowest unused file number is %d", nFileNo);
|
||
|
|
||
|
/* descriptors count reached OPEN_MAX */
|
||
|
if(nFileNo < 0)
|
||
|
{
|
||
|
ERR("nFileNo is less than zero");
|
||
|
errno = EMFILE;
|
||
|
return (-1);
|
||
|
}
|
||
|
|
||
|
/* if the table doesn't have enough space for the next entry ... */
|
||
|
if(nFileNo >= fdtable->AllocatedDescriptors)
|
||
|
{
|
||
|
void * pTemp;
|
||
|
|
||
|
INFO
|
||
|
(
|
||
|
"growing the array from %lu to %lu bytes",
|
||
|
fdtable->AllocatedDescriptors * sizeof(*fdtable->Descriptors),
|
||
|
(nFileNo + 1) * sizeof(*fdtable->Descriptors)
|
||
|
);
|
||
|
|
||
|
/* ... try to increase the size of the table */
|
||
|
if(fdtable->AllocatedDescriptors * sizeof(*fdtable->Descriptors) == 0)
|
||
|
pTemp = __malloc((nFileNo + 1) * sizeof(*fdtable->Descriptors));
|
||
|
else
|
||
|
pTemp = __realloc
|
||
|
(
|
||
|
fdtable->Descriptors,
|
||
|
(nFileNo + 1) * sizeof(*fdtable->Descriptors)
|
||
|
);
|
||
|
|
||
|
/* reallocation failed */
|
||
|
if(pTemp == 0)
|
||
|
{
|
||
|
ERR("__realloc() failed");
|
||
|
errno = ENOMEM;
|
||
|
return (-1);
|
||
|
}
|
||
|
|
||
|
/* update the table */
|
||
|
fdtable->AllocatedDescriptors = nFileNo + 1;
|
||
|
fdtable->Descriptors = pTemp;
|
||
|
}
|
||
|
|
||
|
/* initialize descriptor */
|
||
|
if(fildes == 0)
|
||
|
memset(&fdtable->Descriptors[nFileNo], 0, sizeof(__fildes_t));
|
||
|
else
|
||
|
memcpy(&fdtable->Descriptors[nFileNo], fildes, sizeof(__fildes_t));
|
||
|
|
||
|
if(newfd != 0)
|
||
|
*newfd = &fdtable->Descriptors[nFileNo];
|
||
|
|
||
|
INFO
|
||
|
(
|
||
|
"file number %d: handle 0x%08X, open flags 0x%08X, flags 0x%08X, extra data size %u, extra data at 0x%08X",
|
||
|
nFileNo,
|
||
|
fdtable->Descriptors[nFileNo].FileHandle,
|
||
|
fdtable->Descriptors[nFileNo].OpenFlags,
|
||
|
fdtable->Descriptors[nFileNo].FdFlags,
|
||
|
fdtable->Descriptors[nFileNo].ExtraDataSize,
|
||
|
fdtable->Descriptors[nFileNo].ExtraData
|
||
|
);
|
||
|
|
||
|
INFO
|
||
|
(
|
||
|
"incrementing used descriptors count from %u to %u",
|
||
|
fdtable->UsedDescriptors,
|
||
|
fdtable->UsedDescriptors + 1
|
||
|
);
|
||
|
fdtable->UsedDescriptors ++;
|
||
|
|
||
|
INFO
|
||
|
(
|
||
|
"setting bit %u of cell %u of the bitmap to 1",
|
||
|
nFileNo % 32,
|
||
|
nFileNo / 32
|
||
|
);
|
||
|
fdtable->DescriptorsBitmap[nFileNo / 32] |= (1 << (nFileNo % 32));
|
||
|
|
||
|
fdtable->LowestUnusedFileNo = __fdtable_entry_nextavail(fdtable, nFileNo);
|
||
|
INFO("setting the lowest unused file number to %d", fdtable->LowestUnusedFileNo);
|
||
|
|
||
|
return (nFileNo);
|
||
|
}
|
||
|
|
||
|
int __fdtable_entry_remove(__fdtable_t * fdtable, int fileno)
|
||
|
{
|
||
|
return (-1);
|
||
|
}
|
||
|
|
||
|
__fildes_t *__fdtable_entry_get(__fdtable_t * fdtable, int fileno)
|
||
|
{
|
||
|
/* this fileno hasn't been allocated */
|
||
|
if(fileno >= fdtable->AllocatedDescriptors)
|
||
|
return (0);
|
||
|
|
||
|
/* TODO: check the fileno against the bitmap */
|
||
|
return (&fdtable->Descriptors[fileno]);
|
||
|
}
|
||
|
|
||
|
/* EOF */
|
||
|
|