source: trunk/samba-3.0.25pre1/source/lib/os2ea.c@ 12

Last change on this file since 12 was 12, checked in by Yuri Dario, 18 years ago

Use lowmem buffer for DosEnumAttribute.

File size: 9.2 KB
Line 
1/* This file contains helper functions for OS/2 - don't try and compile on other platforms */
2
3#ifdef __OS2__
4
5#define INCL_LONGLONG
6#define INCL_DOS
7#define INCL_DOSPROCESS
8#define INCL_DOSPROFILE
9#define INCL_DOSMISC
10#define INCL_DOSMODULEMGR
11#define INCL_DOSERRORS
12//_SMB_H
13#include <os2.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <errno.h>
17#include <types.h>
18
19//YD for tmalloc
20#include <malloc.h>
21
22#ifndef TESTING
23#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
24#define CMD_KI_RDCNT (0x63)
25
26typedef struct _CPUUTIL {
27 ULONG ulTimeLow; /* Low 32 bits of time stamp */
28 ULONG ulTimeHigh; /* High 32 bits of time stamp */
29 ULONG ulIdleLow; /* Low 32 bits of idle time */
30 ULONG ulIdleHigh; /* High 32 bits of idle time */
31 ULONG ulBusyLow; /* Low 32 bits of busy time */
32 ULONG ulBusyHigh; /* High 32 bits of busy time */
33 ULONG ulIntrLow; /* Low 32 bits of interrupt time */
34 ULONG ulIntrHigh; /* High 32 bits of interrupt time */
35 } CPUUTIL;
36
37#include "local.h"
38#include "xfile.h"
39#include "pstring.h"
40#include "debug.h"
41#else
42#define DEBUG(a,b) (0)
43#endif
44
45#include <string.h>
46
47#ifndef ENOATTR
48#define ENOATTR 22
49#endif
50
51int os2_ftruncate(int fd, off_t size)
52{
53 // We call there __libc_Back_ioFileSizeSet directly instead of
54 // ftruncate to force it not to zero expanding files to optimize
55 // samba performance when copying files
56 int rc = __libc_Back_ioFileSizeSet(fd, size, 0);
57 if (rc < 0)
58 {
59 errno = -rc;
60 return -1;
61 }
62 return 0;
63}
64
65// very simple random data gatherer derived from openssl
66void os2_randget(char * buffer, int length)
67{
68 QWORD qwTime;
69 ULONG SysVars[QSV_FOREGROUND_PROCESS];
70 int done = 0;
71
72 if (!buffer || length <= 0)
73 {
74 return;
75 }
76
77 DosTmrQueryTime(&qwTime);
78 memcpy(buffer, &qwTime, sizeof(qwTime) > length ? length : sizeof(qwTime));
79 done += sizeof(qwTime);
80 if (done >= length)
81 {
82 return;
83 }
84
85 if (DosPerfSysCall)
86 {
87 CPUUTIL util;
88 if (DosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0)
89 {
90 memcpy(buffer + done, &util, sizeof(util) > length - done ? length - done : sizeof(util));
91 done += sizeof(util);
92 if (done >= length)
93 {
94 return;
95 }
96 }
97 }
98
99 DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars));
100 memcpy(buffer + done, SysVars, sizeof(SysVars) > length - done ? length - done : sizeof(SysVars));
101}
102
103
104void maperrno(int rc)
105{
106 switch (rc)
107 {
108 case ERROR_PATH_NOT_FOUND :
109 case ERROR_FILE_NOT_FOUND : errno = ENOENT; break;
110 case ERROR_INVALID_HANDLE : errno = EBADF; break;
111 case ERROR_ACCESS_DENIED : errno = EACCES; break;
112 case ERROR_BUFFER_OVERFLOW :
113 case ERROR_NOT_ENOUGH_MEMORY : errno = ERANGE; break;
114 case ERROR_INVALID_EA_NAME : errno = ENOATTR; break;
115 case ERROR_INVALID_LEVEL :
116 case ERROR_INVALID_PARAMETER : errno = EINVAL; break;
117 case ERROR_SHARING_VIOLATION : errno = EACCES; break;
118 default : errno = EINVAL;
119 }
120}
121
122ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
123{
124 int rc, namelen;
125 EAOP2 eaop2 = {0};
126 PGEA2LIST pgea2list = NULL;
127 PFEA2LIST pfea2list = NULL;
128 char * p;
129
130 if ((!path && !file) || !name)
131 {
132 errno = EINVAL;
133 return -1;
134 }
135 namelen = strlen(name);
136 if (namelen > 0xFF)
137 {
138 errno = EINVAL;
139 return -1;
140 }
141 pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
142 pgea2list->list[0].oNextEntryOffset = 0;
143 pgea2list->list[0].cbName = namelen;
144 strcpy(pgea2list->list[0].szName, name);
145 pgea2list->cbList = sizeof(GEA2LIST) + namelen;
146
147 // max ea is 64kb
148 pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
149 pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
150
151 eaop2.fpGEA2List = pgea2list;
152 eaop2.fpFEA2List = pfea2list;
153 eaop2.oError = 0;
154 do
155 {
156 if (path)
157 {
158 char npath[CCHMAXPATH + 1] = {0};
159 strncpy(npath, path, CCHMAXPATH);
160 for (p = npath; *p; p++)
161 {
162 if (*p == '/') *p = '\\';
163 }
164 rc = DosQueryPathInfo(npath, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
165 }
166 else
167 {
168 rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
169 }
170 if (rc)
171 {
172 maperrno(rc);
173 rc = -1;
174 break;
175 }
176 if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0)
177 {
178 errno = ENOATTR;
179 rc = -1;
180 break;
181 }
182 rc = pfea2list->list[0].cbValue;
183 if (value)
184 {
185 if (size < rc)
186 {
187 errno = ERANGE;
188 rc = -1;
189 }
190 else
191 {
192 p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
193 memcpy(value, p, rc);
194 }
195 }
196 } while (0);
197 if (pgea2list)
198 {
199 free(pgea2list);
200 }
201 if (pgea2list)
202 {
203 free(pfea2list);
204 }
205 DEBUG(4,("unigetxattr : (%s:%d) %s %d\n", path ? path : "null", file, name, rc));
206 return rc;
207}
208
209ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
210{
211 ssize_t gotsize = 0;
212 unsigned long ulCount = -1;
213 int rc;
214 char * buf, *p = list;
215 PFEA2 pfea;
216 FILESTATUS4 stat = {0};
217 char npath[CCHMAXPATH + 1] = {0};
218 if (!path && !file)
219 {
220 errno = EINVAL;
221 return -1;
222 }
223 if (path)
224 {
225 char * p;
226 strncpy(npath, path, CCHMAXPATH);
227 for (p = npath; *p; p++)
228 {
229 if (*p == '/') *p = '\\';
230 }
231 rc = DosQueryPathInfo(npath, FIL_QUERYEASIZE, &stat, sizeof(stat));
232 }
233 else
234 {
235 rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
236 }
237 if (rc)
238 {
239 DEBUG(4,("unilistxattr1 : (%s:%d) %d\n", path ? path : "null", file, rc));
240 maperrno(rc);
241 return -1;
242 }
243 if (stat.cbList <= 4)
244 {
245 // NO ea
246 return 0;
247 }
248 //YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
249 buf = (char *)_tmalloc(stat.cbList * 2);
250 rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
251 if (rc)
252 {
253 DEBUG(4,("unilistxattr2 : (%s:%d) %d\n", path ? path : "null", file, rc));
254 maperrno(rc);
255 _tfree(buf);
256 return -1;
257 }
258 if (ulCount > 0)
259 for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset))
260 {
261 if (pfea->cbName > 0)
262 {
263 gotsize += pfea->cbName + 1;
264 if (p && size >= gotsize)
265 {
266 pfea->szName[pfea->cbName] = 0;
267 strcpy(p, pfea->szName);
268 p += strlen(p) + 1;
269 }
270 }
271 if (!pfea->oNextEntryOffset)
272 {
273 break;
274 }
275 }
276 _tfree(buf);
277 DEBUG(4,("unilistxattr : (%s:%d) %d\n", path ? path : "null", file, gotsize));
278 if (gotsize > size)
279 {
280 errno = ERANGE;
281 return list ? -1 : gotsize;
282 }
283 return gotsize;
284}
285
286int uniremovexattr (const char *path, int file, const char *name)
287{
288 int rc, namelen;
289 EAOP2 eaop2 = {0};
290 PFEA2LIST pfea2list = NULL;
291 char buf[300] = {0};
292
293 if ((!path && !file) || !name)
294 {
295 errno = EINVAL;
296 return -1;
297 }
298
299 namelen = strlen(name);
300 if (namelen > 0xFF)
301 {
302 errno = EINVAL;
303 return -1;
304 }
305
306 pfea2list = (PFEA2LIST)buf;
307 pfea2list->list[0].cbName = namelen;
308 pfea2list->list[0].cbValue = 0;
309 pfea2list->list[0].fEA = 0;
310 strcpy(pfea2list->list[0].szName, name);
311 pfea2list->cbList = sizeof(FEA2LIST) + namelen;
312 eaop2.fpFEA2List = pfea2list;
313
314 if (path)
315 {
316 char npath[CCHMAXPATH + 1] = {0};
317 char * p;
318 strncpy(npath, path, CCHMAXPATH);
319 for (p = npath; *p; p++)
320 {
321 if (*p == '/') *p = '\\';
322 }
323 rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
324 }
325 else
326 {
327 rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
328 }
329 if (rc)
330 {
331 maperrno(rc);
332 return -1;
333 }
334 return 0;
335}
336
337#ifndef XATTR_CREATE
338#define XATTR_CREATE 1
339#endif
340#ifndef XATTR_REPLACE
341#define XATTR_REPLACE 2
342#endif
343
344int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
345{
346 int rc, namelen, totalsize;
347 EAOP2 eaop2 = {0};
348 PFEA2LIST pfea2list = NULL;
349 char * p;
350
351 if ((!path && !file) || !name || (!value && size))
352 {
353 errno = EINVAL;
354 return -1;
355 }
356 namelen = strlen(name);
357 if (namelen > 0xFF)
358 {
359 errno = EINVAL;
360 return -1;
361 }
362
363 if (flags & (XATTR_CREATE | XATTR_REPLACE))
364 {
365 ssize_t esize = unigetxattr(path, file, name, 0, 0);
366 if (flags & XATTR_CREATE && esize > 0)
367 {
368 errno = EEXIST;
369 return -1;
370 }
371 if (flags & XATTR_REPLACE && esize < 0)
372 {
373 errno = ENOATTR;
374 return -1;
375 }
376 }
377
378 totalsize = sizeof(FEA2LIST) + size + namelen + 1;
379
380 pfea2list = (PFEA2LIST)calloc(totalsize, 1);
381 pfea2list->cbList = totalsize;
382 pfea2list->list[0].oNextEntryOffset = 0;
383 pfea2list->list[0].cbName = namelen;
384 pfea2list->list[0].cbValue = size;
385 strcpy(pfea2list->list[0].szName, name);
386 if (value)
387 {
388 memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
389 }
390 eaop2.fpFEA2List = pfea2list;
391
392 if (path)
393 {
394 char npath[CCHMAXPATH + 1] = {0};
395 char * p;
396 strncpy(npath, path, CCHMAXPATH);
397 for (p = npath; *p; p++)
398 {
399 if (*p == '/') *p = '\\';
400 }
401 rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
402 }
403 else
404 {
405 rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
406 }
407 free(pfea2list);
408 if (rc)
409 {
410 maperrno(rc);
411 return -1;
412 }
413 return 0;
414}
415
416#endif
Note: See TracBrowser for help on using the repository browser.