source: branches/samba-3.3.x/source/lib/os2ea.c@ 370

Last change on this file since 370 was 370, checked in by Herwig Bauernfeind, 16 years ago

Update Samba 3.3 to 3.3.10 (source)

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