source: branches/samba-3.0/source/lib/os2ea.c@ 104

Last change on this file since 104 was 56, checked in by Paul Smedley, 18 years ago

Add new function os2_isattribute to check file attributes

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