source: branches/samba-3.3.x/source/lib/os2helper.c @ 460

Last change on this file since 460 was 460, checked in by Silvan Scherrer, 10 years ago

SambaServer? 3.3: unified os2ea.c and os2path.c, rewrote randomizer

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