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

Last change on this file since 396 was 372, checked in by Silvan Scherrer, 16 years ago

remove hardcoded path, remove some files

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