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

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

Samba Server 3.5: fixed a missing return, changed os2_socketpair to os2_pipe

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