source: branches/samba-3.5.x/source3/lib/os2helper.c@ 773

Last change on this file since 773 was 773, checked in by Herwig Bauernfeind, 12 years ago

Samba Server 3.5: Update branch to 3.5.20

File size: 14.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 * 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
183filehandle is not working. */
184int os2_pipe(int fds[2])
185{
186 int rc = 0;
187
188 rc = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
189 return rc;
190}
191
192#if 0
193// OS/2 specific connect() implementation, as it only works in low mem
194int os2_connect(int fd, const struct sockaddr *address, int address_len)
195{
196 struct sockaddr *addresslow;
197 int rc;
198 addresslow = (struct sockaddr*) _lmalloc(address_len);
199 if (!addresslow)
200 return -1;
201
202 memcpy(addresslow, address, address_len);
203 rc = connect(fd, addresslow, address_len);
204
205 free(addresslow);
206
207 return rc;
208}
209#endif
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 DEBUG(4,("unisetxattr : (%s:%d) %s %d\n", path ? path : "null", file, name, size));
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/* set date/time on OS/2 */
560int os2_setdatetime(time_t t)
561{
562 struct tm *tm;
563
564 tm = localtime(&t);
565 if (!tm) {
566 return -1;
567 }
568
569 DATETIME DateTime = {0};
570 APIRET rc = NO_ERROR;
571
572 /* Get current date/time to properly fill structure */
573 rc = DosGetDateTime(&DateTime);
574 if (rc != NO_ERROR) {
575 return rc;
576 }
577
578 DateTime.year = (USHORT) ((BYTE) tm->tm_year+1900);
579 DateTime.month = (UCHAR) ((BYTE) tm->tm_mon+1);
580 DateTime.day = (UCHAR) ((BYTE) tm->tm_mday);
581 DateTime.hours = (UCHAR) ((BYTE) tm->tm_hour);
582 DateTime.minutes = (UCHAR) ((BYTE) tm->tm_min);
583 DateTime.seconds = (UCHAR) ((BYTE) tm->tm_sec);
584
585 rc = DosSetDateTime(&DateTime); /* Update the date and time */
586
587 if (rc!= NO_ERROR) {
588 printf ("DosSetDateTime error : return code = %u\n", rc);
589 }
590 return rc;
591}
592
593#endif
Note: See TracBrowser for help on using the repository browser.