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

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

Samba Server 3.5: more high mem work

File size: 13.3 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 connect() implementation, as it only works in low mem
195int os2_connect(int fd, const struct sockaddr *address, int address_len)
196{
197 struct sockaddr *addresslow;
198 int rc;
199 addresslow = (struct sockaddr*) _lmalloc(address_len);
200 if (!addresslow)
201 return -1;
202
203 memcpy(addresslow, address, address_len);
204 rc = connect(fd, addresslow, address_len);
205
206 free(addresslow);
207
208 return rc;
209}
210
211/* OS/2-specific random functions. these functions used to be based on APR
212 random code, but we discovered some nasty problems with it on fast hardware
213 (especially on quadcore) and decided to rewrite it with libc random() */
214
215void os2_randget(char * buffer, int length)
216{
217 UCHAR randbyte();
218 unsigned int idx;
219
220 for (idx=0; idx<length; idx++)
221 buffer[idx] = randbyte();
222
223}
224
225UCHAR randbyte()
226{
227 int c;
228 UCHAR byte;
229 ULONG ulrandom;
230 ulrandom = random();
231
232 for (c = 0; c < sizeof(ulrandom); c++) {
233 byte ^= ((UCHAR *)&ulrandom)[c];
234 }
235
236 return byte;
237}
238
239
240void maperrno(int rc)
241{
242 switch (rc)
243 {
244 case ERROR_PATH_NOT_FOUND :
245 case ERROR_FILE_NOT_FOUND : errno = ENOENT; break;
246 case ERROR_INVALID_HANDLE : errno = EBADF; break;
247 case ERROR_ACCESS_DENIED : errno = EACCES; break;
248 case ERROR_BUFFER_OVERFLOW :
249 case ERROR_NOT_ENOUGH_MEMORY : errno = ERANGE; break;
250 case ERROR_INVALID_EA_NAME : errno = ENOATTR; break;
251 case ERROR_INVALID_LEVEL :
252 case ERROR_INVALID_PARAMETER : errno = EINVAL; break;
253 case ERROR_SHARING_VIOLATION : errno = EACCES; break;
254 default : errno = EINVAL;
255 }
256}
257
258ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
259{
260 int rc, namelen;
261 EAOP2 eaop2 = {0};
262 PGEA2LIST pgea2list = NULL;
263 PFEA2LIST pfea2list = NULL;
264 char * p;
265
266 if ((!path && !file) || !name)
267 {
268 errno = EINVAL;
269 return -1;
270 }
271 namelen = strlen(name);
272 if (namelen > 0xFF)
273 {
274 errno = EINVAL;
275 return -1;
276 }
277 pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
278 pgea2list->list[0].oNextEntryOffset = 0;
279 pgea2list->list[0].cbName = namelen;
280 strcpy(pgea2list->list[0].szName, name);
281 pgea2list->cbList = sizeof(GEA2LIST) + namelen;
282
283 // max ea is 64kb
284 pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
285 pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
286
287 eaop2.fpGEA2List = pgea2list;
288 eaop2.fpFEA2List = pfea2list;
289 eaop2.oError = 0;
290 do
291 {
292 if (path)
293 {
294 char npath[CCHMAXPATH + 1] = {0};
295 strncpy(npath, path, CCHMAXPATH);
296 for (p = npath; *p; p++)
297 {
298 if (*p == '/') *p = '\\';
299 }
300 rc = DosQueryPathInfo(npath, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
301 }
302 else
303 {
304 rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
305 }
306 if (rc)
307 {
308 maperrno(rc);
309 rc = -1;
310 break;
311 }
312 if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0)
313 {
314 errno = ENOATTR;
315 rc = -1;
316 break;
317 }
318 rc = pfea2list->list[0].cbValue;
319 if (value)
320 {
321 if (size < rc)
322 {
323 errno = ERANGE;
324 rc = -1;
325 }
326 else
327 {
328 p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
329 memcpy(value, p, rc);
330 }
331 }
332 } while (0);
333 if (pgea2list)
334 {
335 free(pgea2list);
336 }
337 if (pfea2list)
338 {
339 free(pfea2list);
340 }
341 DEBUG(4,("unigetxattr : (%s:%d) %s %d\n", path ? path : "null", file, name, rc));
342 return rc;
343}
344
345ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
346{
347 ssize_t gotsize = 0;
348 unsigned long ulCount = -1;
349 int rc;
350 char * buf, *p = list;
351 PFEA2 pfea;
352 FILESTATUS4 stat = {0};
353 char npath[CCHMAXPATH + 1] = {0};
354 if (!path && !file)
355 {
356 errno = EINVAL;
357 return -1;
358 }
359 if (path)
360 {
361 char * p;
362 strncpy(npath, path, CCHMAXPATH);
363 for (p = npath; *p; p++)
364 {
365 if (*p == '/') *p = '\\';
366 }
367 rc = DosQueryPathInfo(npath, FIL_QUERYEASIZE, &stat, sizeof(stat));
368 }
369 else
370 {
371 rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
372 }
373 if (rc)
374 {
375 DEBUG(4,("unilistxattr1 : (%s:%d) %d\n", path ? path : "null", file, rc));
376 maperrno(rc);
377 return -1;
378 }
379 if (stat.cbList <= 4)
380 {
381 // NO ea
382 return 0;
383 }
384 //YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
385 buf = (char *)_tmalloc(stat.cbList * 2);
386 rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
387 if (rc)
388 {
389 DEBUG(4,("unilistxattr2 : (%s:%d) %d\n", path ? path : "null", file, rc));
390 maperrno(rc);
391 _tfree(buf);
392 return -1;
393 }
394 if (ulCount > 0)
395 for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset))
396 {
397 if (pfea->cbName > 0)
398 {
399 gotsize += pfea->cbName + 1;
400 if (p && size >= gotsize)
401 {
402 pfea->szName[pfea->cbName] = 0;
403 strcpy(p, pfea->szName);
404 p += strlen(p) + 1;
405 }
406 }
407 // had to be added to avoid crash in case of broken extended attributes
408 if (pfea->oNextEntryOffset > 0x10000)
409 {
410 // DEBUG(0, ("Broken Extended Attributes detected for: %s:%d\n", path ? path : "null", file));
411 DEBUG(0, ("Broken Extended Attributes detected for: %s:%d, Last EA:%s\n", path ? path : "null", file, pfea->szName));
412 break;
413 }
414 if (!pfea->oNextEntryOffset)
415 {
416 break;
417 }
418 }
419 _tfree(buf);
420 DEBUG(4,("unilistxattr : (%s:%d) %d\n", path ? path : "null", file, gotsize));
421 if (gotsize > size)
422 {
423 errno = ERANGE;
424 return list ? -1 : gotsize;
425 }
426 return gotsize;
427}
428
429int uniremovexattr (const char *path, int file, const char *name)
430{
431 int rc, namelen;
432 EAOP2 eaop2 = {0};
433 PFEA2LIST pfea2list = NULL;
434 char buf[300] = {0};
435
436 if ((!path && !file) || !name)
437 {
438 errno = EINVAL;
439 return -1;
440 }
441
442 namelen = strlen(name);
443 if (namelen > 0xFF)
444 {
445 errno = EINVAL;
446 return -1;
447 }
448
449 pfea2list = (PFEA2LIST)buf;
450 pfea2list->list[0].cbName = namelen;
451 pfea2list->list[0].cbValue = 0;
452 pfea2list->list[0].fEA = 0;
453 strcpy(pfea2list->list[0].szName, name);
454 pfea2list->cbList = sizeof(FEA2LIST) + namelen;
455 eaop2.fpFEA2List = pfea2list;
456
457 if (path)
458 {
459 char npath[CCHMAXPATH + 1] = {0};
460 char * p;
461 strncpy(npath, path, CCHMAXPATH);
462 for (p = npath; *p; p++)
463 {
464 if (*p == '/') *p = '\\';
465 }
466 rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
467 }
468 else
469 {
470 rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
471 }
472 if (rc)
473 {
474 maperrno(rc);
475 return -1;
476 }
477 return 0;
478}
479
480#ifndef XATTR_CREATE
481#define XATTR_CREATE 1
482#endif
483#ifndef XATTR_REPLACE
484#define XATTR_REPLACE 2
485#endif
486
487int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
488{
489 int rc, namelen, totalsize;
490 EAOP2 eaop2 = {0};
491 PFEA2LIST pfea2list = NULL;
492 char * p;
493
494 if ((!path && !file) || !name || (!value && size))
495 {
496 errno = EINVAL;
497 return -1;
498 }
499 namelen = strlen(name);
500 if (namelen > 0xFF)
501 {
502 errno = EINVAL;
503 return -1;
504 }
505
506 if (flags & (XATTR_CREATE | XATTR_REPLACE))
507 {
508 ssize_t esize = unigetxattr(path, file, name, 0, 0);
509 if (flags & XATTR_CREATE && esize > 0)
510 {
511 errno = EEXIST;
512 return -1;
513 }
514 if (flags & XATTR_REPLACE && esize < 0)
515 {
516 errno = ENOATTR;
517 return -1;
518 }
519 }
520
521 totalsize = sizeof(FEA2LIST) + size + namelen + 1;
522
523 pfea2list = (PFEA2LIST)calloc(totalsize, 1);
524 pfea2list->cbList = totalsize;
525 pfea2list->list[0].oNextEntryOffset = 0;
526 pfea2list->list[0].cbName = namelen;
527 pfea2list->list[0].cbValue = size;
528 strcpy(pfea2list->list[0].szName, name);
529 if (value)
530 {
531 memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
532 }
533 eaop2.fpFEA2List = pfea2list;
534
535 if (path)
536 {
537 char npath[CCHMAXPATH + 1] = {0};
538 char * p;
539 strncpy(npath, path, CCHMAXPATH);
540 for (p = npath; *p; p++)
541 {
542 if (*p == '/') *p = '\\';
543 }
544 rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
545 }
546 else
547 {
548 rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
549 }
550 free(pfea2list);
551 if (rc)
552 {
553 maperrno(rc);
554 return -1;
555 }
556 return 0;
557}
558
559#endif
Note: See TracBrowser for help on using the repository browser.