source: branches/samba-3.0/source/lib/os2ea.c@ 161

Last change on this file since 161 was 160, checked in by Paul Smedley, 17 years ago

New implementation of os2_randget() - fixes SIGSEGV with GCC 4.3.2 and -O2 or higher

File size: 13.3 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/* these define the attribute byte as seen by DOS */
23#define aRONLY (1L<<0) /* 0x01 */
24#define aHIDDEN (1L<<1) /* 0x02 */
25#define aSYSTEM (1L<<2) /* 0x04 */
26#define aVOLID (1L<<3) /* 0x08 */
27#define aDIR (1L<<4) /* 0x10 */
28#define aARCH (1L<<5) /* 0x20 */
29
30#ifndef TESTING
31#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
32#define CMD_KI_RDCNT (0x63)
33
34#include "local.h"
35#include "xfile.h"
36#include "pstring.h"
37#include "debug.h"
38#else
39#define DEBUG(a,b) (0)
40#endif
41
42#include <string.h>
43
44#ifndef ENOATTR
45#define ENOATTR 22
46#endif
47
48int os2_ftruncate(int fd, off_t size)
49{
50 // We call there __libc_Back_ioFileSizeSet directly instead of
51 // ftruncate to force it not to zero expanding files to optimize
52 // samba performance when copying files
53 int rc = __libc_Back_ioFileSizeSet(fd, size, 0);
54 if (rc < 0)
55 {
56 errno = -rc;
57 return -1;
58 }
59 return 0;
60}
61
62int os2_isattribute(char *path, unsigned short attr)
63{
64 HDIR hdirFindHandle = HDIR_CREATE;
65 FILEFINDBUF3 FindBuffer = {0}; /* Returned from FindFirst/Next */
66 USHORT dosattr; /* attribute to search for */
67 ULONG ulResultBufLen = sizeof(FILEFINDBUF3);
68 ULONG ulFindCount = 1; /* Look for 1 file at a time */
69 APIRET rc = NO_ERROR; /* Return code */
70 if (attr==aARCH)
71 dosattr=MUST_HAVE_ARCHIVED;
72 else if (attr==aRONLY)
73 dosattr=MUST_HAVE_READONLY;
74 else if (attr==aSYSTEM)
75 dosattr=MUST_HAVE_SYSTEM;
76 else if (attr==aHIDDEN)
77 dosattr=MUST_HAVE_HIDDEN;
78
79 rc = DosFindFirst( path, /* File pattern - all files */
80 &hdirFindHandle, /* Directory search handle */
81 dosattr,
82 &FindBuffer, /* Result buffer */
83 ulResultBufLen, /* Result buffer length */
84 &ulFindCount, /* Number of entries to find */
85 FIL_STANDARD); /* Return Level 1 file info */
86
87 if (rc != NO_ERROR) {
88 rc = DosFindClose(hdirFindHandle); /* Close our directory handle */
89 return 1;
90
91 } else {
92 rc = DosFindClose(hdirFindHandle); /* Close our directory handle */
93 return 0;
94
95 } /* endif */
96
97}
98
99/* Functions below are based on APR random code */
100/* Licensed to the Apache Software Foundation (ASF) under one or more
101 * contributor license agreements. See the NOTICE file distributed with
102 * this work for additional information regarding copyright ownership.
103 * The ASF licenses this file to You under the Apache License, Version 2.0
104 * (the "License"); you may not use this file except in compliance with
105 * the License. You may obtain a copy of the License at
106 *
107 * http://www.apache.org/licenses/LICENSE-2.0
108 *
109 * Unless required by applicable law or agreed to in writing, software
110 * distributed under the License is distributed on an "AS IS" BASIS,
111 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
112 * See the License for the specific language governing permissions and
113 * limitations under the License.
114 */
115
116/* The high resolution timer API provides access to the hardware timer
117 * running at around 1.1MHz. The amount this changes in a time slice is
118 * varies randomly due to system events, hardware interrupts etc
119 */
120
121void os2_randget(char * buffer, int length)
122{
123 UCHAR randbyte();
124 unsigned int idx;
125
126 for (idx=0; idx<length; idx++)
127 buffer[idx] = randbyte();
128
129}
130
131static UCHAR randbyte_hrtimer()
132{
133 QWORD t1, t2;
134 UCHAR byte;
135
136 DosTmrQueryTime(&t1);
137 DosSleep(5);
138 DosTmrQueryTime(&t2);
139
140 byte = (t2.ulLo - t1.ulLo) & 0xFF;
141 byte ^= (t2.ulLo - t1.ulLo) >> 8;
142 return byte;
143}
144
145
146
147/* A bunch of system information like memory & process stats.
148 * Not highly random but every bit helps....
149 */
150static UCHAR randbyte_sysinfo()
151{
152 UCHAR byte = 0;
153 UCHAR SysVars[100];
154 int b;
155
156 DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars));
157
158 for (b = 0; b < 100; b++) {
159 byte ^= SysVars[b];
160 }
161
162 return byte;
163}
164
165
166
167/* Similar in concept to randbyte_hrtimer() but accesses the CPU's internal
168 * counters which run at the CPU's MHz speed. We get separate
169 * idle / busy / interrupt cycle counts which should provide very good
170 * randomness due to interference of hardware events.
171 * This only works on newer CPUs (at least PPro or K6) and newer OS/2 versions
172 * which is why it's run-time linked.
173 */
174
175static HMODULE hDoscalls = 0;
176#define CMD_KI_RDCNT (0x63)
177
178typedef struct _CPUUTIL {
179 ULONG ulTimeLow; /* Low 32 bits of time stamp */
180 ULONG ulTimeHigh; /* High 32 bits of time stamp */
181 ULONG ulIdleLow; /* Low 32 bits of idle time */
182 ULONG ulIdleHigh; /* High 32 bits of idle time */
183 ULONG ulBusyLow; /* Low 32 bits of busy time */
184 ULONG ulBusyHigh; /* High 32 bits of busy time */
185 ULONG ulIntrLow; /* Low 32 bits of interrupt time */
186 ULONG ulIntrHigh; /* High 32 bits of interrupt time */
187} CPUUTIL;
188
189
190static UCHAR randbyte_perf()
191{
192 UCHAR byte = 0;
193 CPUUTIL util;
194 int c;
195
196#ifndef __INNOTEK_LIBC__
197 if (hDoscalls == 0) {
198 char failed_module[20];
199 ULONG rc;
200
201 rc = DosLoadModule(failed_module, sizeof(failed_module), "DOSCALLS",
202 &hDoscalls);
203
204 if (rc == 0) {
205 rc = DosQueryProcAddr(hDoscalls, 976, NULL, (PFN *)&DosPerfSysCall);
206
207 if (rc) {
208 DosPerfSysCall = NULL;
209 }
210 }
211 }
212
213 if (DosPerfSysCall) {
214 if (DosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) {
215 for (c = 0; c < sizeof(util); c++) {
216 byte ^= ((UCHAR *)&util)[c];
217 }
218 }
219 else {
220 DosPerfSysCall = NULL;
221 }
222 }
223#endif
224 return byte;
225}
226
227
228
229UCHAR randbyte()
230{
231 return randbyte_hrtimer() ^ randbyte_sysinfo() ^ randbyte_perf();
232}
233
234
235void maperrno(int rc)
236{
237 switch (rc)
238 {
239 case ERROR_PATH_NOT_FOUND :
240 case ERROR_FILE_NOT_FOUND : errno = ENOENT; break;
241 case ERROR_INVALID_HANDLE : errno = EBADF; break;
242 case ERROR_ACCESS_DENIED : errno = EACCES; break;
243 case ERROR_BUFFER_OVERFLOW :
244 case ERROR_NOT_ENOUGH_MEMORY : errno = ERANGE; break;
245 case ERROR_INVALID_EA_NAME : errno = ENOATTR; break;
246 case ERROR_INVALID_LEVEL :
247 case ERROR_INVALID_PARAMETER : errno = EINVAL; break;
248 case ERROR_SHARING_VIOLATION : errno = EACCES; break;
249 default : errno = EINVAL;
250 }
251}
252
253ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
254{
255 int rc, namelen;
256 EAOP2 eaop2 = {0};
257 PGEA2LIST pgea2list = NULL;
258 PFEA2LIST pfea2list = NULL;
259 char * p;
260
261 if ((!path && !file) || !name)
262 {
263 errno = EINVAL;
264 return -1;
265 }
266 namelen = strlen(name);
267 if (namelen > 0xFF)
268 {
269 errno = EINVAL;
270 return -1;
271 }
272 pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
273 pgea2list->list[0].oNextEntryOffset = 0;
274 pgea2list->list[0].cbName = namelen;
275 strcpy(pgea2list->list[0].szName, name);
276 pgea2list->cbList = sizeof(GEA2LIST) + namelen;
277
278 // max ea is 64kb
279 pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
280 pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
281
282 eaop2.fpGEA2List = pgea2list;
283 eaop2.fpFEA2List = pfea2list;
284 eaop2.oError = 0;
285 do
286 {
287 if (path)
288 {
289 char npath[CCHMAXPATH + 1] = {0};
290 strncpy(npath, path, CCHMAXPATH);
291 for (p = npath; *p; p++)
292 {
293 if (*p == '/') *p = '\\';
294 }
295 rc = DosQueryPathInfo(npath, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
296 }
297 else
298 {
299 rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
300 }
301 if (rc)
302 {
303 maperrno(rc);
304 rc = -1;
305 break;
306 }
307 if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0)
308 {
309 errno = ENOATTR;
310 rc = -1;
311 break;
312 }
313 rc = pfea2list->list[0].cbValue;
314 if (value)
315 {
316 if (size < rc)
317 {
318 errno = ERANGE;
319 rc = -1;
320 }
321 else
322 {
323 p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
324 memcpy(value, p, rc);
325 }
326 }
327 } while (0);
328 if (pgea2list)
329 {
330 free(pgea2list);
331 }
332 if (pgea2list)
333 {
334 free(pfea2list);
335 }
336 DEBUG(4,("unigetxattr : (%s:%d) %s %d\n", path ? path : "null", file, name, rc));
337 return rc;
338}
339
340ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
341{
342 ssize_t gotsize = 0;
343 unsigned long ulCount = -1;
344 int rc;
345 char * buf, *p = list;
346 PFEA2 pfea;
347 FILESTATUS4 stat = {0};
348 char npath[CCHMAXPATH + 1] = {0};
349 if (!path && !file)
350 {
351 errno = EINVAL;
352 return -1;
353 }
354 if (path)
355 {
356 char * p;
357 strncpy(npath, path, CCHMAXPATH);
358 for (p = npath; *p; p++)
359 {
360 if (*p == '/') *p = '\\';
361 }
362 rc = DosQueryPathInfo(npath, FIL_QUERYEASIZE, &stat, sizeof(stat));
363 }
364 else
365 {
366 rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
367 }
368 if (rc)
369 {
370 DEBUG(4,("unilistxattr1 : (%s:%d) %d\n", path ? path : "null", file, rc));
371 maperrno(rc);
372 return -1;
373 }
374 if (stat.cbList <= 4)
375 {
376 // NO ea
377 return 0;
378 }
379 //YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
380 buf = (char *)_tmalloc(stat.cbList * 2);
381 rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
382 if (rc)
383 {
384 DEBUG(4,("unilistxattr2 : (%s:%d) %d\n", path ? path : "null", file, rc));
385 maperrno(rc);
386 _tfree(buf);
387 return -1;
388 }
389 if (ulCount > 0)
390 for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset))
391 {
392 if (pfea->cbName > 0)
393 {
394 gotsize += pfea->cbName + 1;
395 if (p && size >= gotsize)
396 {
397 pfea->szName[pfea->cbName] = 0;
398 strcpy(p, pfea->szName);
399 p += strlen(p) + 1;
400 }
401 }
402 if (!pfea->oNextEntryOffset)
403 {
404 break;
405 }
406 }
407 _tfree(buf);
408 DEBUG(4,("unilistxattr : (%s:%d) %d\n", path ? path : "null", file, gotsize));
409 if (gotsize > size)
410 {
411 errno = ERANGE;
412 return list ? -1 : gotsize;
413 }
414 return gotsize;
415}
416
417int uniremovexattr (const char *path, int file, const char *name)
418{
419 int rc, namelen;
420 EAOP2 eaop2 = {0};
421 PFEA2LIST pfea2list = NULL;
422 char buf[300] = {0};
423
424 if ((!path && !file) || !name)
425 {
426 errno = EINVAL;
427 return -1;
428 }
429
430 namelen = strlen(name);
431 if (namelen > 0xFF)
432 {
433 errno = EINVAL;
434 return -1;
435 }
436
437 pfea2list = (PFEA2LIST)buf;
438 pfea2list->list[0].cbName = namelen;
439 pfea2list->list[0].cbValue = 0;
440 pfea2list->list[0].fEA = 0;
441 strcpy(pfea2list->list[0].szName, name);
442 pfea2list->cbList = sizeof(FEA2LIST) + namelen;
443 eaop2.fpFEA2List = pfea2list;
444
445 if (path)
446 {
447 char npath[CCHMAXPATH + 1] = {0};
448 char * p;
449 strncpy(npath, path, CCHMAXPATH);
450 for (p = npath; *p; p++)
451 {
452 if (*p == '/') *p = '\\';
453 }
454 rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
455 }
456 else
457 {
458 rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
459 }
460 if (rc)
461 {
462 maperrno(rc);
463 return -1;
464 }
465 return 0;
466}
467
468#ifndef XATTR_CREATE
469#define XATTR_CREATE 1
470#endif
471#ifndef XATTR_REPLACE
472#define XATTR_REPLACE 2
473#endif
474
475int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
476{
477 int rc, namelen, totalsize;
478 EAOP2 eaop2 = {0};
479 PFEA2LIST pfea2list = NULL;
480 char * p;
481
482 if ((!path && !file) || !name || (!value && size))
483 {
484 errno = EINVAL;
485 return -1;
486 }
487 namelen = strlen(name);
488 if (namelen > 0xFF)
489 {
490 errno = EINVAL;
491 return -1;
492 }
493
494 if (flags & (XATTR_CREATE | XATTR_REPLACE))
495 {
496 ssize_t esize = unigetxattr(path, file, name, 0, 0);
497 if (flags & XATTR_CREATE && esize > 0)
498 {
499 errno = EEXIST;
500 return -1;
501 }
502 if (flags & XATTR_REPLACE && esize < 0)
503 {
504 errno = ENOATTR;
505 return -1;
506 }
507 }
508
509 totalsize = sizeof(FEA2LIST) + size + namelen + 1;
510
511 pfea2list = (PFEA2LIST)calloc(totalsize, 1);
512 pfea2list->cbList = totalsize;
513 pfea2list->list[0].oNextEntryOffset = 0;
514 pfea2list->list[0].cbName = namelen;
515 pfea2list->list[0].cbValue = size;
516 strcpy(pfea2list->list[0].szName, name);
517 if (value)
518 {
519 memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
520 }
521 eaop2.fpFEA2List = pfea2list;
522
523 if (path)
524 {
525 char npath[CCHMAXPATH + 1] = {0};
526 char * p;
527 strncpy(npath, path, CCHMAXPATH);
528 for (p = npath; *p; p++)
529 {
530 if (*p == '/') *p = '\\';
531 }
532 rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
533 }
534 else
535 {
536 rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
537 }
538 free(pfea2list);
539 if (rc)
540 {
541 maperrno(rc);
542 return -1;
543 }
544 return 0;
545}
546
547#endif
Note: See TracBrowser for help on using the repository browser.