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

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

Samba Server 3.5: some work to get high-mem working

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