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

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

Samba Server 3.3: fixed ticket 144

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