source: branches/samba-3.3.x/source/lib/os2ea.c @ 372

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

remove hardcoded path, remove some files

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