source: branches/samba-3.3.x/source/lib/os2helper.c@ 937

Last change on this file since 937 was 699, checked in by Silvan Scherrer, 13 years ago

Samba Server 3.3: made it high-mem aware

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