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

Last change on this file since 392 was 392, checked in by Silvan Scherrer, 11 years ago

fixed ticket 112 in 3.0

File size: 13.3 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
34#include "local.h"
35#include "xfile.h"
36#include "pstring.h"
37#include "debug.h"
38#else
39#define DEBUG(a,b) (0)
40#endif
41
42#include <string.h>
43
44#ifndef ENOATTR
45#define ENOATTR 22
46#endif
47
48int os2_ftruncate(int fd, off_t size)
49{
50        // We call there __libc_Back_ioFileSizeSet directly instead of
51        // ftruncate to force it not to zero expanding files to optimize
52        // samba performance when copying files
53        int rc = __libc_Back_ioFileSizeSet(fd, size, 0);
54        if (rc < 0)
55        {
56                errno = -rc;
57                return -1;
58        }
59        return 0;
60}
61
62int os2_isattribute(char *path, unsigned short attr)
63{
64    HDIR          hdirFindHandle = HDIR_CREATE;
65    FILEFINDBUF3  FindBuffer     = {0};      /* Returned from FindFirst/Next */
66    USHORT        dosattr;                      /* attribute to search for */
67    ULONG         ulResultBufLen = sizeof(FILEFINDBUF3);
68    ULONG         ulFindCount    = 1;        /* Look for 1 file at a time    */
69    APIRET        rc             = NO_ERROR; /* Return code                  */
70    if (attr==aARCH) 
71                        dosattr=MUST_HAVE_ARCHIVED;
72    else if (attr==aRONLY)
73                        dosattr=MUST_HAVE_READONLY;
74    else if (attr==aSYSTEM)
75                        dosattr=MUST_HAVE_SYSTEM;
76    else if (attr==aHIDDEN)
77                        dosattr=MUST_HAVE_HIDDEN;
78
79    rc = DosFindFirst( path,                /* File pattern - all files     */
80                       &hdirFindHandle,      /* Directory search handle      */
81                        dosattr,
82                       &FindBuffer,          /* Result buffer                */
83                       ulResultBufLen,       /* Result buffer length         */
84                       &ulFindCount,         /* Number of entries to find    */
85                       FIL_STANDARD);        /* Return Level 1 file info     */
86
87   if (rc != NO_ERROR) {
88         rc = DosFindClose(hdirFindHandle);    /* Close our directory handle */
89       return 1;
90
91    } else {
92         rc = DosFindClose(hdirFindHandle);    /* Close our directory handle */
93        return 0;
94
95    } /* endif */
96
97}
98
99/* Functions below are based on APR random code */
100/* Licensed to the Apache Software Foundation (ASF) under one or more
101 * contributor license agreements.  See the NOTICE file distributed with
102 * this work for additional information regarding copyright ownership.
103 * The ASF licenses this file to You under the Apache License, Version 2.0
104 * (the "License"); you may not use this file except in compliance with
105 * the License.  You may obtain a copy of the License at
106 *
107 *     http://www.apache.org/licenses/LICENSE-2.0
108 *
109 * Unless required by applicable law or agreed to in writing, software
110 * distributed under the License is distributed on an "AS IS" BASIS,
111 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
112 * See the License for the specific language governing permissions and
113 * limitations under the License.
114 */
115
116void os2_randget(char * buffer, int length)
117{
118    UCHAR randbyte();
119    unsigned int idx;
120
121    for (idx=0; idx<length; idx++)
122        buffer[idx] = randbyte();
123
124}
125
126/* A bunch of system information like memory & process stats.
127 * Not highly random but every bit helps....
128 */
129static UCHAR randbyte_sysinfo()
130{
131    UCHAR byte = 0;
132    UCHAR SysVars[100];
133    int b;
134
135    DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars));
136
137    for (b = 0; b < 100; b++) {
138        byte ^= SysVars[b];
139    }
140
141    return byte;
142}
143
144
145
146/* Similar in concept to randbyte_hrtimer() but accesses the CPU's internal
147 * counters which run at the CPU's MHz speed. We get separate
148 * idle / busy / interrupt cycle counts which should provide very good
149 * randomness due to interference of hardware events.
150 * This only works on newer CPUs (at least PPro or K6) and newer OS/2 versions
151 * which is why it's run-time linked.
152 */
153
154static HMODULE hDoscalls = 0;
155#define   CMD_KI_RDCNT    (0x63)
156
157typedef struct _CPUUTIL {
158    ULONG ulTimeLow;            /* Low 32 bits of time stamp      */
159    ULONG ulTimeHigh;           /* High 32 bits of time stamp     */
160    ULONG ulIdleLow;            /* Low 32 bits of idle time       */
161    ULONG ulIdleHigh;           /* High 32 bits of idle time      */
162    ULONG ulBusyLow;            /* Low 32 bits of busy time       */
163    ULONG ulBusyHigh;           /* High 32 bits of busy time      */
164    ULONG ulIntrLow;            /* Low 32 bits of interrupt time  */
165    ULONG ulIntrHigh;           /* High 32 bits of interrupt time */
166} CPUUTIL;
167
168APIRET APIENTRY(*pfnDosPerfSysCall) (ULONG ulCommand, ULONG ulParm1, ULONG ulParm2, ULONG ulParm3) = NULL;
169APIRET APIENTRY(*pfnDosQuerySysState) (ULONG func, ULONG arg1, ULONG pid, ULONG _res_, PVOID buf, ULONG bufsz) = NULL;
170
171static UCHAR randbyte_perf()
172{
173    UCHAR byte = 0;
174    CPUUTIL util;
175    int c;
176
177    if (hDoscalls == 0) {
178        char failed_module[20];
179        ULONG rc;
180
181        rc = DosLoadModule(failed_module, sizeof(failed_module), "DOSCALLS",
182                           &hDoscalls);
183
184        if (rc == 0) {
185            rc = DosQueryProcAddr(hDoscalls, 976, NULL, (PFN *)&pfnDosPerfSysCall);
186
187            if (rc) {
188                pfnDosPerfSysCall = NULL;
189            }
190        }
191    }
192
193    if (pfnDosPerfSysCall) {
194        if ((*pfnDosPerfSysCall) (CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) {
195            for (c = 0; c < sizeof(util); c++) {
196                byte ^= ((UCHAR *)&util)[c];
197            }
198        }
199        else {
200            pfnDosPerfSysCall = NULL;
201        }
202    }
203
204    return byte;
205}
206
207
208
209UCHAR randbyte()
210{
211    return randbyte_sysinfo() ^ randbyte_perf();
212}
213
214
215void maperrno(int rc)
216{
217        switch (rc)
218        {
219                case ERROR_PATH_NOT_FOUND    : 
220                case ERROR_FILE_NOT_FOUND    : errno = ENOENT; break;
221                case ERROR_INVALID_HANDLE    : errno = EBADF; break;
222                case ERROR_ACCESS_DENIED     : errno = EACCES; break;
223                case ERROR_BUFFER_OVERFLOW   :
224                case ERROR_NOT_ENOUGH_MEMORY : errno = ERANGE; break;
225                case ERROR_INVALID_EA_NAME   : errno = ENOATTR; break;
226                case ERROR_INVALID_LEVEL     :
227                case ERROR_INVALID_PARAMETER : errno = EINVAL; break;
228                case ERROR_SHARING_VIOLATION : errno = EACCES; break;
229                default : errno = EINVAL;
230        }
231}
232
233ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
234{
235        int rc, namelen;
236        EAOP2       eaop2 = {0};
237        PGEA2LIST   pgea2list = NULL;
238        PFEA2LIST   pfea2list = NULL;
239        char * p;
240       
241        if ((!path && !file) || !name)
242        {
243                errno = EINVAL;
244                return -1;
245        }
246        namelen = strlen(name);
247        if (namelen > 0xFF)
248        {
249                errno = EINVAL;
250                return -1;
251        }
252        pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
253        pgea2list->list[0].oNextEntryOffset = 0;
254        pgea2list->list[0].cbName = namelen;
255        strcpy(pgea2list->list[0].szName, name);
256        pgea2list->cbList = sizeof(GEA2LIST) + namelen;
257
258        // max ea is 64kb
259        pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
260        pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
261
262        eaop2.fpGEA2List = pgea2list;
263        eaop2.fpFEA2List = pfea2list;
264        eaop2.oError = 0;       
265        do
266        {
267                if (path)
268                {
269                        char npath[CCHMAXPATH + 1] = {0};
270                        strncpy(npath, path, CCHMAXPATH);
271                        for (p = npath; *p; p++)
272                        {
273                                if (*p == '/') *p = '\\';
274                        }
275                        rc = DosQueryPathInfo(npath, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
276                }
277                else
278                {
279                        rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
280                }
281                if (rc)
282                {
283                        maperrno(rc);
284                        rc = -1;
285                        break;
286                }
287                if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0)
288                {
289                        errno = ENOATTR;
290                        rc = -1;
291                        break;
292                }
293                rc = pfea2list->list[0].cbValue;
294                if (value)
295                {
296                        if (size < rc)
297                        {
298                                errno = ERANGE;
299                                rc = -1;
300                        }
301                        else
302                        {
303                                p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
304                                memcpy(value, p, rc);
305                        }
306                }
307        } while (0);
308        if (pgea2list)
309        {
310                free(pgea2list);
311        }
312        if (pfea2list)
313        {
314                free(pfea2list);
315        }
316        DEBUG(4,("unigetxattr : (%s:%d) %s %d\n", path ? path : "null", file, name, rc));
317        return rc;
318}
319
320ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
321{
322        ssize_t gotsize = 0;
323        unsigned long ulCount = -1;
324        int rc;
325        char * buf, *p = list;
326        PFEA2 pfea;
327        FILESTATUS4 stat = {0};
328        char npath[CCHMAXPATH + 1] = {0};
329        if (!path && !file)
330        {
331                errno = EINVAL;
332                return -1;
333        }
334        if (path)
335        {
336                char * p;
337                strncpy(npath, path, CCHMAXPATH);
338                for (p = npath; *p; p++)
339                {
340                        if (*p == '/') *p = '\\';
341                }
342                rc = DosQueryPathInfo(npath, FIL_QUERYEASIZE, &stat, sizeof(stat));
343        }
344        else
345        {
346                rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
347        }
348        if (rc)
349        {
350                DEBUG(4,("unilistxattr1 : (%s:%d) %d\n", path ? path : "null", file, rc));
351                maperrno(rc);
352                return -1;             
353        }
354        if (stat.cbList <= 4)
355        {
356                // NO ea
357                return 0;
358        }
359        //YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
360        buf = (char *)_tmalloc(stat.cbList * 2);
361        rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
362        if (rc)
363        {
364                DEBUG(4,("unilistxattr2 : (%s:%d) %d\n", path ? path : "null", file, rc));
365                maperrno(rc);
366                _tfree(buf);
367                return -1;
368        }
369        if (ulCount > 0)
370        for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset))
371        {
372                if (pfea->cbName > 0)
373                {
374                        gotsize += pfea->cbName + 1;
375                        if (p && size >= gotsize)
376                        {
377                                pfea->szName[pfea->cbName] = 0;
378                                strcpy(p, pfea->szName);
379                                p += strlen(p) + 1;
380                        }
381                }
382                // had to be added to avoid crash in case of broken extended attributes
383                if (pfea->oNextEntryOffset > 0x10000)
384                {
385                        DEBUG(0, ("Broken Extended Attributes detected for: %s:%d\n", path ? path : "null", file));
386                        // DEBUG(0, ("Broken Extended Attributes detected for: %s:%d, Last EA:%s\n", path ? path : "null", file, pfea->szName));
387                        break;
388                }
389                if (!pfea->oNextEntryOffset)
390                {
391                        break;
392                }
393        }
394        _tfree(buf);
395        DEBUG(4,("unilistxattr : (%s:%d) %d\n", path ? path : "null", file, gotsize));
396        if (gotsize > size)
397        {
398                errno = ERANGE;
399                return list ? -1 : gotsize;
400        }
401        return gotsize;
402}
403
404int uniremovexattr (const char *path, int file, const char *name)
405{
406        int rc, namelen;
407        EAOP2 eaop2 = {0};
408        PFEA2LIST pfea2list = NULL;
409        char buf[300] = {0};
410
411        if ((!path && !file) || !name)
412        {
413                errno = EINVAL;
414                return -1;
415        }
416
417        namelen = strlen(name);
418        if (namelen > 0xFF)
419        {
420                errno = EINVAL;
421                return -1;
422        }
423       
424        pfea2list = (PFEA2LIST)buf;
425        pfea2list->list[0].cbName = namelen;
426        pfea2list->list[0].cbValue = 0;
427        pfea2list->list[0].fEA = 0;
428        strcpy(pfea2list->list[0].szName, name);
429        pfea2list->cbList = sizeof(FEA2LIST) + namelen;
430        eaop2.fpFEA2List = pfea2list;
431
432        if (path)
433        {
434                char npath[CCHMAXPATH + 1] = {0};
435                char * p;
436                strncpy(npath, path, CCHMAXPATH);
437                for (p = npath; *p; p++)
438                {
439                        if (*p == '/') *p = '\\';
440                }
441                rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
442        }
443        else
444        {
445                rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
446        }
447        if (rc)
448        {
449                maperrno(rc);
450                return -1;
451        }
452        return 0;
453}
454
455#ifndef XATTR_CREATE
456#define XATTR_CREATE  1
457#endif
458#ifndef XATTR_REPLACE
459#define XATTR_REPLACE 2
460#endif
461
462int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
463{
464        int rc, namelen, totalsize;
465        EAOP2       eaop2 = {0};
466        PFEA2LIST   pfea2list = NULL;
467        char * p;
468       
469        if ((!path && !file) || !name || (!value && size))
470        {
471                errno = EINVAL;
472                return -1;
473        }
474        namelen = strlen(name);
475        if (namelen > 0xFF)
476        {
477                errno = EINVAL;
478                return -1;
479        }
480
481        if (flags & (XATTR_CREATE | XATTR_REPLACE))
482        {
483                ssize_t esize = unigetxattr(path, file, name, 0, 0);
484                if (flags & XATTR_CREATE && esize > 0)
485                {
486                        errno = EEXIST;
487                        return -1;
488                }
489                if (flags & XATTR_REPLACE && esize < 0)
490                {
491                        errno = ENOATTR;
492                        return -1;
493                }
494        }
495
496        totalsize = sizeof(FEA2LIST) + size + namelen + 1;
497
498        pfea2list = (PFEA2LIST)calloc(totalsize, 1);
499        pfea2list->cbList = totalsize;
500        pfea2list->list[0].oNextEntryOffset = 0;
501        pfea2list->list[0].cbName = namelen;
502        pfea2list->list[0].cbValue = size;
503        strcpy(pfea2list->list[0].szName, name);
504        if (value)
505        {
506                memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
507        }
508        eaop2.fpFEA2List = pfea2list;   
509
510        if (path)
511        {
512                char npath[CCHMAXPATH + 1] = {0};
513                char * p;
514                strncpy(npath, path, CCHMAXPATH);
515                for (p = npath; *p; p++)
516                {
517                        if (*p == '/') *p = '\\';
518                }
519                rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
520        }
521        else
522        {
523                rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
524        }
525        free(pfea2list);
526        if (rc)
527        {
528                maperrno(rc);
529                return -1;
530        }
531        return 0;
532}
533
534#endif
Note: See TracBrowser for help on using the repository browser.