source: branches/samba-3.3.x/source/lib/os2helper.c@ 472

Last change on this file since 472 was 470, checked in by Silvan Scherrer, 15 years ago

Samba Server 3.3: updated os2helper

File size: 11.0 KB
Line 
1/* This file contains helper functions for OS/2 -
2 do not try to compile on other platforms! */
3
4#ifdef __OS2__
5
6#define INCL_LONGLONG
7#define INCL_DOS
8#define INCL_DOSPROCESS
9#define INCL_DOSPROFILE
10#define INCL_DOSMISC
11#define INCL_DOSMODULEMGR
12#define INCL_DOSERRORS
13
14#include <os2.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <errno.h>
18#include <types.h>
19#include <string.h>
20//YD for tmalloc
21#include <malloc.h>
22
23// these define the attribute byte as seen by DOS
24#define aRONLY (1L<<0) /* 0x01 */
25#define aHIDDEN (1L<<1) /* 0x02 */
26#define aSYSTEM (1L<<2) /* 0x04 */
27#define aVOLID (1L<<3) /* 0x08 */
28#define aDIR (1L<<4) /* 0x10 */
29#define aARCH (1L<<5) /* 0x20 */
30
31#ifndef TESTING
32
33// Samba DEBUG() needs the following includes and defines
34#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
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#ifndef ENOATTR
45#define ENOATTR 22
46#endif
47
48int os2_ftruncate(int fd, off_t size)
49{
50 /* We call __libc_Back_ioFileSizeSet directly instead of
51 ftruncate to force it not to zero expanding files to
52 optimize Samba performance when copying files */
53
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 } else {
92 rc = DosFindClose(hdirFindHandle); /* Close our directory handle */
93 return 0;
94 } /* endif */
95}
96
97// we search the path of the .exe and return it
98int os2_GetExePath(char *buff)
99{
100 APIRET rc = NO_ERROR;
101 PPIB ppib = NULL;
102 char sExePath [_MAX_PATH];
103 char sDrive [_MAX_PATH], sDir [_MAX_DIR];
104
105 // we search for the infoblock to get the module name
106 rc = DosGetInfoBlocks(NULL, &ppib);
107 if (rc != NO_ERROR)
108 {
109 return -1;
110 }
111
112 // with the module name we get the path (including the exe name)
113 rc = DosQueryModuleName(ppib->pib_hmte, sizeof(sExePath), sExePath);
114 if (rc != NO_ERROR)
115 {
116 return -1;
117 }
118
119 // we split to the different values
120 _splitpath(sExePath, sDrive, sDir, NULL, NULL);
121 // strcat(sDrive, sDir);
122 strncat(sDrive, sDir, strlen(sDir) -1);
123 strcpy(buff, sDrive);
124
125 return 0;
126}
127
128/* OS/2-specific random functions. these functions used to be based on APR
129 random code, but we discovered some nasty problems with it on fast hardware
130 (especially on quadcore) and decided to rewrite it with libc random() */
131
132void os2_randget(char * buffer, int length)
133{
134 UCHAR randbyte();
135 unsigned int idx;
136
137 for (idx=0; idx<length; idx++)
138 buffer[idx] = randbyte();
139
140}
141
142UCHAR randbyte()
143{
144 int c;
145 UCHAR byte;
146 ULONG ulrandom;
147 ulrandom = random();
148
149 for (c = 0; c < sizeof(ulrandom); c++) {
150 byte ^= ((UCHAR *)&ulrandom)[c];
151 }
152
153 return byte;
154}
155
156
157void maperrno(int rc)
158{
159 switch (rc)
160 {
161 case ERROR_PATH_NOT_FOUND :
162 case ERROR_FILE_NOT_FOUND : errno = ENOENT; break;
163 case ERROR_INVALID_HANDLE : errno = EBADF; break;
164 case ERROR_ACCESS_DENIED : errno = EACCES; break;
165 case ERROR_BUFFER_OVERFLOW :
166 case ERROR_NOT_ENOUGH_MEMORY : errno = ERANGE; break;
167 case ERROR_INVALID_EA_NAME : errno = ENOATTR; break;
168 case ERROR_INVALID_LEVEL :
169 case ERROR_INVALID_PARAMETER : errno = EINVAL; break;
170 case ERROR_SHARING_VIOLATION : errno = EACCES; break;
171 default : errno = EINVAL;
172 }
173}
174
175ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
176{
177 int rc, namelen;
178 EAOP2 eaop2 = {0};
179 PGEA2LIST pgea2list = NULL;
180 PFEA2LIST pfea2list = NULL;
181 char * p;
182
183 if ((!path && !file) || !name)
184 {
185 errno = EINVAL;
186 return -1;
187 }
188 namelen = strlen(name);
189 if (namelen > 0xFF)
190 {
191 errno = EINVAL;
192 return -1;
193 }
194 pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
195 pgea2list->list[0].oNextEntryOffset = 0;
196 pgea2list->list[0].cbName = namelen;
197 strcpy(pgea2list->list[0].szName, name);
198 pgea2list->cbList = sizeof(GEA2LIST) + namelen;
199
200 // max ea is 64kb
201 pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
202 pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
203
204 eaop2.fpGEA2List = pgea2list;
205 eaop2.fpFEA2List = pfea2list;
206 eaop2.oError = 0;
207 do
208 {
209 if (path)
210 {
211 char npath[CCHMAXPATH + 1] = {0};
212 strncpy(npath, path, CCHMAXPATH);
213 for (p = npath; *p; p++)
214 {
215 if (*p == '/') *p = '\\';
216 }
217 rc = DosQueryPathInfo(npath, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
218 }
219 else
220 {
221 rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
222 }
223 if (rc)
224 {
225 maperrno(rc);
226 rc = -1;
227 break;
228 }
229 if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0)
230 {
231 errno = ENOATTR;
232 rc = -1;
233 break;
234 }
235 rc = pfea2list->list[0].cbValue;
236 if (value)
237 {
238 if (size < rc)
239 {
240 errno = ERANGE;
241 rc = -1;
242 }
243 else
244 {
245 p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
246 memcpy(value, p, rc);
247 }
248 }
249 } while (0);
250 if (pgea2list)
251 {
252 free(pgea2list);
253 }
254 if (pfea2list)
255 {
256 free(pfea2list);
257 }
258 DEBUG(4,("unigetxattr : (%s:%d) %s %d\n", path ? path : "null", file, name, rc));
259 return rc;
260}
261
262ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
263{
264 ssize_t gotsize = 0;
265 unsigned long ulCount = -1;
266 int rc;
267 char * buf, *p = list;
268 PFEA2 pfea;
269 FILESTATUS4 stat = {0};
270 char npath[CCHMAXPATH + 1] = {0};
271 if (!path && !file)
272 {
273 errno = EINVAL;
274 return -1;
275 }
276 if (path)
277 {
278 char * p;
279 strncpy(npath, path, CCHMAXPATH);
280 for (p = npath; *p; p++)
281 {
282 if (*p == '/') *p = '\\';
283 }
284 rc = DosQueryPathInfo(npath, FIL_QUERYEASIZE, &stat, sizeof(stat));
285 }
286 else
287 {
288 rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
289 }
290 if (rc)
291 {
292 DEBUG(4,("unilistxattr1 : (%s:%d) %d\n", path ? path : "null", file, rc));
293 maperrno(rc);
294 return -1;
295 }
296 if (stat.cbList <= 4)
297 {
298 // NO ea
299 return 0;
300 }
301 //YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
302 buf = (char *)_tmalloc(stat.cbList * 2);
303 rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
304 if (rc)
305 {
306 DEBUG(4,("unilistxattr2 : (%s:%d) %d\n", path ? path : "null", file, rc));
307 maperrno(rc);
308 _tfree(buf);
309 return -1;
310 }
311 if (ulCount > 0)
312 for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset))
313 {
314 if (pfea->cbName > 0)
315 {
316 gotsize += pfea->cbName + 1;
317 if (p && size >= gotsize)
318 {
319 pfea->szName[pfea->cbName] = 0;
320 strcpy(p, pfea->szName);
321 p += strlen(p) + 1;
322 }
323 }
324 // had to be added to avoid crash in case of broken extended attributes
325 if (pfea->oNextEntryOffset > 0x10000)
326 {
327 // DEBUG(0, ("Broken Extended Attributes detected for: %s:%d\n", path ? path : "null", file));
328 DEBUG(0, ("Broken Extended Attributes detected for: %s:%d, Last EA:%s\n", path ? path : "null", file, pfea->szName));
329 break;
330 }
331 if (!pfea->oNextEntryOffset)
332 {
333 break;
334 }
335 }
336 _tfree(buf);
337 DEBUG(4,("unilistxattr : (%s:%d) %d\n", path ? path : "null", file, gotsize));
338 if (gotsize > size)
339 {
340 errno = ERANGE;
341 return list ? -1 : gotsize;
342 }
343 return gotsize;
344}
345
346int uniremovexattr (const char *path, int file, const char *name)
347{
348 int rc, namelen;
349 EAOP2 eaop2 = {0};
350 PFEA2LIST pfea2list = NULL;
351 char buf[300] = {0};
352
353 if ((!path && !file) || !name)
354 {
355 errno = EINVAL;
356 return -1;
357 }
358
359 namelen = strlen(name);
360 if (namelen > 0xFF)
361 {
362 errno = EINVAL;
363 return -1;
364 }
365
366 pfea2list = (PFEA2LIST)buf;
367 pfea2list->list[0].cbName = namelen;
368 pfea2list->list[0].cbValue = 0;
369 pfea2list->list[0].fEA = 0;
370 strcpy(pfea2list->list[0].szName, name);
371 pfea2list->cbList = sizeof(FEA2LIST) + namelen;
372 eaop2.fpFEA2List = pfea2list;
373
374 if (path)
375 {
376 char npath[CCHMAXPATH + 1] = {0};
377 char * p;
378 strncpy(npath, path, CCHMAXPATH);
379 for (p = npath; *p; p++)
380 {
381 if (*p == '/') *p = '\\';
382 }
383 rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
384 }
385 else
386 {
387 rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
388 }
389 if (rc)
390 {
391 maperrno(rc);
392 return -1;
393 }
394 return 0;
395}
396
397#ifndef XATTR_CREATE
398#define XATTR_CREATE 1
399#endif
400#ifndef XATTR_REPLACE
401#define XATTR_REPLACE 2
402#endif
403
404int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
405{
406 int rc, namelen, totalsize;
407 EAOP2 eaop2 = {0};
408 PFEA2LIST pfea2list = NULL;
409 char * p;
410
411 if ((!path && !file) || !name || (!value && size))
412 {
413 errno = EINVAL;
414 return -1;
415 }
416 namelen = strlen(name);
417 if (namelen > 0xFF)
418 {
419 errno = EINVAL;
420 return -1;
421 }
422
423 if (flags & (XATTR_CREATE | XATTR_REPLACE))
424 {
425 ssize_t esize = unigetxattr(path, file, name, 0, 0);
426 if (flags & XATTR_CREATE && esize > 0)
427 {
428 errno = EEXIST;
429 return -1;
430 }
431 if (flags & XATTR_REPLACE && esize < 0)
432 {
433 errno = ENOATTR;
434 return -1;
435 }
436 }
437
438 totalsize = sizeof(FEA2LIST) + size + namelen + 1;
439
440 pfea2list = (PFEA2LIST)calloc(totalsize, 1);
441 pfea2list->cbList = totalsize;
442 pfea2list->list[0].oNextEntryOffset = 0;
443 pfea2list->list[0].cbName = namelen;
444 pfea2list->list[0].cbValue = size;
445 strcpy(pfea2list->list[0].szName, name);
446 if (value)
447 {
448 memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
449 }
450 eaop2.fpFEA2List = pfea2list;
451
452 if (path)
453 {
454 char npath[CCHMAXPATH + 1] = {0};
455 char * p;
456 strncpy(npath, path, CCHMAXPATH);
457 for (p = npath; *p; p++)
458 {
459 if (*p == '/') *p = '\\';
460 }
461 rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
462 }
463 else
464 {
465 rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
466 }
467 free(pfea2list);
468 if (rc)
469 {
470 maperrno(rc);
471 return -1;
472 }
473 return 0;
474}
475
476#endif
Note: See TracBrowser for help on using the repository browser.