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

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

Samba Server 3.5: Move fix for Ticket #182 to os2helper.c

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