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

Last change on this file since 539 was 457, checked in by Herwig Bauernfeind, 15 years ago

_divers fix for Ticket #131 and #138

File size: 13.5 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
116void os2_randget(char * buffer, int length)
117{
118 UCHAR randbyte();
119 unsigned int idx;
120
121 for (idx=0; idx<length; idx++)
122 buffer[idx] = randbyte();
123
124}
125
126/* A bunch of system information like memory & process stats.
127 * Not highly random but every bit helps....
128 */
129static UCHAR randbyte_sysinfo()
130{
131 UCHAR byte = 0;
132 UCHAR SysVars[100];
133 int b;
134
135 DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars));
136
137 for (b = 0; b < 100; b++) {
138 byte ^= SysVars[b];
139 }
140
141 return byte;
142}
143
144
145
146/* Similar in concept to randbyte_hrtimer() but accesses the CPU's internal
147 * counters which run at the CPU's MHz speed. We get separate
148 * idle / busy / interrupt cycle counts which should provide very good
149 * randomness due to interference of hardware events.
150 * This only works on newer CPUs (at least PPro or K6) and newer OS/2 versions
151 * which is why it's run-time linked.
152 */
153
154static HMODULE hDoscalls = 0;
155#define CMD_KI_RDCNT (0x63)
156
157typedef struct _CPUUTIL {
158 ULONG ulTimeLow; /* Low 32 bits of time stamp */
159 ULONG ulTimeHigh; /* High 32 bits of time stamp */
160 ULONG ulIdleLow; /* Low 32 bits of idle time */
161 ULONG ulIdleHigh; /* High 32 bits of idle time */
162 ULONG ulBusyLow; /* Low 32 bits of busy time */
163 ULONG ulBusyHigh; /* High 32 bits of busy time */
164 ULONG ulIntrLow; /* Low 32 bits of interrupt time */
165 ULONG ulIntrHigh; /* High 32 bits of interrupt time */
166} CPUUTIL;
167
168APIRET APIENTRY(*pfnDosPerfSysCall) (ULONG ulCommand, ULONG ulParm1, ULONG ulParm2, ULONG ulParm3) = NULL;
169APIRET APIENTRY(*pfnDosQuerySysState) (ULONG func, ULONG arg1, ULONG pid, ULONG _res_, PVOID buf, ULONG bufsz) = NULL;
170
171static UCHAR randbyte_perf()
172{
173 UCHAR byte = 0;
174 int c;
175#if 0
176// The following routine crashes on Quadcore CPUs
177 CPUUTIL util;
178
179 if (hDoscalls == 0) {
180 char failed_module[20];
181 ULONG rc;
182
183 rc = DosLoadModule(failed_module, sizeof(failed_module), "DOSCALLS",
184 &hDoscalls);
185
186 if (rc == 0) {
187 rc = DosQueryProcAddr(hDoscalls, 976, NULL, (PFN *)&pfnDosPerfSysCall);
188
189 if (rc) {
190 pfnDosPerfSysCall = NULL;
191 }
192 }
193 }
194
195 if (pfnDosPerfSysCall) {
196 if ((*pfnDosPerfSysCall) (CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) {
197 for (c = 0; c < sizeof(util); c++) {
198 byte ^= ((UCHAR *)&util)[c];
199 }
200 }
201 else {
202 pfnDosPerfSysCall = NULL;
203 }
204 }
205#endif
206// SC's randomizer
207
208 ULONG ulrandom;
209 ulrandom = random();
210 for (c = 0; c < sizeof(ulrandom); c++) {
211 byte ^= ((UCHAR *)&ulrandom)[c];
212 }
213
214 return byte;
215}
216
217UCHAR randbyte()
218{
219 return randbyte_sysinfo() ^ randbyte_perf();
220}
221
222
223void maperrno(int rc)
224{
225 switch (rc)
226 {
227 case ERROR_PATH_NOT_FOUND :
228 case ERROR_FILE_NOT_FOUND : errno = ENOENT; break;
229 case ERROR_INVALID_HANDLE : errno = EBADF; break;
230 case ERROR_ACCESS_DENIED : errno = EACCES; break;
231 case ERROR_BUFFER_OVERFLOW :
232 case ERROR_NOT_ENOUGH_MEMORY : errno = ERANGE; break;
233 case ERROR_INVALID_EA_NAME : errno = ENOATTR; break;
234 case ERROR_INVALID_LEVEL :
235 case ERROR_INVALID_PARAMETER : errno = EINVAL; break;
236 case ERROR_SHARING_VIOLATION : errno = EACCES; break;
237 default : errno = EINVAL;
238 }
239}
240
241ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
242{
243 int rc, namelen;
244 EAOP2 eaop2 = {0};
245 PGEA2LIST pgea2list = NULL;
246 PFEA2LIST pfea2list = NULL;
247 char * p;
248
249 if ((!path && !file) || !name)
250 {
251 errno = EINVAL;
252 return -1;
253 }
254 namelen = strlen(name);
255 if (namelen > 0xFF)
256 {
257 errno = EINVAL;
258 return -1;
259 }
260 pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
261 pgea2list->list[0].oNextEntryOffset = 0;
262 pgea2list->list[0].cbName = namelen;
263 strcpy(pgea2list->list[0].szName, name);
264 pgea2list->cbList = sizeof(GEA2LIST) + namelen;
265
266 // max ea is 64kb
267 pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
268 pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
269
270 eaop2.fpGEA2List = pgea2list;
271 eaop2.fpFEA2List = pfea2list;
272 eaop2.oError = 0;
273 do
274 {
275 if (path)
276 {
277 char npath[CCHMAXPATH + 1] = {0};
278 strncpy(npath, path, CCHMAXPATH);
279 for (p = npath; *p; p++)
280 {
281 if (*p == '/') *p = '\\';
282 }
283 rc = DosQueryPathInfo(npath, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
284 }
285 else
286 {
287 rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
288 }
289 if (rc)
290 {
291 maperrno(rc);
292 rc = -1;
293 break;
294 }
295 if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0)
296 {
297 errno = ENOATTR;
298 rc = -1;
299 break;
300 }
301 rc = pfea2list->list[0].cbValue;
302 if (value)
303 {
304 if (size < rc)
305 {
306 errno = ERANGE;
307 rc = -1;
308 }
309 else
310 {
311 p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
312 memcpy(value, p, rc);
313 }
314 }
315 } while (0);
316 if (pgea2list)
317 {
318 free(pgea2list);
319 }
320 if (pfea2list)
321 {
322 free(pfea2list);
323 }
324 DEBUG(4,("unigetxattr : (%s:%d) %s %d\n", path ? path : "null", file, name, rc));
325 return rc;
326}
327
328ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
329{
330 ssize_t gotsize = 0;
331 unsigned long ulCount = -1;
332 int rc;
333 char * buf, *p = list;
334 PFEA2 pfea;
335 FILESTATUS4 stat = {0};
336 char npath[CCHMAXPATH + 1] = {0};
337 if (!path && !file)
338 {
339 errno = EINVAL;
340 return -1;
341 }
342 if (path)
343 {
344 char * p;
345 strncpy(npath, path, CCHMAXPATH);
346 for (p = npath; *p; p++)
347 {
348 if (*p == '/') *p = '\\';
349 }
350 rc = DosQueryPathInfo(npath, FIL_QUERYEASIZE, &stat, sizeof(stat));
351 }
352 else
353 {
354 rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
355 }
356 if (rc)
357 {
358 DEBUG(4,("unilistxattr1 : (%s:%d) %d\n", path ? path : "null", file, rc));
359 maperrno(rc);
360 return -1;
361 }
362 if (stat.cbList <= 4)
363 {
364 // NO ea
365 return 0;
366 }
367 //YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
368 buf = (char *)_tmalloc(stat.cbList * 2);
369 rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
370 if (rc)
371 {
372 DEBUG(4,("unilistxattr2 : (%s:%d) %d\n", path ? path : "null", file, rc));
373 maperrno(rc);
374 _tfree(buf);
375 return -1;
376 }
377 if (ulCount > 0)
378 for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset))
379 {
380 if (pfea->cbName > 0)
381 {
382 gotsize += pfea->cbName + 1;
383 if (p && size >= gotsize)
384 {
385 pfea->szName[pfea->cbName] = 0;
386 strcpy(p, pfea->szName);
387 p += strlen(p) + 1;
388 }
389 }
390 // had to be added to avoid crash in case of broken extended attributes
391 if (pfea->oNextEntryOffset > 0x10000)
392 {
393 DEBUG(0, ("Broken Extended Attributes detected for: %s:%d\n", path ? path : "null", file));
394 // DEBUG(0, ("Broken Extended Attributes detected for: %s:%d, Last EA:%s\n", path ? path : "null", file, pfea->szName));
395 break;
396 }
397 if (!pfea->oNextEntryOffset)
398 {
399 break;
400 }
401 }
402 _tfree(buf);
403 DEBUG(4,("unilistxattr : (%s:%d) %d\n", path ? path : "null", file, gotsize));
404 if (gotsize > size)
405 {
406 errno = ERANGE;
407 return list ? -1 : gotsize;
408 }
409 return gotsize;
410}
411
412int uniremovexattr (const char *path, int file, const char *name)
413{
414 int rc, namelen;
415 EAOP2 eaop2 = {0};
416 PFEA2LIST pfea2list = NULL;
417 char buf[300] = {0};
418
419 if ((!path && !file) || !name)
420 {
421 errno = EINVAL;
422 return -1;
423 }
424
425 namelen = strlen(name);
426 if (namelen > 0xFF)
427 {
428 errno = EINVAL;
429 return -1;
430 }
431
432 pfea2list = (PFEA2LIST)buf;
433 pfea2list->list[0].cbName = namelen;
434 pfea2list->list[0].cbValue = 0;
435 pfea2list->list[0].fEA = 0;
436 strcpy(pfea2list->list[0].szName, name);
437 pfea2list->cbList = sizeof(FEA2LIST) + namelen;
438 eaop2.fpFEA2List = pfea2list;
439
440 if (path)
441 {
442 char npath[CCHMAXPATH + 1] = {0};
443 char * p;
444 strncpy(npath, path, CCHMAXPATH);
445 for (p = npath; *p; p++)
446 {
447 if (*p == '/') *p = '\\';
448 }
449 rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
450 }
451 else
452 {
453 rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
454 }
455 if (rc)
456 {
457 maperrno(rc);
458 return -1;
459 }
460 return 0;
461}
462
463#ifndef XATTR_CREATE
464#define XATTR_CREATE 1
465#endif
466#ifndef XATTR_REPLACE
467#define XATTR_REPLACE 2
468#endif
469
470int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
471{
472 int rc, namelen, totalsize;
473 EAOP2 eaop2 = {0};
474 PFEA2LIST pfea2list = NULL;
475 char * p;
476
477 if ((!path && !file) || !name || (!value && size))
478 {
479 errno = EINVAL;
480 return -1;
481 }
482 namelen = strlen(name);
483 if (namelen > 0xFF)
484 {
485 errno = EINVAL;
486 return -1;
487 }
488
489 if (flags & (XATTR_CREATE | XATTR_REPLACE))
490 {
491 ssize_t esize = unigetxattr(path, file, name, 0, 0);
492 if (flags & XATTR_CREATE && esize > 0)
493 {
494 errno = EEXIST;
495 return -1;
496 }
497 if (flags & XATTR_REPLACE && esize < 0)
498 {
499 errno = ENOATTR;
500 return -1;
501 }
502 }
503
504 totalsize = sizeof(FEA2LIST) + size + namelen + 1;
505
506 pfea2list = (PFEA2LIST)calloc(totalsize, 1);
507 pfea2list->cbList = totalsize;
508 pfea2list->list[0].oNextEntryOffset = 0;
509 pfea2list->list[0].cbName = namelen;
510 pfea2list->list[0].cbValue = size;
511 strcpy(pfea2list->list[0].szName, name);
512 if (value)
513 {
514 memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
515 }
516 eaop2.fpFEA2List = pfea2list;
517
518 if (path)
519 {
520 char npath[CCHMAXPATH + 1] = {0};
521 char * p;
522 strncpy(npath, path, CCHMAXPATH);
523 for (p = npath; *p; p++)
524 {
525 if (*p == '/') *p = '\\';
526 }
527 rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
528 }
529 else
530 {
531 rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
532 }
533 free(pfea2list);
534 if (rc)
535 {
536 maperrno(rc);
537 return -1;
538 }
539 return 0;
540}
541
542#endif
Note: See TracBrowser for help on using the repository browser.