/* This file contains helper functions for OS/2 - don't try and compile on other platforms */ #ifdef __OS2__ #define INCL_LONGLONG #define INCL_DOS #define INCL_DOSPROCESS #define INCL_DOSPROFILE #define INCL_DOSMISC #define INCL_DOSMODULEMGR #define INCL_DOSERRORS //_SMB_H #include #include #include #include #include //YD for tmalloc #include /* these define the attribute byte as seen by DOS */ #define aRONLY (1L<<0) /* 0x01 */ #define aHIDDEN (1L<<1) /* 0x02 */ #define aSYSTEM (1L<<2) /* 0x04 */ #define aVOLID (1L<<3) /* 0x08 */ #define aDIR (1L<<4) /* 0x10 */ #define aARCH (1L<<5) /* 0x20 */ #ifndef TESTING #define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) #define CMD_KI_RDCNT (0x63) typedef struct _CPUUTIL { ULONG ulTimeLow; /* Low 32 bits of time stamp */ ULONG ulTimeHigh; /* High 32 bits of time stamp */ ULONG ulIdleLow; /* Low 32 bits of idle time */ ULONG ulIdleHigh; /* High 32 bits of idle time */ ULONG ulBusyLow; /* Low 32 bits of busy time */ ULONG ulBusyHigh; /* High 32 bits of busy time */ ULONG ulIntrLow; /* Low 32 bits of interrupt time */ ULONG ulIntrHigh; /* High 32 bits of interrupt time */ } CPUUTIL; #include "local.h" #include "xfile.h" #define DEBUG(a,b) (0) #else #define DEBUG(a,b) (0) #endif #include #ifndef ENOATTR #define ENOATTR 22 #endif int os2_ftruncate(int fd, off_t size) { // We call there __libc_Back_ioFileSizeSet directly instead of // ftruncate to force it not to zero expanding files to optimize // samba performance when copying files int rc = __libc_Back_ioFileSizeSet(fd, size, 0); if (rc < 0) { errno = -rc; return -1; } return 0; } int os2_isattribute(char *path, unsigned short attr) { HDIR hdirFindHandle = HDIR_CREATE; FILEFINDBUF3 FindBuffer = {0}; /* Returned from FindFirst/Next */ USHORT dosattr; /* attribute to search for */ ULONG ulResultBufLen = sizeof(FILEFINDBUF3); ULONG ulFindCount = 1; /* Look for 1 file at a time */ APIRET rc = NO_ERROR; /* Return code */ if (attr==aARCH) dosattr=MUST_HAVE_ARCHIVED; else if (attr==aRONLY) dosattr=MUST_HAVE_READONLY; else if (attr==aSYSTEM) dosattr=MUST_HAVE_SYSTEM; else if (attr==aHIDDEN) dosattr=MUST_HAVE_HIDDEN; rc = DosFindFirst( path, /* File pattern - all files */ &hdirFindHandle, /* Directory search handle */ dosattr, &FindBuffer, /* Result buffer */ ulResultBufLen, /* Result buffer length */ &ulFindCount, /* Number of entries to find */ FIL_STANDARD); /* Return Level 1 file info */ if (rc != NO_ERROR) { rc = DosFindClose(hdirFindHandle); /* Close our directory handle */ return 1; } else { rc = DosFindClose(hdirFindHandle); /* Close our directory handle */ return 0; } /* endif */ } // very simple random data gatherer derived from openssl void os2_randget(char * buffer, int length) { QWORD qwTime; ULONG SysVars[QSV_FOREGROUND_PROCESS]; int done = 0; if (!buffer || length <= 0) { return; } DosTmrQueryTime(&qwTime); memcpy(buffer, &qwTime, sizeof(qwTime) > length ? length : sizeof(qwTime)); done += sizeof(qwTime); if (done >= length) { return; } if (DosPerfSysCall) { CPUUTIL util; if (DosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) { memcpy(buffer + done, &util, sizeof(util) > length - done ? length - done : sizeof(util)); done += sizeof(util); if (done >= length) { return; } } } DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars)); memcpy(buffer + done, SysVars, sizeof(SysVars) > length - done ? length - done : sizeof(SysVars)); } void maperrno(int rc) { switch (rc) { case ERROR_PATH_NOT_FOUND : case ERROR_FILE_NOT_FOUND : errno = ENOENT; break; case ERROR_INVALID_HANDLE : errno = EBADF; break; case ERROR_ACCESS_DENIED : errno = EACCES; break; case ERROR_BUFFER_OVERFLOW : case ERROR_NOT_ENOUGH_MEMORY : errno = ERANGE; break; case ERROR_INVALID_EA_NAME : errno = ENOATTR; break; case ERROR_INVALID_LEVEL : case ERROR_INVALID_PARAMETER : errno = EINVAL; break; case ERROR_SHARING_VIOLATION : errno = EACCES; break; default : errno = EINVAL; } } ssize_t unigetxattr (const char *path, int file, const char *name, void *value, size_t size) { int rc, namelen; EAOP2 eaop2 = {0}; PGEA2LIST pgea2list = NULL; PFEA2LIST pfea2list = NULL; char * p; if ((!path && !file) || !name) { errno = EINVAL; return -1; } namelen = strlen(name); if (namelen > 0xFF) { errno = EINVAL; return -1; } pgea2list = (PGEA2LIST)calloc(sizeof(GEA2LIST) + namelen + 1, 1); pgea2list->list[0].oNextEntryOffset = 0; pgea2list->list[0].cbName = namelen; strcpy(pgea2list->list[0].szName, name); pgea2list->cbList = sizeof(GEA2LIST) + namelen; // max ea is 64kb pfea2list = (PFEA2LIST)calloc(sizeof(FEA2LIST) + 0x10000, 1); pfea2list->cbList = sizeof(FEA2LIST) + 0x10000; eaop2.fpGEA2List = pgea2list; eaop2.fpFEA2List = pfea2list; eaop2.oError = 0; do { if (path) { char npath[CCHMAXPATH + 1] = {0}; strncpy(npath, path, CCHMAXPATH); for (p = npath; *p; p++) { if (*p == '/') *p = '\\'; } rc = DosQueryPathInfo(npath, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2)); } else { rc = DosQueryFileInfo( file, FIL_QUERYEASFROMLIST, &eaop2, sizeof(eaop2)); } if (rc) { maperrno(rc); rc = -1; break; } if (strnicmp(pfea2list->list[0].szName, name, namelen) || pfea2list->list[0].cbValue == 0) { errno = ENOATTR; rc = -1; break; } rc = pfea2list->list[0].cbValue; if (value) { if (size < rc) { errno = ERANGE; rc = -1; } else { p = pfea2list->list[0].szName + pfea2list->list[0].cbName + 1; memcpy(value, p, rc); } } } while (0); if (pgea2list) { free(pgea2list); } if (pgea2list) { free(pfea2list); } DEBUG(4,("unigetxattr : (%s:%d) %s %d\n", path ? path : "null", file, name, rc)); return rc; } ssize_t unilistxattr (const char *path, int file, char *list, size_t size) { ssize_t gotsize = 0; unsigned long ulCount = -1; int rc; char * buf, *p = list; PFEA2 pfea; FILESTATUS4 stat = {0}; char npath[CCHMAXPATH + 1] = {0}; if (!path && !file) { errno = EINVAL; return -1; } if (path) { char * p; strncpy(npath, path, CCHMAXPATH); for (p = npath; *p; p++) { if (*p == '/') *p = '\\'; } rc = DosQueryPathInfo(npath, FIL_QUERYEASIZE, &stat, sizeof(stat)); } else { rc = DosQueryFileInfo( file, FIL_QUERYEASIZE, &stat, sizeof(stat)); } if (rc) { DEBUG(4,("unilistxattr1 : (%s:%d) %d\n", path ? path : "null", file, rc)); maperrno(rc); return -1; } if (stat.cbList <= 4) { // NO ea return 0; } //YD DosEnumAttribute doesn't like high-mem buffers, get a low one. buf = (char *)_tmalloc(stat.cbList * 2); rc = DosEnumAttribute(path ? 1 : 0, path ? (PVOID)path : (PVOID)&file, 1, (PVOID)buf, stat.cbList * 2, &ulCount, 1); if (rc) { DEBUG(4,("unilistxattr2 : (%s:%d) %d\n", path ? path : "null", file, rc)); maperrno(rc); _tfree(buf); return -1; } if (ulCount > 0) for (pfea = (PFEA2)buf;;pfea = (PFEA2)((char *)pfea + pfea->oNextEntryOffset)) { if (pfea->cbName > 0) { gotsize += pfea->cbName + 1; if (p && size >= gotsize) { pfea->szName[pfea->cbName] = 0; strcpy(p, pfea->szName); p += strlen(p) + 1; } } if (!pfea->oNextEntryOffset) { break; } } _tfree(buf); DEBUG(4,("unilistxattr : (%s:%d) %d\n", path ? path : "null", file, gotsize)); if (gotsize > size) { errno = ERANGE; return list ? -1 : gotsize; } return gotsize; } int uniremovexattr (const char *path, int file, const char *name) { int rc, namelen; EAOP2 eaop2 = {0}; PFEA2LIST pfea2list = NULL; char buf[300] = {0}; if ((!path && !file) || !name) { errno = EINVAL; return -1; } namelen = strlen(name); if (namelen > 0xFF) { errno = EINVAL; return -1; } pfea2list = (PFEA2LIST)buf; pfea2list->list[0].cbName = namelen; pfea2list->list[0].cbValue = 0; pfea2list->list[0].fEA = 0; strcpy(pfea2list->list[0].szName, name); pfea2list->cbList = sizeof(FEA2LIST) + namelen; eaop2.fpFEA2List = pfea2list; if (path) { char npath[CCHMAXPATH + 1] = {0}; char * p; strncpy(npath, path, CCHMAXPATH); for (p = npath; *p; p++) { if (*p == '/') *p = '\\'; } rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU); } else { rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2)); } if (rc) { maperrno(rc); return -1; } return 0; } #ifndef XATTR_CREATE #define XATTR_CREATE 1 #endif #ifndef XATTR_REPLACE #define XATTR_REPLACE 2 #endif int unisetxattr (const char *path, int file, const char *name, const void *value, size_t size, int flags) { int rc, namelen, totalsize; EAOP2 eaop2 = {0}; PFEA2LIST pfea2list = NULL; char * p; if ((!path && !file) || !name || (!value && size)) { errno = EINVAL; return -1; } namelen = strlen(name); if (namelen > 0xFF) { errno = EINVAL; return -1; } if (flags & (XATTR_CREATE | XATTR_REPLACE)) { ssize_t esize = unigetxattr(path, file, name, 0, 0); if (flags & XATTR_CREATE && esize > 0) { errno = EEXIST; return -1; } if (flags & XATTR_REPLACE && esize < 0) { errno = ENOATTR; return -1; } } totalsize = sizeof(FEA2LIST) + size + namelen + 1; pfea2list = (PFEA2LIST)calloc(totalsize, 1); pfea2list->cbList = totalsize; pfea2list->list[0].oNextEntryOffset = 0; pfea2list->list[0].cbName = namelen; pfea2list->list[0].cbValue = size; strcpy(pfea2list->list[0].szName, name); if (value) { memcpy(pfea2list->list[0].szName + namelen + 1, value, size); } eaop2.fpFEA2List = pfea2list; if (path) { char npath[CCHMAXPATH + 1] = {0}; char * p; strncpy(npath, path, CCHMAXPATH); for (p = npath; *p; p++) { if (*p == '/') *p = '\\'; } rc = DosSetPathInfo(npath, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2), DSPI_WRTTHRU); } else { rc = DosSetFileInfo( file, FIL_QUERYEASIZE, &eaop2, sizeof(eaop2)); } free(pfea2list); if (rc) { maperrno(rc); return -1; } return 0; } #endif