scroll mode for very long start menus
[reactos.git] / posix / lib / psxdll / misc / fdtable.c
1 /* $Id: fdtable.c,v 1.6 2002/10/29 04:45:31 rex Exp $
2 */
3 /*
4 * COPYRIGHT: See COPYING in the top level directory
5 * PROJECT: ReactOS POSIX+ Subsystem
6 * FILE: subsys/psx/lib/psxdll/misc/fdtable.c
7 * PURPOSE: File descriptors table functions
8 * PROGRAMMER: KJK::Hyperion <noog@libero.it>
9 * UPDATE HISTORY:
10 * 12/02/2002: Created
11 */
12
13 #include <string.h>
14 #include <errno.h>
15 #include <psx/fdtable.h>
16 #include <psx/stdlib.h>
17 #include <psx/debug.h>
18 #include <psx/safeobj.h>
19
20 int __fdtable_init(__fdtable_t * fdtable)
21 {
22 if(fdtable == 0)
23 {
24 errno = EINVAL;
25 return (-1);
26 }
27
28 memset(fdtable, 0, sizeof(*fdtable));
29
30 fdtable->Signature = __FDTABLE_MAGIC;
31
32 return (0);
33 }
34
35 int __fdtable_free(__fdtable_t * fdtable)
36 {
37 if(fdtable == 0)
38 {
39 errno = EINVAL;
40 return (-1);
41 }
42
43 __free(&fdtable->Descriptors);
44
45 memset(fdtable, 0, sizeof(*fdtable));
46
47 fdtable->Signature = MAGIC('B', 'A', 'A', 'D');
48
49 return (0);
50 }
51
52 int __fdtable_entry_isavail(__fdtable_t * fdtable, int fileno)
53 {
54 return ((fdtable->DescriptorsBitmap[fileno / 32] >> (fileno % 32)) % 2);
55 }
56
57 int __fdtable_entry_nextavail(__fdtable_t * fdtable, int fileno)
58 {
59 int nCurMapIndex;
60 int nUnusedIndex;
61 uint32_t nCurMapCell;
62
63 nUnusedIndex = fileno;
64
65 /* The file descriptors bitmap is an array of 32 bit unsigned integers (32 bit
66 integers were chosen for proper data alignment without padding). The array is
67 big enough to hold at least OPEN_MAX bits, that is it has OPEN_MAX / 32 cells
68 (see also the __fdtable_t definition in psx/fdtable.h). Bits correspond to
69 file numbers: if a bit is 1, the corresponding file number is in use, else
70 it's unused. Bit numbering is right-to-left wise, that is the rightmost (least
71 significative) bit of cell 0 corresponds to file number 0, the leftmost (most
72 significative) bit of cell 0 to file number 7, the leftmost bit of cell 1 to
73 file number 8, and so on
74 */
75 /* NOTE: I'm sure the algorytm can be greatly optimized, but I prefer to privilege
76 readability - it allows for more maintenable code. Please don't pretend to
77 outsmart the compiler: such optimizations as performing divisions as bit shifts
78 are useless */
79
80 /* index of the bitmap cell containing nUnusedIndex */
81 nCurMapIndex = nUnusedIndex / 32;
82
83 /* get a copy of the bitmap cell containg nUnusedIndex, and shift it to the right
84 so that the rightmost (least significative) bit is the one referencing nUnusedIndex */
85 nCurMapCell = fdtable->DescriptorsBitmap[nCurMapIndex] >> (nUnusedIndex % 32);
86
87 while(1)
88 {
89 /* if the least significative bit of the current cell is 0, we've found an unused
90 fileno, and we return it */
91 if((nCurMapCell % 2) == 0)
92 return (nUnusedIndex);
93
94 /* on to next fileno */
95 nUnusedIndex ++;
96
97 /* this is NOT a failure. -1 with undefined errno means that no unused file
98 number exists */
99 if(nUnusedIndex >= OPEN_MAX)
100 return (-1);
101
102 /* this fileno is referenced in the next cell */
103 if((nUnusedIndex % 32) == 0)
104 {
105 nCurMapIndex ++;
106 nCurMapCell = fdtable->DescriptorsBitmap[nCurMapIndex];
107 }
108 /* on to next fileno (bit) in the current cell */
109 else
110 nCurMapCell >>= 1;
111 }
112
113 return (-1);
114 }
115
116 int __fdtable_entry_add(__fdtable_t * fdtable, int fileno, __fildes_t * fildes, __fildes_t ** newfd)
117 {
118 int nFileNo;
119
120 /* descriptors count reached OPEN_MAX */
121 if(fdtable->UsedDescriptors >= OPEN_MAX)
122 {
123 ERR("file descriptor table full");
124 errno = EMFILE;
125 return (-1);
126 }
127
128 /* base fileno less than zero: use the lowest unused fileno */
129 if(fileno < 0)
130 nFileNo = fdtable->LowestUnusedFileNo;
131 /* base fileno greater than or equal to zero: use the next available fileno */
132 else
133 nFileNo = __fdtable_entry_nextavail(fdtable, fileno);
134
135 INFO("lowest unused file number is %d", nFileNo);
136
137 /* descriptors count reached OPEN_MAX */
138 if(nFileNo < 0)
139 {
140 ERR("nFileNo is less than zero");
141 errno = EMFILE;
142 return (-1);
143 }
144
145 /* if the table doesn't have enough space for the next entry ... */
146 if(nFileNo >= fdtable->AllocatedDescriptors)
147 {
148 void * pTemp;
149
150 INFO
151 (
152 "growing the array from %lu to %lu bytes",
153 fdtable->AllocatedDescriptors * sizeof(*fdtable->Descriptors),
154 (nFileNo + 1) * sizeof(*fdtable->Descriptors)
155 );
156
157 /* ... try to increase the size of the table */
158 if(fdtable->AllocatedDescriptors * sizeof(*fdtable->Descriptors) == 0)
159 pTemp = __malloc((nFileNo + 1) * sizeof(*fdtable->Descriptors));
160 else
161 pTemp = __realloc
162 (
163 fdtable->Descriptors,
164 (nFileNo + 1) * sizeof(*fdtable->Descriptors)
165 );
166
167 /* reallocation failed */
168 if(pTemp == 0)
169 {
170 ERR("__realloc() failed");
171 errno = ENOMEM;
172 return (-1);
173 }
174
175 /* update the table */
176 fdtable->AllocatedDescriptors = nFileNo + 1;
177 fdtable->Descriptors = pTemp;
178 }
179
180 /* initialize descriptor */
181 if(fildes == 0)
182 memset(&fdtable->Descriptors[nFileNo], 0, sizeof(__fildes_t));
183 else
184 memcpy(&fdtable->Descriptors[nFileNo], fildes, sizeof(__fildes_t));
185
186 if(newfd != 0)
187 *newfd = &fdtable->Descriptors[nFileNo];
188
189 INFO
190 (
191 "file number %d: handle 0x%08X, open flags 0x%08X, flags 0x%08X, extra data size %u, extra data at 0x%08X",
192 nFileNo,
193 fdtable->Descriptors[nFileNo].FileHandle,
194 fdtable->Descriptors[nFileNo].OpenFlags,
195 fdtable->Descriptors[nFileNo].FdFlags,
196 fdtable->Descriptors[nFileNo].ExtraDataSize,
197 fdtable->Descriptors[nFileNo].ExtraData
198 );
199
200 INFO
201 (
202 "incrementing used descriptors count from %u to %u",
203 fdtable->UsedDescriptors,
204 fdtable->UsedDescriptors + 1
205 );
206 fdtable->UsedDescriptors ++;
207
208 INFO
209 (
210 "setting bit %u of cell %u of the bitmap to 1",
211 nFileNo % 32,
212 nFileNo / 32
213 );
214 fdtable->DescriptorsBitmap[nFileNo / 32] |= (1 << (nFileNo % 32));
215
216 fdtable->LowestUnusedFileNo = __fdtable_entry_nextavail(fdtable, nFileNo);
217 INFO("setting the lowest unused file number to %d", fdtable->LowestUnusedFileNo);
218
219 return (nFileNo);
220 }
221
222 int __fdtable_entry_remove(__fdtable_t * fdtable, int fileno)
223 {
224 return (-1);
225 }
226
227 __fildes_t *__fdtable_entry_get(__fdtable_t * fdtable, int fileno)
228 {
229 /* this fileno hasn't been allocated */
230 if(fileno >= fdtable->AllocatedDescriptors)
231 return (0);
232
233 /* TODO: check the fileno against the bitmap */
234 return (&fdtable->Descriptors[fileno]);
235 }
236
237 /* EOF */
238