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

Last change on this file since 463 was 463, checked in by Silvan Scherrer, 15 years ago

Samba Server 3.5: included os2helper from 3.3 instead of os2ea & os2path

File size: 11.1 KB
Line 
1/* This file contains helper functions for OS/2 -
2 do not try to compile on other platforms! */
3
4#ifdef __OS2__
5
6#define INCL_LONGLONG
7#define INCL_DOS
8#define INCL_DOSPROCESS
9#define INCL_DOSPROFILE
10#define INCL_DOSMISC
11#define INCL_DOSMODULEMGR
12#define INCL_DOSERRORS
13
14#include <os2.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <errno.h>
18#include <types.h>
19#include <string.h>
20//YD for tmalloc
21#include <malloc.h>
22
23/* these define the attribute byte as seen by DOS */
24#define aRONLY (1L<<0) /* 0x01 */
25#define aHIDDEN (1L<<1) /* 0x02 */
26#define aSYSTEM (1L<<2) /* 0x04 */
27#define aVOLID (1L<<3) /* 0x08 */
28#define aDIR (1L<<4) /* 0x10 */
29#define aARCH (1L<<5) /* 0x20 */
30
31#ifndef TESTING
32
33// Samba DEBUG() needs the following includes and defines
34#include <stdbool.h>
35#include "../lib/replace/replace.h"
36#include "local.h"
37#include "../lib/util/attr.h"
38#include "../lib/util/xfile.h"
39#include "debug.h"
40#else
41
42#define DEBUG(a,b) (0)
43#endif
44
45#ifndef ENOATTR
46#define ENOATTR 22
47#endif
48
49int os2_ftruncate(int fd, off_t size)
50{
51 /* We call __libc_Back_ioFileSizeSet directly instead of
52 ftruncate to force it not to zero expanding files to optimize
53 samba performance when copying files */
54
55 int rc = __libc_Back_ioFileSizeSet(fd, size, 0);
56 if (rc < 0)
57 {
58 errno = -rc;
59 return -1;
60 }
61 return 0;
62}
63
64int os2_isattribute(char *path, unsigned short attr)
65{
66 HDIR hdirFindHandle = HDIR_CREATE;
67 FILEFINDBUF3 FindBuffer = {0}; /* Returned from FindFirst/Next */
68 USHORT dosattr; /* attribute to search for */
69 ULONG ulResultBufLen = sizeof(FILEFINDBUF3);
70 ULONG ulFindCount = 1; /* Look for 1 file at a time */
71 APIRET rc = NO_ERROR; /* Return code */
72 if (attr==aARCH)
73 dosattr=MUST_HAVE_ARCHIVED;
74 else if (attr==aRONLY)
75 dosattr=MUST_HAVE_READONLY;
76 else if (attr==aSYSTEM)
77 dosattr=MUST_HAVE_SYSTEM;
78 else if (attr==aHIDDEN)
79 dosattr=MUST_HAVE_HIDDEN;
80
81 rc = DosFindFirst( path, /* File pattern - all files */
82 &hdirFindHandle, /* Directory search handle */
83 dosattr,
84 &FindBuffer, /* Result buffer */
85 ulResultBufLen, /* Result buffer length */
86 &ulFindCount, /* Number of entries to find */
87 FIL_STANDARD); /* Return Level 1 file info */
88
89 if (rc != NO_ERROR) {
90 rc = DosFindClose(hdirFindHandle); /* Close our directory handle */
91 return 1;
92 } else {
93 rc = DosFindClose(hdirFindHandle); /* Close our directory handle */
94 return 0;
95 } /* endif */
96}
97
98// we search the path of the .exe and return it
99int os2_GetExePath(char *buff)
100{
101 APIRET rc = NO_ERROR;
102 PPIB ppib = NULL;
103 char sExePath [_MAX_PATH];
104 char sDrive [_MAX_PATH], sDir [_MAX_DIR];
105
106 // we search for the infoblock to get the module name
107 rc = DosGetInfoBlocks(NULL, &ppib);
108 if (rc != NO_ERROR)
109 {
110 return -1;
111 }
112
113 // with the module name we get the path (including the exe name)
114 rc = DosQueryModuleName(ppib->pib_hmte, sizeof(sExePath), sExePath);
115 if (rc != NO_ERROR)
116 {
117 return -1;
118 }
119
120 // we split to the different values
121 _splitpath(sExePath, sDrive, sDir, NULL, NULL);
122 // strcat(sDrive, sDir);
123 strncat(sDrive, sDir, strlen(sDir) -1);
124 strcpy(buff, sDrive);
125
126 return 0;
127}
128
129/* OS/2-specific random functions. these functions used to be based on APR
130 random code, but we discovered some nasty problems with it on fast hardware
131 (especially on quadcore) and decided to rewrite it with libc random() */
132
133void os2_randget(char * buffer, int length)
134{
135 UCHAR randbyte();
136 unsigned int idx;
137
138 for (idx=0; idx<length; idx++)
139 buffer[idx] = randbyte();
140
141}
142
143UCHAR randbyte()
144{
145 int c;
146 UCHAR byte;
147 ULONG ulrandom;
148 ulrandom = random();
149
150 for (c = 0; c < sizeof(ulrandom); c++) {
151 byte ^= ((UCHAR *)&ulrandom)[c];
152 }
153
154 return byte;
155}
156
157
158void maperrno(int rc)
159{
160 switch (rc)
161 {
162 case ERROR_PATH_NOT_FOUND :
163 case ERROR_FILE_NOT_FOUND : errno = ENOENT; break;
164 case ERROR_INVALID_HANDLE : errno = EBADF; break;
165 case ERROR_ACCESS_DENIED : errno = EACCES; break;
166 case ERROR_BUFFER_OVERFLOW :
167 case ERROR_NOT_ENOUGH_MEMORY : errno = ERANGE; break;
168 case ERROR_INVALID_EA_NAME : errno = ENOATTR; break;
169 case ERROR_INVALID_LEVEL :
170 case ERROR_INVALID_PARAMETER : errno = EINVAL; break;
171 case ERROR_SHARING_VIOLATION : errno = EACCES; break;
172 default : errno = EINVAL;
173 }
174}
175
176ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
177{
178 int rc, namelen;
179 EAOP2 eaop2 = {0};
180 PGEA2LIST pgea2list = NULL;
181 PFEA2LIST pfea2list = NULL;
182 char * p;
183
184 if ((!path && !file) || !name)
185 {
186 errno = EINVAL;
187 return -1;
188 }
189 namelen = strlen(name);
190 if (namelen > 0xFF)
191 {
192 errno = EINVAL;
193 return -1;
194 }
195 pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
196 pgea2list->list[0].oNextEntryOffset = 0;
197 pgea2list->list[0].cbName = namelen;
198 strcpy(pgea2list->list[0].szName, name);
199 pgea2list->cbList = sizeof(GEA2LIST) + namelen;
200
201 // max ea is 64kb
202 pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
203 pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
204
205 eaop2.fpGEA2List = pgea2list;
206 eaop2.fpFEA2List = pfea2list;
207 eaop2.oError = 0;
208 do
209 {
210 if (path)
211 {
212 char npath[CCHMAXPATH + 1] = {0};
213 strncpy(npath, path, CCHMAXPATH);
214 for (p = npath; *p; p++)
215 {
216 if (*p == '/') *p = '\\';
217 }
218 rc = DosQueryPathInfo(npath, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
219 }
220 else
221 {
222 rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
223 }
224 if (rc)
225 {
226 maperrno(rc);
227 rc = -1;
228 break;
229 }
230 if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0)
231 {
232 errno = ENOATTR;
233 rc = -1;
234 break;
235 }
236 rc = pfea2list->list[0].cbValue;
237 if (value)
238 {
239 if (size < rc)
240 {
241 errno = ERANGE;
242 rc = -1;
243 }
244 else
245 {
246 p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
247 memcpy(value, p, rc);
248 }
249 }
250 } while (0);
251 if (pgea2list)
252 {
253 free(pgea2list);
254 }
255 if (pfea2list)
256 {
257 free(pfea2list);
258 }
259 DEBUG(4,("unigetxattr : (%s:%d) %s %d\n", path ? path : "null", file, name, rc));
260 return rc;
261}
262
263ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
264{
265 ssize_t gotsize = 0;
266 unsigned long ulCount = -1;
267 int rc;
268 char * buf, *p = list;
269 PFEA2 pfea;
270 FILESTATUS4 stat = {0};
271 char npath[CCHMAXPATH + 1] = {0};
272 if (!path && !file)
273 {
274 errno = EINVAL;
275 return -1;
276 }
277 if (path)
278 {
279 char * p;
280 strncpy(npath, path, CCHMAXPATH);
281 for (p = npath; *p; p++)
282 {
283 if (*p == '/') *p = '\\';
284 }
285 rc = DosQueryPathInfo(npath, FIL_QUERYEASIZE, &stat, sizeof(stat));
286 }
287 else
288 {
289 rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
290 }
291 if (rc)
292 {
293 DEBUG(4,("unilistxattr1 : (%s:%d) %d\n", path ? path : "null", file, rc));
294 maperrno(rc);
295 return -1;
296 }
297 if (stat.cbList <= 4)
298 {
299 // NO ea
300 return 0;
301 }
302 //YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
303 buf = (char *)_tmalloc(stat.cbList * 2);
304 rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
305 if (rc)
306 {
307 DEBUG(4,("unilistxattr2 : (%s:%d) %d\n", path ? path : "null", file, rc));
308 maperrno(rc);
309 _tfree(buf);
310 return -1;
311 }
312 if (ulCount > 0)
313 for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset))
314 {
315 if (pfea->cbName > 0)
316 {
317 gotsize += pfea->cbName + 1;
318 if (p && size >= gotsize)
319 {
320 pfea->szName[pfea->cbName] = 0;
321 strcpy(p, pfea->szName);
322 p += strlen(p) + 1;
323 }
324 }
325 // had to be added to avoid crash in case of broken extended attributes
326 if (pfea->oNextEntryOffset > 0x10000)
327 {
328 // DEBUG(0, ("Broken Extended Attributes detected for: %s:%d\n", path ? path : "null", file));
329 DEBUG(0, ("Broken Extended Attributes detected for: %s:%d, Last EA:%s\n", path ? path : "null", file, pfea->szName));
330 break;
331 }
332 if (!pfea->oNextEntryOffset)
333 {
334 break;
335 }
336 }
337 _tfree(buf);
338 DEBUG(4,("unilistxattr : (%s:%d) %d\n", path ? path : "null", file, gotsize));
339 if (gotsize > size)
340 {
341 errno = ERANGE;
342 return list ? -1 : gotsize;
343 }
344 return gotsize;
345}
346
347int uniremovexattr (const char *path, int file, const char *name)
348{
349 int rc, namelen;
350 EAOP2 eaop2 = {0};
351 PFEA2LIST pfea2list = NULL;
352 char buf[300] = {0};
353
354 if ((!path && !file) || !name)
355 {
356 errno = EINVAL;
357 return -1;
358 }
359
360 namelen = strlen(name);
361 if (namelen > 0xFF)
362 {
363 errno = EINVAL;
364 return -1;
365 }
366
367 pfea2list = (PFEA2LIST)buf;
368 pfea2list->list[0].cbName = namelen;
369 pfea2list->list[0].cbValue = 0;
370 pfea2list->list[0].fEA = 0;
371 strcpy(pfea2list->list[0].szName, name);
372 pfea2list->cbList = sizeof(FEA2LIST) + namelen;
373 eaop2.fpFEA2List = pfea2list;
374
375 if (path)
376 {
377 char npath[CCHMAXPATH + 1] = {0};
378 char * p;
379 strncpy(npath, path, CCHMAXPATH);
380 for (p = npath; *p; p++)
381 {
382 if (*p == '/') *p = '\\';
383 }
384 rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
385 }
386 else
387 {
388 rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
389 }
390 if (rc)
391 {
392 maperrno(rc);
393 return -1;
394 }
395 return 0;
396}
397
398#ifndef XATTR_CREATE
399#define XATTR_CREATE 1
400#endif
401#ifndef XATTR_REPLACE
402#define XATTR_REPLACE 2
403#endif
404
405int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
406{
407 int rc, namelen, totalsize;
408 EAOP2 eaop2 = {0};
409 PFEA2LIST pfea2list = NULL;
410 char * p;
411
412 if ((!path && !file) || !name || (!value && size))
413 {
414 errno = EINVAL;
415 return -1;
416 }
417 namelen = strlen(name);
418 if (namelen > 0xFF)
419 {
420 errno = EINVAL;
421 return -1;
422 }
423
424 if (flags & (XATTR_CREATE | XATTR_REPLACE))
425 {
426 ssize_t esize = unigetxattr(path, file, name, 0, 0);
427 if (flags & XATTR_CREATE && esize > 0)
428 {
429 errno = EEXIST;
430 return -1;
431 }
432 if (flags & XATTR_REPLACE && esize < 0)
433 {
434 errno = ENOATTR;
435 return -1;
436 }
437 }
438
439 totalsize = sizeof(FEA2LIST) + size + namelen + 1;
440
441 pfea2list = (PFEA2LIST)calloc(totalsize, 1);
442 pfea2list->cbList = totalsize;
443 pfea2list->list[0].oNextEntryOffset = 0;
444 pfea2list->list[0].cbName = namelen;
445 pfea2list->list[0].cbValue = size;
446 strcpy(pfea2list->list[0].szName, name);
447 if (value)
448 {
449 memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
450 }
451 eaop2.fpFEA2List = pfea2list;
452
453 if (path)
454 {
455 char npath[CCHMAXPATH + 1] = {0};
456 char * p;
457 strncpy(npath, path, CCHMAXPATH);
458 for (p = npath; *p; p++)
459 {
460 if (*p == '/') *p = '\\';
461 }
462 rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
463 }
464 else
465 {
466 rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
467 }
468 free(pfea2list);
469 if (rc)
470 {
471 maperrno(rc);
472 return -1;
473 }
474 return 0;
475}
476
477#endif
Note: See TracBrowser for help on using the repository browser.