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

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

Samba Server 3.3: updated os2helper

File size: 11.0 KB
Line 
1/* This file contains helper functions for OS/2 -
2   do not try to compile on other platforms! */
3
4#ifdef __OS2__
5
6#define INCL_LONGLONG
7#define INCL_DOS
8#define INCL_DOSPROCESS
9#define INCL_DOSPROFILE
10#define INCL_DOSMISC
11#define INCL_DOSMODULEMGR
12#define INCL_DOSERRORS
13
14#include <os2.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <errno.h>
18#include <types.h>
19#include <string.h>
20//YD for tmalloc
21#include <malloc.h>
22
23// these define the attribute byte as seen by DOS
24#define aRONLY (1L<<0)   /* 0x01 */
25#define aHIDDEN (1L<<1)  /* 0x02 */
26#define aSYSTEM (1L<<2)  /* 0x04 */
27#define aVOLID (1L<<3)   /* 0x08 */
28#define aDIR (1L<<4)     /* 0x10 */
29#define aARCH (1L<<5)    /* 0x20 */
30
31#ifndef TESTING
32
33// Samba DEBUG() needs the following includes and defines
34#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
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#ifndef ENOATTR
45#define ENOATTR 22
46#endif
47
48int os2_ftruncate(int fd, off_t size)
49{
50        /* We call __libc_Back_ioFileSizeSet directly instead of
51           ftruncate to force it not to zero expanding files to
52           optimize Samba performance when copying files */
53
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        } else {
92                rc = DosFindClose(hdirFindHandle);    /* Close our directory handle */
93                return 0;
94        } /* endif */
95}
96
97// we search the path of the .exe and return it
98int os2_GetExePath(char *buff)
99{
100        APIRET rc = NO_ERROR;
101        PPIB ppib = NULL;
102        char sExePath [_MAX_PATH];
103        char sDrive [_MAX_PATH], sDir [_MAX_DIR]; 
104
105        // we search for the infoblock to get the module name
106        rc = DosGetInfoBlocks(NULL, &ppib);
107        if (rc != NO_ERROR)
108        {
109                return -1;
110        }
111
112        // with the module name we get the path (including the exe name)
113        rc = DosQueryModuleName(ppib->pib_hmte, sizeof(sExePath), sExePath);
114        if (rc != NO_ERROR)
115        {
116                return -1;
117        }
118
119        // we split to the different values
120        _splitpath(sExePath, sDrive, sDir, NULL, NULL);
121        // strcat(sDrive, sDir);
122        strncat(sDrive, sDir, strlen(sDir) -1);
123        strcpy(buff, sDrive);
124
125        return 0;
126}
127
128/* OS/2-specific random functions. these functions used to be based on APR
129   random code, but we discovered some nasty problems with it on fast hardware
130   (especially on quadcore) and decided to rewrite it with libc random() */
131
132void os2_randget(char * buffer, int length)
133{
134        UCHAR randbyte();
135        unsigned int idx;
136
137        for (idx=0; idx<length; idx++)
138        buffer[idx] = randbyte();
139
140}
141
142UCHAR randbyte()
143{
144        int c;
145        UCHAR byte;
146        ULONG ulrandom;
147        ulrandom = random();
148       
149        for (c = 0; c < sizeof(ulrandom); c++) {
150                byte ^= ((UCHAR *)&ulrandom)[c];
151        }
152
153        return byte;
154}
155
156
157void maperrno(int rc)
158{
159        switch (rc)
160        {
161                case ERROR_PATH_NOT_FOUND    : 
162                case ERROR_FILE_NOT_FOUND    : errno = ENOENT; break;
163                case ERROR_INVALID_HANDLE    : errno = EBADF; break;
164                case ERROR_ACCESS_DENIED     : errno = EACCES; break;
165                case ERROR_BUFFER_OVERFLOW   :
166                case ERROR_NOT_ENOUGH_MEMORY : errno = ERANGE; break;
167                case ERROR_INVALID_EA_NAME   : errno = ENOATTR; break;
168                case ERROR_INVALID_LEVEL     :
169                case ERROR_INVALID_PARAMETER : errno = EINVAL; break;
170                case ERROR_SHARING_VIOLATION : errno = EACCES; break;
171                default : errno = EINVAL;
172        }
173}
174
175ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size)
176{
177        int rc, namelen;
178        EAOP2       eaop2 = {0};
179        PGEA2LIST   pgea2list = NULL;
180        PFEA2LIST   pfea2list = NULL;
181        char * p;
182       
183        if ((!path && !file) || !name)
184        {
185                errno = EINVAL;
186                return -1;
187        }
188        namelen = strlen(name);
189        if (namelen > 0xFF)
190        {
191                errno = EINVAL;
192                return -1;
193        }
194        pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1);
195        pgea2list->list[0].oNextEntryOffset = 0;
196        pgea2list->list[0].cbName = namelen;
197        strcpy(pgea2list->list[0].szName, name);
198        pgea2list->cbList = sizeof(GEA2LIST) + namelen;
199
200        // max ea is 64kb
201        pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1);
202        pfea2list->cbList = sizeof(FEA2LIST) + 0x10000;
203
204        eaop2.fpGEA2List = pgea2list;
205        eaop2.fpFEA2List = pfea2list;
206        eaop2.oError = 0;       
207        do
208        {
209                if (path)
210                {
211                        char npath[CCHMAXPATH + 1] = {0};
212                        strncpy(npath, path, CCHMAXPATH);
213                        for (p = npath; *p; p++)
214                        {
215                                if (*p == '/') *p = '\\';
216                        }
217                        rc = DosQueryPathInfo(npath, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
218                }
219                else
220                {
221                        rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2));
222                }
223                if (rc)
224                {
225                        maperrno(rc);
226                        rc = -1;
227                        break;
228                }
229                if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0)
230                {
231                        errno = ENOATTR;
232                        rc = -1;
233                        break;
234                }
235                rc = pfea2list->list[0].cbValue;
236                if (value)
237                {
238                        if (size < rc)
239                        {
240                                errno = ERANGE;
241                                rc = -1;
242                        }
243                        else
244                        {
245                                p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1;
246                                memcpy(value, p, rc);
247                        }
248                }
249        } while (0);
250        if (pgea2list)
251        {
252                free(pgea2list);
253        }
254        if (pfea2list)
255        {
256                free(pfea2list);
257        }
258        DEBUG(4,("unigetxattr : (%s:%d) %s %d\n", path ? path : "null", file, name, rc));
259        return rc;
260}
261
262ssize_t unilistxattr (const char *path, int file, char *list, size_t size)
263{
264        ssize_t gotsize = 0;
265        unsigned long ulCount = -1;
266        int rc;
267        char * buf, *p = list;
268        PFEA2 pfea;
269        FILESTATUS4 stat = {0};
270        char npath[CCHMAXPATH + 1] = {0};
271        if (!path && !file)
272        {
273                errno = EINVAL;
274                return -1;
275        }
276        if (path)
277        {
278                char * p;
279                strncpy(npath, path, CCHMAXPATH);
280                for (p = npath; *p; p++)
281                {
282                        if (*p == '/') *p = '\\';
283                }
284                rc = DosQueryPathInfo(npath, FIL_QUERYEASIZE, &stat, sizeof(stat));
285        }
286        else
287        {
288                rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat));
289        }
290        if (rc)
291        {
292                DEBUG(4,("unilistxattr1 : (%s:%d) %d\n", path ? path : "null", file, rc));
293                maperrno(rc);
294                return -1;             
295        }
296        if (stat.cbList <= 4)
297        {
298                // NO ea
299                return 0;
300        }
301        //YD DosEnumAttribute doesn't like high-mem buffers, get a low one.
302        buf = (char *)_tmalloc(stat.cbList * 2);
303        rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1);
304        if (rc)
305        {
306                DEBUG(4,("unilistxattr2 : (%s:%d) %d\n", path ? path : "null", file, rc));
307                maperrno(rc);
308                _tfree(buf);
309                return -1;
310        }
311        if (ulCount > 0)
312        for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset))
313        {
314                if (pfea->cbName > 0)
315                {
316                        gotsize += pfea->cbName + 1;
317                        if (p && size >= gotsize)
318                        {
319                                pfea->szName[pfea->cbName] = 0;
320                                strcpy(p, pfea->szName);
321                                p += strlen(p) + 1;
322                        }
323                }
324                // had to be added to avoid crash in case of broken extended attributes
325                if (pfea->oNextEntryOffset > 0x10000)
326                {
327                        // DEBUG(0, ("Broken Extended Attributes detected for: %s:%d\n", path ? path : "null", file));
328                        DEBUG(0, ("Broken Extended Attributes detected for: %s:%d, Last EA:%s\n", path ? path : "null", file, pfea->szName));
329                        break;
330                }
331                if (!pfea->oNextEntryOffset)
332                {
333                        break;
334                }
335        }
336        _tfree(buf);
337        DEBUG(4,("unilistxattr : (%s:%d) %d\n", path ? path : "null", file, gotsize));
338        if (gotsize > size)
339        {
340                errno = ERANGE;
341                return list ? -1 : gotsize;
342        }
343        return gotsize;
344}
345
346int uniremovexattr (const char *path, int file, const char *name)
347{
348        int rc, namelen;
349        EAOP2 eaop2 = {0};
350        PFEA2LIST pfea2list = NULL;
351        char buf[300] = {0};
352
353        if ((!path && !file) || !name)
354        {
355                errno = EINVAL;
356                return -1;
357        }
358
359        namelen = strlen(name);
360        if (namelen > 0xFF)
361        {
362                errno = EINVAL;
363                return -1;
364        }
365       
366        pfea2list = (PFEA2LIST)buf;
367        pfea2list->list[0].cbName = namelen;
368        pfea2list->list[0].cbValue = 0;
369        pfea2list->list[0].fEA = 0;
370        strcpy(pfea2list->list[0].szName, name);
371        pfea2list->cbList = sizeof(FEA2LIST) + namelen;
372        eaop2.fpFEA2List = pfea2list;
373
374        if (path)
375        {
376                char npath[CCHMAXPATH + 1] = {0};
377                char * p;
378                strncpy(npath, path, CCHMAXPATH);
379                for (p = npath; *p; p++)
380                {
381                        if (*p == '/') *p = '\\';
382                }
383                rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
384        }
385        else
386        {
387                rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
388        }
389        if (rc)
390        {
391                maperrno(rc);
392                return -1;
393        }
394        return 0;
395}
396
397#ifndef XATTR_CREATE
398#define XATTR_CREATE  1
399#endif
400#ifndef XATTR_REPLACE
401#define XATTR_REPLACE 2
402#endif
403
404int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags)
405{
406        int rc, namelen, totalsize;
407        EAOP2       eaop2 = {0};
408        PFEA2LIST   pfea2list = NULL;
409        char * p;
410       
411        if ((!path && !file) || !name || (!value && size))
412        {
413                errno = EINVAL;
414                return -1;
415        }
416        namelen = strlen(name);
417        if (namelen > 0xFF)
418        {
419                errno = EINVAL;
420                return -1;
421        }
422
423        if (flags & (XATTR_CREATE | XATTR_REPLACE))
424        {
425                ssize_t esize = unigetxattr(path, file, name, 0, 0);
426                if (flags & XATTR_CREATE && esize > 0)
427                {
428                        errno = EEXIST;
429                        return -1;
430                }
431                if (flags & XATTR_REPLACE && esize < 0)
432                {
433                        errno = ENOATTR;
434                        return -1;
435                }
436        }
437
438        totalsize = sizeof(FEA2LIST) + size + namelen + 1;
439
440        pfea2list = (PFEA2LIST)calloc(totalsize, 1);
441        pfea2list->cbList = totalsize;
442        pfea2list->list[0].oNextEntryOffset = 0;
443        pfea2list->list[0].cbName = namelen;
444        pfea2list->list[0].cbValue = size;
445        strcpy(pfea2list->list[0].szName, name);
446        if (value)
447        {
448                memcpy(pfea2list->list[0].szName + namelen + 1, value, size);
449        }
450        eaop2.fpFEA2List = pfea2list;   
451
452        if (path)
453        {
454                char npath[CCHMAXPATH + 1] = {0};
455                char * p;
456                strncpy(npath, path, CCHMAXPATH);
457                for (p = npath; *p; p++)
458                {
459                        if (*p == '/') *p = '\\';
460                }
461                rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU);
462        }
463        else
464        {
465                rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2));
466        }
467        free(pfea2list);
468        if (rc)
469        {
470                maperrno(rc);
471                return -1;
472        }
473        return 0;
474}
475
476#endif
Note: See TracBrowser for help on using the repository browser.