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

Last change on this file since 457 was 457, checked in by Herwig Bauernfeind, 10 years ago

_divers fix for Ticket #131 and #138

File size: 13.5 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    int c;
175#if 0
176// The following routine crashes on Quadcore CPUs
177    CPUUTIL util;
178
179    if (hDoscalls == 0) {
180        char failed_module[20];
181        ULONG rc;
182
183        rc = DosLoadModule(failed_module, sizeof(failed_module), "DOSCALLS",
184                           &hDoscalls);
185
186        if (rc == 0) {
187            rc = DosQueryProcAddr(hDoscalls, 976, NULL, (PFN *)&pfnDosPerfSysCall);
188
189            if (rc) {
190                pfnDosPerfSysCall = NULL;
191            }
192        }
193    }
194
195    if (pfnDosPerfSysCall) {
196        if ((*pfnDosPerfSysCall) (CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) {
197            for (c = 0; c < sizeof(util); c++) {
198                byte ^= ((UCHAR *)&util)[c];
199            }
200        }
201        else {
202            pfnDosPerfSysCall = NULL;
203        }
204    }
205#endif
206// SC's randomizer
207
208    ULONG ulrandom;
209        ulrandom = random();
210        for (c = 0; c < sizeof(ulrandom); c++) {
211                byte ^= ((UCHAR *)&ulrandom)[c];
212        }
213
214    return byte;
215}
216
217UCHAR randbyte()
218{
219    return randbyte_sysinfo() ^ randbyte_perf();
220}
221
222
223void maperrno(int rc)
224{
225        switch (rc)
226        {
227                case ERROR_PATH_NOT_FOUND    : 
228                case ERROR_FILE_NOT_FOUND    : errno = ENOENT; break;
229                case ERROR_INVALID_HANDLE    : errno = EBADF; break;
230                case ERROR_ACCESS_DENIED     : errno = EACCES; break;
231                case ERROR_BUFFER_OVERFLOW   :
232                case ERROR_NOT_ENOUGH_MEMORY : errno = ERANGE; break;
233                case ERROR_INVALID_EA_NAME   : errno = ENOATTR; break;
234                case ERROR_INVALID_LEVEL     :
235                case ERROR_INVALID_PARAMETER : errno = EINVAL; break;
236                case ERROR_SHARING_VIOLATION : errno = EACCES; break;
237                default : errno = EINVAL;
238        }
239}
240
241ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
242{
243        int rc, namelen;
244        EAOP2       eaop2 = {0};
245        PGEA2LIST   pgea2list = NULL;
246        PFEA2LIST   pfea2list = NULL;
247        char * p;
248       
249        if ((!path && !file) || !name)
250        {
251                errno = EINVAL;
252                return -1;
253        }
254        namelen = strlen(name);
255        if (namelen > 0xFF)
256        {
257                errno = EINVAL;
258                return -1;
259        }
260        pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
261        pgea2list->list[0].oNextEntryOffset = 0;
262        pgea2list->list[0].cbName = namelen;
263        strcpy(pgea2list->list[0].szName, name);
264        pgea2list->cbList = sizeof(GEA2LIST) + namelen;
265
266        // max ea is 64kb
267        pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
268        pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
269
270        eaop2.fpGEA2List = pgea2list;
271        eaop2.fpFEA2List = pfea2list;
272        eaop2.oError = 0;       
273        do
274        {
275                if (path)
276                {
277                        char npath[CCHMAXPATH + 1] = {0};
278                        strncpy(npath, path, CCHMAXPATH);
279                        for (p = npath; *p; p++)
280                        {
281                                if (*p == '/') *p = '\\';
282                        }
283                        rc = DosQueryPathInfo(npath, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
284                }
285                else
286                {
287                        rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
288                }
289                if (rc)
290                {
291                        maperrno(rc);
292                        rc = -1;
293                        break;
294                }
295                if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0)
296                {
297                        errno = ENOATTR;
298                        rc = -1;
299                        break;
300                }
301                rc = pfea2list->list[0].cbValue;
302                if (value)
303                {
304                        if (size < rc)
305                        {
306                                errno = ERANGE;
307                                rc = -1;
308                        }
309                        else
310                        {
311                                p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
312                                memcpy(value, p, rc);
313                        }
314                }
315        } while (0);
316        if (pgea2list)
317        {
318                free(pgea2list);
319        }
320        if (pfea2list)
321        {
322                free(pfea2list);
323        }
324        DEBUG(4,("unigetxattr : (%s:%d) %s %d\n", path ? path : "null", file, name, rc));
325        return rc;
326}
327
328ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
329{
330        ssize_t gotsize = 0;
331        unsigned long ulCount = -1;
332        int rc;
333        char * buf, *p = list;
334        PFEA2 pfea;
335        FILESTATUS4 stat = {0};
336        char npath[CCHMAXPATH + 1] = {0};
337        if (!path && !file)
338        {
339                errno = EINVAL;
340                return -1;
341        }
342        if (path)
343        {
344                char * p;
345                strncpy(npath, path, CCHMAXPATH);
346                for (p = npath; *p; p++)
347                {
348                        if (*p == '/') *p = '\\';
349                }
350                rc = DosQueryPathInfo(npath, FIL_QUERYEASIZE, &stat, sizeof(stat));
351        }
352        else
353        {
354                rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
355        }
356        if (rc)
357        {
358                DEBUG(4,("unilistxattr1 : (%s:%d) %d\n", path ? path : "null", file, rc));
359                maperrno(rc);
360                return -1;             
361        }
362        if (stat.cbList <= 4)
363        {
364                // NO ea
365                return 0;
366        }
367        //YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
368        buf = (char *)_tmalloc(stat.cbList * 2);
369        rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
370        if (rc)
371        {
372                DEBUG(4,("unilistxattr2 : (%s:%d) %d\n", path ? path : "null", file, rc));
373                maperrno(rc);
374                _tfree(buf);
375                return -1;
376        }
377        if (ulCount > 0)
378        for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset))
379        {
380                if (pfea->cbName > 0)
381                {
382                        gotsize += pfea->cbName + 1;
383                        if (p && size >= gotsize)
384                        {
385                                pfea->szName[pfea->cbName] = 0;
386                                strcpy(p, pfea->szName);
387                                p += strlen(p) + 1;
388                        }
389                }
390                // had to be added to avoid crash in case of broken extended attributes
391                if (pfea->oNextEntryOffset > 0x10000)
392                {
393                        DEBUG(0, ("Broken Extended Attributes detected for: %s:%d\n", path ? path : "null", file));
394                        // DEBUG(0, ("Broken Extended Attributes detected for: %s:%d, Last EA:%s\n", path ? path : "null", file, pfea->szName));
395                        break;
396                }
397                if (!pfea->oNextEntryOffset)
398                {
399                        break;
400                }
401        }
402        _tfree(buf);
403        DEBUG(4,("unilistxattr : (%s:%d) %d\n", path ? path : "null", file, gotsize));
404        if (gotsize > size)
405        {
406                errno = ERANGE;
407                return list ? -1 : gotsize;
408        }
409        return gotsize;
410}
411
412int uniremovexattr (const char *path, int file, const char *name)
413{
414        int rc, namelen;
415        EAOP2 eaop2 = {0};
416        PFEA2LIST pfea2list = NULL;
417        char buf[300] = {0};
418
419        if ((!path && !file) || !name)
420        {
421                errno = EINVAL;
422                return -1;
423        }
424
425        namelen = strlen(name);
426        if (namelen > 0xFF)
427        {
428                errno = EINVAL;
429                return -1;
430        }
431       
432        pfea2list = (PFEA2LIST)buf;
433        pfea2list->list[0].cbName = namelen;
434        pfea2list->list[0].cbValue = 0;
435        pfea2list->list[0].fEA = 0;
436        strcpy(pfea2list->list[0].szName, name);
437        pfea2list->cbList = sizeof(FEA2LIST) + namelen;
438        eaop2.fpFEA2List = pfea2list;
439
440        if (path)
441        {
442                char npath[CCHMAXPATH + 1] = {0};
443                char * p;
444                strncpy(npath, path, CCHMAXPATH);
445                for (p = npath; *p; p++)
446                {
447                        if (*p == '/') *p = '\\';
448                }
449                rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
450        }
451        else
452        {
453                rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
454        }
455        if (rc)
456        {
457                maperrno(rc);
458                return -1;
459        }
460        return 0;
461}
462
463#ifndef XATTR_CREATE
464#define XATTR_CREATE  1
465#endif
466#ifndef XATTR_REPLACE
467#define XATTR_REPLACE 2
468#endif
469
470int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
471{
472        int rc, namelen, totalsize;
473        EAOP2       eaop2 = {0};
474        PFEA2LIST   pfea2list = NULL;
475        char * p;
476       
477        if ((!path && !file) || !name || (!value && size))
478        {
479                errno = EINVAL;
480                return -1;
481        }
482        namelen = strlen(name);
483        if (namelen > 0xFF)
484        {
485                errno = EINVAL;
486                return -1;
487        }
488
489        if (flags & (XATTR_CREATE | XATTR_REPLACE))
490        {
491                ssize_t esize = unigetxattr(path, file, name, 0, 0);
492                if (flags & XATTR_CREATE && esize > 0)
493                {
494                        errno = EEXIST;
495                        return -1;
496                }
497                if (flags & XATTR_REPLACE && esize < 0)
498                {
499                        errno = ENOATTR;
500                        return -1;
501                }
502        }
503
504        totalsize = sizeof(FEA2LIST) + size + namelen + 1;
505
506        pfea2list = (PFEA2LIST)calloc(totalsize, 1);
507        pfea2list->cbList = totalsize;
508        pfea2list->list[0].oNextEntryOffset = 0;
509        pfea2list->list[0].cbName = namelen;
510        pfea2list->list[0].cbValue = size;
511        strcpy(pfea2list->list[0].szName, name);
512        if (value)
513        {
514                memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
515        }
516        eaop2.fpFEA2List = pfea2list;   
517
518        if (path)
519        {
520                char npath[CCHMAXPATH + 1] = {0};
521                char * p;
522                strncpy(npath, path, CCHMAXPATH);
523                for (p = npath; *p; p++)
524                {
525                        if (*p == '/') *p = '\\';
526                }
527                rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
528        }
529        else
530        {
531                rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
532        }
533        free(pfea2list);
534        if (rc)
535        {
536                maperrno(rc);
537                return -1;
538        }
539        return 0;
540}
541
542#endif
Note: See TracBrowser for help on using the repository browser.