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

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

Samba Server 3.3: Fix for Ticket #182

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