source: trunk/server/source3/lib/os2helper.c@ 586

Last change on this file since 586 was 586, checked in by Silvan Scherrer, 14 years ago

samba server 3.5: reworked os2_getexename()

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