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

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

SambaServer 3.3: unified os2ea.c and os2path.c, rewrote randomizer

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