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

Last change on this file since 656 was 656, checked in by Herwig Bauernfeind, 14 years ago

Samba Server 3.5: Some more work to get high-mem working

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