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

Last change on this file was 850, checked in by Silvan Scherrer, 12 years ago

Samba Server 3.5: fix EA problem

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