Changeset 2742
- Timestamp:
- Jul 26, 2006, 3:35:40 AM (19 years ago)
- Location:
- trunk/libc
- Files:
-
- 3 added
- 8 edited
- 5 copied
- 4 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/libc/include/InnoTekLIBC/backend.h
r2739 r2742 906 906 /** @defgroup grp_Back_process LIBC Backend - Process Management 907 907 * @{ */ 908 909 /** 910 * Sets the exit code for the current process and terminates it. 911 * This call never returns. 912 * 913 * @param rc The process exit code. 914 */ 915 void __libc_Back_processExit(int rc); 908 916 909 917 /** -
trunk/libc/include/InnoTekLIBC/logstrict.h
r2436 r2742 159 159 /** Macro to log an unsigned long int return and do the return. */ 160 160 #define LIBCLOG_RETURN_ULONG(rc) LIBCLOG_RETURN_MSG((rc), "ret %lu (%#lx)\n", (rc), (rc)) 161 /** Macro to log an off_t return and do the return. */ 162 #define LIBCLOG_RETURN_OFF(rc) LIBCLOG_RETURN_MSG((rc), "ret %lld (%#llx)\n", (rc), (rc)) 161 163 /** Macro to log a pointer return and do the return. */ 162 164 #define LIBCLOG_RETURN_P(rc) LIBCLOG_RETURN_MSG((rc), "ret %p\n", (void*)(rc)) -
trunk/libc/include/emx/syscalls.h
r2739 r2742 131 131 int __endthread (void *pvThrd); 132 132 int __execname (char *buf, size_t bufsize); 133 void __exit (int ret) __attribute__ ((__noreturn__)); 133 /*void __exit (int ret) __attribute__ ((__noreturn__));*/ 134 134 /*int __fcntl (int handle, int request, int arg);*/ 135 135 int __filesys (__const__ char *drive, char *name, size_t size); -
trunk/libc/include/klibc/io.h
r2739 r2742 85 85 */ 86 86 int (*pfnWrite)(struct __libc_FileHandle *pFH, const void *pvBuf, size_t cbWrite, size_t *pcbWritten); 87 /** Seek operation. 88 * @returns 0 on success. 89 * @returns Negated errno on failure. 90 * @param pFH Pointer to the handle structure to operate on. 91 * @param off The seek offset. 92 * @param iMethod The seek method (SEEK_SET, SEEK_CUR, SEEK_END). 93 * @param poffActual Where to store the new offset. 94 */ 95 int (*pfnSeek)(struct __libc_FileHandle *pFH, off_t off, int iMethod, off_t *poffActual); 96 /** 97 * Sets the size of an open file. 98 * 99 * @returns 0 on success. 100 * @returns Negative error code (errno.h) on failure. 101 * @param pFH The file handle structure. 102 * @param cbFile The new filesize. 103 * @param fZero If set any new allocated file space should be initialized to zero. 104 */ 105 int (*pfnSizeSet)(struct __libc_FileHandle *pFH, off_t cbFile, int fZero); 87 106 /** Duplicate handle operation. 88 107 * @returns 0 on success. -
trunk/libc/src/kNIX/Makefile.kmk
r2739 r2742 37 37 $(PATH_LIBC_SRC)/kNIX/b_ioRead.c \ 38 38 $(PATH_LIBC_SRC)/kNIX/b_ioWrite.c \ 39 $(PATH_LIBC_SRC)/kNIX/b_ioSeek.c \ 40 $(PATH_LIBC_SRC)/kNIX/b_ioFileSizeSet.c \ 39 41 $(PATH_LIBC_SRC)/kNIX/b_mmanBrk.c \ 40 42 $(PATH_LIBC_SRC)/kNIX/b_mmanSBrk.c \ 41 43 $(PATH_LIBC_SRC)/kNIX/b_mmanSBrkGetModel.c \ 42 44 $(PATH_LIBC_SRC)/kNIX/b_mmanSBrkSetModel.c \ 45 $(PATH_LIBC_SRC)/kNIX/b_signalSendPid.c \ 43 46 $(PATH_LIBC_SRC)/kNIX/filehandles.c \ 47 $(PATH_LIBC_SRC)/kNIX/fs.c \ 44 48 $(PATH_LIBC_SRC)/kNIX/heap.c \ 45 49 $(PATH_LIBC_SRC)/kNIX/heapdata.c \ … … 92 96 $(PATH_LIBC_SRC)/kNIX/os2/b_panic.c \ 93 97 $(PATH_LIBC_SRC)/kNIX/os2/b_processCredentials.c \ 98 $(PATH_LIBC_SRC)/kNIX/os2/b_processExit.c \ 94 99 $(PATH_LIBC_SRC)/kNIX/os2/b_processGetPriority.c \ 95 100 $(PATH_LIBC_SRC)/kNIX/os2/b_processSetPriority.c \ … … 166 171 $(PATH_LIBC_SRC)/kNIX/os2/__dup.c \ 167 172 $(PATH_LIBC_SRC)/kNIX/os2/__dup2.c \ 168 $(PATH_LIBC_SRC)/kNIX/os2/__exit.c \169 173 $(PATH_LIBC_SRC)/kNIX/os2/__fcntl.c \ 170 174 $(PATH_LIBC_SRC)/kNIX/os2/__ftime.c \ … … 196 200 197 201 libc_kNIX_SOURCES.nt = \ 202 $(PATH_LIBC_SRC)/kNIX/nt/b_fsUnlink.c \ 198 203 $(PATH_LIBC_SRC)/kNIX/nt/b_panic.c \ 204 $(PATH_LIBC_SRC)/kNIX/nt/b_processExit.c \ 205 $(PATH_LIBC_SRC)/kNIX/nt/b_signalAction.c \ 206 $(PATH_LIBC_SRC)/kNIX/nt/b_signalMask.c \ 207 $(PATH_LIBC_SRC)/kNIX/nt/b_signalSendPGrp.c \ 208 $(PATH_LIBC_SRC)/kNIX/nt/b_threadCleanup.c \ 209 $(PATH_LIBC_SRC)/kNIX/nt/b_threadInit.c \ 199 210 $(PATH_LIBC_SRC)/kNIX/nt/fhNtFile.c \ 200 211 $(PATH_LIBC_SRC)/kNIX/nt/NtStatus.c \ -
trunk/libc/src/kNIX/b_ioFileSizeSet.c
r2738 r2742 2 2 /** @file 3 3 * 4 * LIBC SYS Backend - chsize.4 * kNIX - _chsize() / ftruncate(). 5 5 * 6 * Copyright (c) 200 3-2004 knut st. osmundsen <bird@innotek.de>6 * Copyright (c) 2006 knut st. osmundsen <bird-srcspam@anduin.net> 7 7 * 8 8 * 9 * This file is part of InnoTekLIBC.9 * This file is part of kLIBC. 10 10 * 11 * InnoTekLIBC is free software; you can redistribute it and/or modify11 * kLIBC is free software; you can redistribute it and/or modify 12 12 * it under the terms of the GNU Lesser General Public License as published 13 13 * by the Free Software Foundation; either version 2 of the License, or 14 14 * (at your option) any later version. 15 15 * 16 * InnoTekLIBC is distributed in the hope that it will be useful,16 * kLIBC is distributed in the hope that it will be useful, 17 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the … … 20 20 * 21 21 * You should have received a copy of the GNU Lesser General Public License 22 * along with InnoTekLIBC; if not, write to the Free Software22 * along with kLIBC; if not, write to the Free Software 23 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 24 * … … 29 29 * Header Files * 30 30 *******************************************************************************/ 31 #include "libc-alias.h"32 #define INCL_FSMACROS33 #define INCL_ERRORS34 #include <os2emx.h>35 #include "b_fs.h"36 #include <limits.h>37 #include <errno.h>38 #include <InnoTekLIBC/backend.h>39 31 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_IO 40 #include <InnoTekLIBC/logstrict.h> 32 #include "kNIX.h" 33 #include <klibc/backend.h> 34 #include <klibc/logstrict.h> 41 35 42 /*******************************************************************************43 * Global Variables *44 *******************************************************************************/45 /** A page of zeros.46 * @todo Make this a separate segment for optimal thunking effiency! */47 static const char __libc_gachZeros[65536 - 4096];48 49 50 /*******************************************************************************51 * Internal Functions *52 *******************************************************************************/53 static inline int getFileSize(HFILE hFile, off_t *pcb);54 static inline int setFileSize(HFILE hFile, off_t cbFile);55 static inline int seekFile(HFILE hFile, off_t cbFile, int iMethod, off_t *poffFile);56 57 /**58 * Calls the correct OS/2 api for this operation.59 * FS is saved and loaded by caller.60 * @returns OS/2 error code or negative errno.61 */62 static inline int getFileSize(HFILE hFile, off_t *pcb)63 {64 union65 {66 FILESTATUS3 fsts3;67 FILESTATUS3L fsts3L;68 } info;69 int rc;70 #if OFF_MAX > LONG_MAX71 if (__libc_gpfnDosOpenL)72 {73 rc = DosQueryFileInfo(hFile, FIL_STANDARDL, &info, sizeof(info.fsts3L));74 *pcb = info.fsts3L.cbFile;75 }76 else77 #endif78 {79 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &info, sizeof(info.fsts3));80 *pcb = info.fsts3.cbFile;81 }82 return rc;83 }84 85 /**86 * Calls the correct OS/2 api for this operation.87 * FS is saved and loaded by caller.88 * @returns OS/2 error code or negative errno.89 */90 static inline int setFileSize(HFILE hFile, off_t cbFile)91 {92 int rc;93 #if OFF_MAX > LONG_MAX94 if (__libc_gpfnDosSetFileSizeL)95 rc = __libc_gpfnDosSetFileSizeL(hFile, cbFile);96 else97 {98 if (cbFile > __LONG_MAX)99 return -EOVERFLOW;100 rc = DosSetFileSize(hFile, cbFile);101 }102 #else103 rc = DosSetFileSize(hFile, cbFile);104 #endif105 return rc;106 }107 108 /**109 * Calls the correct OS/2 api for this operation.110 * FS is saved and loaded by caller.111 * @returns OS/2 error code or negative errno.112 */113 static inline int seekFile(HFILE hFile, off_t off, int iMethod, off_t *poffFile)114 {115 int rc;116 #if OFF_MAX > LONG_MAX117 if (__libc_gpfnDosSetFilePtrL)118 {119 LONGLONG cbNewTmp;120 rc = __libc_gpfnDosSetFilePtrL(hFile, off, iMethod, &cbNewTmp);121 off = cbNewTmp;122 }123 else124 {125 ULONG cbNewTmp;126 if (off > LONG_MAX || off < LONG_MIN)127 return -EOVERFLOW;128 rc = DosSetFilePtr(hFile, off, iMethod, &cbNewTmp);129 off = cbNewTmp;130 }131 #else132 {133 ULONG cbNewTmp;134 rc = DosSetFilePtr(hFile, off, iMethod, &cbNewTmp);135 off = cbNewTmp;136 }137 #endif138 if (poffFile)139 *poffFile = off;140 return rc;141 }142 36 143 37 … … 162 56 * Get filehandle. 163 57 */ 164 PLIBCFHpFH;165 int rc = __libc_FH Ex(fh, &pFH);58 __LIBC_PFH pFH; 59 int rc = __libc_FHGet(fh, &pFH); 166 60 if (rc) 167 61 LIBCLOG_ERROR_RETURN_INT(rc); 168 62 169 if (!pFH->pOps) 170 { 171 /* 172 * Standard OS/2 file handle. 173 * 174 * Get the current file size so we can perform 175 * any necessary zero padding. 176 */ 177 FS_VAR(); 178 FS_SAVE_LOAD(); 179 off_t cbCur; 180 rc = getFileSize(fh, &cbCur); 181 if (!rc) 182 { 183 if (cbCur != cbFile) 184 { 185 /* 186 * File size change needed. 187 */ 188 rc = setFileSize(fh, cbFile); 189 if (!rc) 190 { 191 /* 192 * We're done if it was a truncation. 193 */ 194 off_t cbLeft = cbFile - cbCur; 195 if ( cbLeft <= 0 196 || !fZero 197 || (pFH->pFsInfo && pFH->pFsInfo->fZeroNewBytes)) 198 { 199 FS_RESTORE(); 200 LIBCLOG_RETURN_INT(0); 201 } 202 203 /* 204 * Must fill the allocated file space with zeros. 205 */ 206 off_t offSaved; 207 rc = seekFile(fh, 0, FILE_CURRENT, &offSaved); 208 if (!rc) 209 rc = seekFile(fh, cbCur, FILE_BEGIN, NULL); 210 while (!rc && cbLeft > 0) 211 { 212 ULONG cb = cbLeft >= sizeof(__libc_gachZeros) ? sizeof(__libc_gachZeros) : cbLeft; 213 rc = DosWrite(fh, &__libc_gachZeros[0], cb, &cb); 214 cbLeft -= cb; 215 } 216 int rc2 = seekFile(fh, offSaved, FILE_BEGIN, NULL); 217 if (!rc && !rc2) 218 { 219 FS_RESTORE(); 220 LIBCLOG_RETURN_INT(0); 221 } 222 223 /* 224 * Shit, we failed writing zeros. 225 * Try undo the expand operation. 226 */ 227 setFileSize(fh, cbCur); 228 if (rc2) 229 { 230 seekFile(fh, offSaved, FILE_BEGIN, NULL); 231 if (!rc) 232 rc = rc2; 233 } 234 } 235 } 236 } 237 238 FS_RESTORE(); 239 if (rc > 0) 240 rc = -__libc_native2errno(rc); 241 LIBCLOG_ERROR_RETURN_INT(rc); 242 } 243 else 244 { 245 /* 246 * Non-standard file handle - fail. 247 */ 248 LIBCLOG_ERROR_RETURN_INT(-EOPNOTSUPP); 249 } 63 /* 64 * Perform the operation. 65 */ 66 rc = pFH->pOps->pfnSizeSet(pFH, cbFile, fZero); 67 __libc_FHPut(pFH); 68 if (!rc) 69 LIBCLOG_RETURN_INT(rc); 70 LIBCLOG_ERROR_RETURN_INT(rc); 250 71 } 251 72 -
trunk/libc/src/kNIX/b_ioSeek.c
r2738 r2742 2 2 /** @file 3 3 * 4 * LIBC SYS Backend - seek.4 * kNIX - seek(). 5 5 * 6 * Copyright (c) 200 3-2004 knut st. osmundsen <bird@innotek.de>6 * Copyright (c) 2006 knut st. osmundsen <bird-srcspam@anduin.net> 7 7 * 8 8 * 9 * This file is part of InnoTekLIBC.9 * This file is part of kLIBC. 10 10 * 11 * InnoTekLIBC is free software; you can redistribute it and/or modify11 * kLIBC is free software; you can redistribute it and/or modify 12 12 * it under the terms of the GNU Lesser General Public License as published 13 13 * by the Free Software Foundation; either version 2 of the License, or 14 14 * (at your option) any later version. 15 15 * 16 * InnoTekLIBC is distributed in the hope that it will be useful,16 * kLIBC is distributed in the hope that it will be useful, 17 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the … … 20 20 * 21 21 * You should have received a copy of the GNU Lesser General Public License 22 * along with InnoTekLIBC; if not, write to the Free Software22 * along with kLIBC; if not, write to the Free Software 23 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 24 * … … 29 29 * Header Files * 30 30 *******************************************************************************/ 31 #include "libc-alias.h" 32 #define INCL_FSMACROS 33 #include <os2emx.h> 34 #include "b_fs.h" 35 #include <limits.h> 31 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_IO 32 #include "kNIX.h" 36 33 #include <errno.h> 37 34 #include <stdio.h> 38 #include < InnoTekLIBC/backend.h>39 # define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_IO40 #include < InnoTekLIBC/logstrict.h>35 #include <unistd.h> 36 #include <klibc/backend.h> 37 #include <klibc/logstrict.h> 41 38 42 39 … … 46 43 * @returns new file offset on success. 47 44 * @returns Negative error code (errno) on failure. 48 * @param hFileFile handle to preform seek operation on.45 * @param fh File handle to preform seek operation on. 49 46 * @param off Offset to seek to. 50 * @param i OriginThe seek method. SEEK_CUR, SEEK_SET or SEEK_END.47 * @param iMethod The seek method. SEEK_CUR, SEEK_SET or SEEK_END. 51 48 */ 52 off_t __libc_Back_ioSeek(int hFile, off_t off, int iMethod)49 off_t __libc_Back_ioSeek(int fh, off_t off, int iMethod) 53 50 { 54 LIBCLOG_ENTER(" hFile=%d off=%lld iMethod=%d\n", hFile, off, iMethod);51 LIBCLOG_ENTER("fh=%d off=%lld iMethod=%d\n", fh, off, iMethod); 55 52 56 53 /* 57 * Get filehandle / validate input.54 * Validate the method and get the filehandle. 58 55 */ 59 56 if (iMethod != SEEK_SET && iMethod != SEEK_CUR && iMethod != SEEK_END) 60 LIBCLOG_ RETURN_INT(-EINVAL);61 PLIBCFH pFH;62 int rc = __libc_FH Ex(hFile, &pFH);57 LIBCLOG_ERROR_RETURN_INT(-EINVAL); 58 __LIBC_PFH pFH; 59 int rc = __libc_FHGet(fh, &pFH); 63 60 if (rc) 64 61 LIBCLOG_ERROR_RETURN_INT(rc); 65 62 66 off_t cbNew; 67 if (!pFH->pOps) 68 { 69 /* 70 * Standard OS/2 filehandle. 71 */ 72 FS_VAR(); 73 FS_SAVE_LOAD(); 74 #if OFF_MAX > LONG_MAX 75 if (__libc_gpfnDosSetFilePtrL) 76 { 77 LONGLONG cbNewTmp; 78 rc = __libc_gpfnDosSetFilePtrL(hFile, off, iMethod, &cbNewTmp); 79 cbNew = cbNewTmp; 80 } 81 else 82 { 83 ULONG cbNewTmp; 84 if (off > LONG_MAX || off < LONG_MIN) 85 { 86 FS_RESTORE(); 87 LIBCLOG_ERROR_RETURN_INT(-EOVERFLOW); 88 } 89 rc = DosSetFilePtr(hFile, off, iMethod, &cbNewTmp); 90 cbNew = cbNewTmp; 91 } 92 #else 93 { 94 ULONG cbNewTmp; 95 rc = DosSetFilePtr(hFile, off, iMethod, &cbNewTmp); 96 cbNew = cbNewTmp; 97 } 98 #endif 99 FS_RESTORE(); 100 101 if (rc) 102 { 103 rc = -__libc_native2errno(rc); 104 LIBCLOG_ERROR_RETURN_INT(rc); 105 } 106 } 107 else 108 { 109 /* 110 * Non-standard filehandle - fail for the present. 111 */ 112 LIBCLOG_ERROR_RETURN_INT(-EOPNOTSUPP); 113 } 114 115 LIBCLOG_RETURN_MSG(cbNew, "ret %lld (%#llx)\n", cbNew, cbNew); 63 /* 64 * Perform the operation. 65 */ 66 rc = pFH->pOps->pfnSeek(pFH, off, iMethod, &off); 67 __libc_FHPut(pFH); 68 if (!rc) 69 LIBCLOG_RETURN_OFF(off); 70 LIBCLOG_ERROR_RETURN_INT(rc); 116 71 } 117 72 118 -
trunk/libc/src/kNIX/b_signalSendPid.c
r2738 r2742 29 29 * Header Files * 30 30 *******************************************************************************/ 31 #include "libc-alias.h" 32 #define INCL_BASE 33 #define INCL_FSMACROS 34 #define INCL_DOSSIGNALS 35 #include <os2emx.h> 36 31 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_SIGNAL 32 #include "kNIX.h" 37 33 #include <signal.h> 38 34 #include <errno.h> 39 #include < InnoTekLIBC/backend.h>40 # define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_SIGNAL41 #i nclude <InnoTekLIBC/logstrict.h>35 #include <klibc/backend.h> 36 #include <klibc/logstrict.h> 37 #ifdef __OS2__ /* later on NT. */ 42 38 #include "b_signal.h" 43 # include "syscalls.h"39 #endif 44 40 45 41 … … 70 66 LIBCLOG_ERROR_RETURN(-EINVAL, "ret -EINVAL - Invalid pid %d\n", pid); 71 67 68 #ifdef __OS2__ 72 69 /* 73 70 * Differ between others and our self. … … 89 86 LIBCLOG_RETURN_INT(rc); 90 87 LIBCLOG_ERROR_RETURN_INT(rc); 88 #else 89 /* stub */ 90 LIBCLOG_ERROR_RETURN_INT(-ENOSYS); 91 #endif 91 92 } 92 93 -
trunk/libc/src/kNIX/fs.c
r2738 r2742 2 2 /** @file 3 3 * 4 * LIBC SYS Backend - file system stuff.5 * 6 * Copyright (c) 2004-200 5 knut st. osmundsen <bird@innotek.de>7 * 8 * 9 * This file is part of InnoTekLIBC.10 * 11 * InnoTekLIBC is free software; you can redistribute it and/or modify4 * kNIX - file system, common bits. 5 * 6 * Copyright (c) 2004-2006 knut st. osmundsen <bird-srcspam@anduin.net> 7 * 8 * 9 * This file is part of kLIBC. 10 * 11 * kLIBC is free software; you can redistribute it and/or modify 12 12 * it under the terms of the GNU Lesser General Public License as published 13 13 * by the Free Software Foundation; either version 2 of the License, or 14 14 * (at your option) any later version. 15 15 * 16 * InnoTekLIBC is distributed in the hope that it will be useful,16 * kLIBC is distributed in the hope that it will be useful, 17 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the … … 20 20 * 21 21 * You should have received a copy of the GNU Lesser General Public License 22 * along with InnoTekLIBC; if not, write to the Free Software22 * along with kLIBC; if not, write to the Free Software 23 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 24 * … … 29 29 * Header Files * 30 30 *******************************************************************************/ 31 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_FS 32 #include "kNIX.h" 31 33 #define _GNU_SOURCE 32 #include "libc-alias.h"33 #define INCL_FSMACROS34 #define INCL_BASE35 #define INCL_ERRORS36 #include <os2emx.h>37 #include "b_fs.h"38 34 #include <stddef.h> 39 35 #include <string.h> 40 36 #include <errno.h> 41 #include <386/builtin.h>42 37 #include <sys/stat.h> 43 38 #include <sys/fmutex.h> 44 39 #include <sys/smutex.h> 45 40 #include <emx/startup.h> 46 #include "syscalls.h" 47 #include <InnoTekLIBC/sharedpm.h> 48 #include <InnoTekLIBC/pathrewrite.h> 49 #include <InnoTekLIBC/libc.h> 50 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_FS 51 #include <InnoTekLIBC/logstrict.h> 52 53 54 /******************************************************************************* 55 * Defined Constants And Macros * 56 *******************************************************************************/ 57 #define ORD_DOS32OPENL 981 58 #define ORD_DOS32SETFILEPTRL 988 59 #define ORD_DOS32SETFILESIZEL 989 60 #define ORD_DOS32SETFILELOCKSL 986 61 62 #define SIZEOF_ACHBUFFER (sizeof(FILEFINDBUF4) + 32) 41 #ifdef __OS2__ 42 # include <InnoTekLIBC/sharedpm.h> //??? 43 # include <InnoTekLIBC/pathrewrite.h>//??! 44 #endif 45 #include <klibc/backend.h> 46 #include <klibc/logstrict.h> 63 47 64 48 … … 80 64 81 65 82 ULONG (* _System __libc_gpfnDosOpenL)(PCSZ pszFileName, PHFILE phFile, PULONG pulAction, LONGLONG llFileSize, ULONG ulAttribute, ULONG ulOpenFlags, ULONG ulOpenMode, PEAOP2 pEABuf) = NULL; 83 ULONG (* _System __libc_gpfnDosSetFilePtrL)(HFILE hFile, LONGLONG llOffset, ULONG ulOrigin, PLONGLONG pllPos) = NULL; 84 ULONG (* _System __libc_gpfnDosSetFileSizeL)(HFILE hFile, LONGLONG cbSize) = NULL; 85 ULONG (* _System __libc_gpfnDosSetFileLocksL)(HFILE hFile, __const__ FILELOCKL *pflUnlock, __const__ FILELOCKL *pflLock, ULONG ulTimeout, ULONG flFlags) = NULL; 86 87 /** Symlink EA name. */ 88 static const char __libc_gszSymlinkEA[] = EA_SYMLINK; 89 /** UID EA name. */ 90 static const char __libc_gszUidEA[] = EA_UID; 91 /** GID EA name. */ 92 static const char __libc_gszGidEA[] = EA_GID; 93 /** Mode EA name. */ 94 static const char __libc_gszModeEA[] = EA_MODE; 95 /** Ino EA name. */ 96 static const char __libc_gszInoEA[] = EA_INO; 97 /** RDev EA name. */ 98 static const char __libc_gszRDevEA[] = EA_RDEV; 99 /** Gen(eration) EA name. */ 100 static const char __libc_gszGenEA[] = EA_GEN; 101 /** User flags EA name. */ 102 static const char __libc_gszFlagsEA[] = EA_FLAGS; 103 104 /** 105 * The prefilled GEA2LIST construct for querying a symlink. 106 */ 107 #pragma pack(1) 108 static const struct 109 { 110 ULONG cbList; 111 ULONG oNextEntryOffset; 112 BYTE cbName; 113 CHAR szName[sizeof(EA_SYMLINK)]; 114 } gGEA2ListSymlink = 115 { 116 sizeof(gGEA2ListSymlink), 117 0, 118 sizeof(EA_SYMLINK) - 1, 119 EA_SYMLINK 120 }; 121 #pragma pack() 122 123 /** 124 * The prefilled GEA2LIST construct for querying all unix attributes. 125 */ 126 const struct __LIBC_BACK_FSUNIXATTRIBSGEA2LIST __libc_gFsUnixAttribsGEA2List = 127 { 128 #define OFF(a,b) offsetof(struct __LIBC_BACK_FSUNIXATTRIBSGEA2LIST, a) - offsetof(struct __LIBC_BACK_FSUNIXATTRIBSGEA2LIST, b) 129 sizeof(__libc_gFsUnixAttribsGEA2List), 130 OFF(offUID, offSymlink), sizeof(EA_SYMLINK) - 1, EA_SYMLINK, 131 OFF(offGID, offUID), sizeof(EA_UID) - 1, EA_UID, 132 OFF(offMode, offGID), sizeof(EA_GID) - 1, EA_GID, 133 OFF(offINO, offMode), sizeof(EA_MODE) - 1, EA_MODE, 134 OFF(offRDev, offINO), sizeof(EA_INO) - 1, EA_INO, 135 OFF(offGen, offRDev), sizeof(EA_RDEV) - 1, EA_RDEV, 136 OFF(offFlags, offGen), sizeof(EA_GEN) - 1, EA_GEN, 137 0, sizeof(EA_FLAGS) - 1, EA_FLAGS 138 #undef OFF 139 }; 140 #pragma pack() 141 142 /** 143 * The prefilled GEA2LIST construct for querying all the mode attribute. 144 */ 145 #pragma pack(1) 146 static const struct 147 { 148 ULONG cbList; 149 ULONG oNextEntryOffset; 150 BYTE cbName; 151 CHAR szName[sizeof(EA_MODE)]; 152 } gGEA2ListMode = 153 { 154 sizeof(gGEA2ListMode), 155 0, 156 sizeof(EA_MODE) - 1, 157 EA_MODE 158 }; 159 #pragma pack() 160 161 /** 162 * The prefilled FEA2LIST construct for setting all attributes during a creation operation. 163 */ 164 #pragma pack(1) 165 const struct __LIBC_FSUNIXATTRIBSCREATEFEA2LIST __libc_gFsUnixAttribsCreateFEA2List = 166 { 167 #define OFF(a,b) offsetof(struct __LIBC_FSUNIXATTRIBSCREATEFEA2LIST, a) - offsetof(struct __LIBC_FSUNIXATTRIBSCREATEFEA2LIST, b) 168 sizeof(__libc_gFsUnixAttribsCreateFEA2List), 169 OFF(offGID, offUID), FEA_NEEDEA, sizeof(EA_UID) - 1, sizeof(uint32_t) + 4, EA_UID, EAT_BINARY, sizeof(uint32_t), 0, "", 170 OFF(offMode, offGID), FEA_NEEDEA, sizeof(EA_GID) - 1, sizeof(uint32_t) + 4, EA_GID, EAT_BINARY, sizeof(uint32_t), 0, "", 171 OFF(offINO, offMode), FEA_NEEDEA, sizeof(EA_MODE) - 1, sizeof(uint32_t) + 4, EA_MODE, EAT_BINARY, sizeof(uint32_t), 0, "", 172 OFF(offRDev, offINO), FEA_NEEDEA, sizeof(EA_INO) - 1, sizeof(uint64_t) + 4, EA_INO, EAT_BINARY, sizeof(uint64_t), 0, "", 173 OFF(offGen, offRDev), FEA_NEEDEA, sizeof(EA_RDEV) - 1, sizeof(uint32_t) + 4, EA_RDEV, EAT_BINARY, sizeof(uint32_t), 0, "", 174 OFF(offFlags, offGen), FEA_NEEDEA, sizeof(EA_GEN) - 1, sizeof(uint32_t) + 4, EA_GEN, EAT_BINARY, sizeof(uint32_t), 0, "", 175 0, FEA_NEEDEA, sizeof(EA_FLAGS) - 1, sizeof(uint32_t) + 4, EA_FLAGS, EAT_BINARY, sizeof(uint32_t), 0, "" 176 #undef OFF 177 }; 178 #pragma pack() 179 180 /** 181 * The prefilled GEA2LIST construct for querying unix attributes for directory listing. 182 */ 183 const struct __LIBC_BACK_FSUNIXATTRIBSDIRGEA2LIST __libc_gFsUnixAttribsDirGEA2List = 184 { 185 #define OFF(a,b) offsetof(struct __LIBC_BACK_FSUNIXATTRIBSDIRGEA2LIST, a) - offsetof(struct __LIBC_BACK_FSUNIXATTRIBSDIRGEA2LIST, b) 186 sizeof(__libc_gFsUnixAttribsDirGEA2List), 187 OFF(offINO, offMode), sizeof(EA_MODE) - 1, EA_MODE, 188 0, sizeof(EA_INO) - 1, EA_INO, 189 #undef OFF 190 }; 191 #pragma pack() 192 66 #ifdef __OS2__ 193 67 /** 194 68 * The special /@unixroot rewrite rule. … … 198 72 __LIBC_PRWF_CASE_SENSITIVE | __LIBC_PRWF_TYPE_DIR, "/@unixroot", 10, __libc_gszUnixRoot, 0 199 73 }; 200 201 202 /** Array of pointers to fs info objects for all 203 * possible OS/2 volumes. 204 */ 205 static __LIBC_FSINFO g_aFSInfoVolumes['Z' - 'A' + 1]; 206 /** Mutex semaphore protecting the g_aFSInfoVolumes array. */ 207 static _fmutex g_mtxFSInfoVolumes = _FMUTEX_INITIALIZER_EX(_FMC_MUST_COMPLETE, "mtxFSInfoVolumes"); 74 #endif 208 75 209 76 … … 211 78 * Internal Functions * 212 79 *******************************************************************************/ 213 static int fsResolveUnix(const char *pszUserPath, unsigned fFlags, char *pszNativePath, int *pfInUnixTree);214 static int fsResolveOS2(const char *pszUserPath, unsigned fFlags, char *pszNativePath, int *pfInUnixTree);215 80 static uint32_t crc32str(const char *psz); 216 81 #if 0 … … 220 85 221 86 222 #ifndef STANDALONE_TEST223 87 /** 224 88 * Init the file system stuff. … … 246 110 LIBCLOG_RETURN_INT(-1); 247 111 112 #ifdef __OS2__ /** @todo move this! */ 248 113 /* 249 114 * Inherit File System Data from parent. … … 344 209 } 345 210 DosFreeModule(hmod); 346 211 #endif /* __OS2__ */ 347 212 LIBCLOG_RETURN_INT(0); 348 213 } 349 214 215 #ifdef __OS2__ /** @todo move this! */ 350 216 /** 351 217 * Pack inherit data. … … 407 273 LIBCLOG_RETURN_INT(rc); 408 274 } 275 #endif /*__OS2__ */ 409 276 410 277 … … 414 281 if (!rc) 415 282 return 0; 416 return - __libc_native2errno(rc);283 return -EDOOFUS; 417 284 } 418 285 … … 426 293 } 427 294 428 #endif /*!STANDALONE_TEST*/429 430 /**431 * Reads the content of a symbolic link.432 *433 * This is weird interface as it will return a truncated result if not434 * enough buffer space. It is also weird in that there is no string435 * terminator.436 *437 * @returns Number of bytes returned in pachBuf.438 * @returns -1 and errno on failure.439 * @param pszNativePath The path to the symlink to read.440 * @param pachBuf Where to store the symlink value.441 * @param cchBuf Size of buffer.442 */443 int __libc_back_fsNativeSymlinkRead(const char *pszNativePath, char *pachBuf, size_t cchBuf)444 {445 LIBCLOG_ENTER("pszNativePath=%p:{%s} pachBuf=%p cchBuf=%d\n", (void *)pszNativePath, pszNativePath, (void *)pachBuf, cchBuf);446 447 /*448 * Query the symlink EA value.449 */450 char _achBuffer[SIZEOF_ACHBUFFER + 4];451 char *pachBuffer = (char *)((uintptr_t)&_achBuffer[3] & ~3);452 EAOP2 EaOp;453 EaOp.fpGEA2List = (PGEA2LIST)&gGEA2ListSymlink;454 EaOp.fpFEA2List = (PFEA2LIST)pachBuffer;455 EaOp.oError = 0;456 EaOp.fpFEA2List->cbList = SIZEOF_ACHBUFFER;457 int rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_QUERYEASFROMLIST, &EaOp, sizeof(EaOp));458 if (!rc)459 {460 if ( EaOp.fpFEA2List->cbList > sizeof(EaOp.fpFEA2List->list[0])461 && EaOp.fpFEA2List->list[0].cbValue)462 {463 /*464 * Validate the EA.465 */466 PUSHORT pusType = (PUSHORT)((char *)&EaOp.fpFEA2List->list[1] + EaOp.fpFEA2List->list[0].cbName);467 int cchSymlink = pusType[1];468 char *pszSymlink = (char *)&pusType[2];469 if ( pusType[0] == EAT_ASCII470 && cchSymlink < EaOp.fpFEA2List->list[0].cbValue471 && cchSymlink > 0472 && *pszSymlink)473 {474 /*475 * Copy it to the buffer and return.476 */477 if (cchSymlink > cchBuf)478 {479 LIBCLOG_ERROR("Buffer to small. %d bytes required, %d bytes available. pszSymlink='%.*s' pszNativePath='%s'\n",480 cchSymlink, cchBuf, cchSymlink, pszSymlink, pszNativePath);481 cchSymlink = cchBuf;482 }483 memcpy(pachBuf, pszSymlink, cchSymlink);484 LIBCLOG_RETURN_INT(cchSymlink);485 }486 else487 LIBCLOG_ERROR_RETURN(-EFTYPE, "ret -EFTYPE - Invalid symlink EA! type=%x len=%d cbValue=%d *pszSymlink=%c pszNativePath='%s'\n",488 pusType[0], pusType[1], EaOp.fpFEA2List->list[0].cbValue, *pszSymlink, pszNativePath);489 }490 else491 LIBCLOG_ERROR_RETURN(-EINVAL, "ret -EINVAL - %s is not a symlink!\n", pszNativePath);492 }493 else494 LIBCLOG_ERROR("DosQueryPathInfo(%s) -> %d!\n", pszNativePath, rc);495 496 /* failure */497 rc = -__libc_native2errno(rc);498 LIBCLOG_ERROR_RETURN_INT(rc);499 }500 501 502 /**503 * Checks if the specified path is a symlink or not.504 * @returns true / false.505 * @param pszNativePath Path to the potential symlink.506 */507 static int fsIsSymlink(const char *pszNativePath)508 {509 char sz[16];510 return __libc_back_fsNativeSymlinkRead(pszNativePath, sz, sizeof(sz)) >= 0;511 }512 513 514 #if 0 //just testing, not useful.515 /**516 * Updates a symlink.517 *518 * @returns 0 on success.519 * @returns -1 and errno on failure.520 * @param pszTarget The symlink target.521 * @param pszSymlink The symlink, the one to be updated.522 */523 int __libc_back_fsSymlinkWrite(const char *pszTarget, const char *pszSymlink)524 {525 LIBCLOG_ENTER("pszTarget=%s pszSymlink=%s\n", pszTarget, pszSymlink);526 527 /*528 * Validate input.529 */530 int cchTarget = strlen(pszTarget);531 if (cchTarget >= PATH_MAX)532 LIBCLOG_ERROR_RETURN(-ENAMETOOLONG, "ret -ENAMETOOLONG - Target is too long, %d bytes. (%s)\n", cchTarget, pszTarget);533 534 /*535 * Allocate FEA buffer.536 */537 EAOP2 EaOp = {0,0,0};538 int cb = cchTarget + sizeof(USHORT) * 2 + sizeof(EA_SYMLINK) + sizeof(FEALIST);539 EaOp.fpFEA2List = alloca(cb);540 if (!EaOp.fpFEA2List)541 LIBCLOG_ERROR_RETURN(-ENOMEM, "ret -ENOMEM - Out of stack! alloca(%d) failed\n", cb);542 543 /*544 * Setup the EAOP structure.545 */546 EaOp.fpFEA2List->cbList = cb;547 PFEA2 pFEA = &EaOp.fpFEA2List->list[0];548 pFEA->oNextEntryOffset = 0;549 pFEA->cbName = sizeof(EA_SYMLINK) - 1;550 pFEA->cbValue = cchTarget + sizeof(USHORT) * 2;551 pFEA->fEA = FEA_NEEDEA;552 memcpy(pFEA->szName, EA_SYMLINK, sizeof(EA_SYMLINK));553 PUSHORT pus = (PUSHORT)&pFEA->szName[sizeof(EA_SYMLINK)];554 pus[0] = EAT_ASCII;555 pus[1] = cchTarget;556 memcpy(&pus[2], pszTarget, cchTarget);557 int rc = DosSetPathInfo((PCSZ)pszTarget, FIL_QUERYEASIZE, &EaOp, sizeof(EAOP2), 0);558 if (!rc)559 LIBCLOG_RETURN_INT(0);560 561 rc = -__libc_native2errno(rc);562 LIBCLOG_ERROR_RETURN_INT(rc);563 }564 #endif565 566 295 567 296 /** … … 573 302 void __libc_back_fsUpdateUnixRoot(const char *pszUnixRoot) 574 303 { 304 #ifdef __OS2__ 575 305 gaRewriteRule.pszTo = "/"; 576 306 gaRewriteRule.cchTo = 1; 307 #endif 577 308 578 309 int cch = strlen(pszUnixRoot); 579 310 memcpy(__libc_gszUnixRoot, pszUnixRoot, cch + 1); 580 311 __libc_gcchUnixRoot = cch; 581 }582 583 584 /**585 * Cleans up a path specifier a little bit.586 * This includes removing duplicate slashes, uncessary single dots, and587 * trailing slashes.588 *589 * @returns Number of bytes in the clean path.590 * @param pszPath The path to cleanup.591 * @param fFlags Flags controlling the operation of the function.592 * See the BACKFS_FLAGS_* defines.593 * @param pfFlags Where to clear the BACKFS_FLAGS_RESOLVE_DIR_MAYBE_ flag if a594 * trailing slash was found.595 */596 static int fsCleanPath(char *pszPath, unsigned fFlags, unsigned *pfFlags)597 {598 /*599 * Change to '/' and remove duplicates.600 */601 int fUnc = 0;602 char *pszSrc = pszPath;603 char *pszTrg = pszPath;604 if ( (pszPath[0] == '\\' || pszPath[0] == '/')605 && (pszPath[1] == '\\' || pszPath[1] == '/')606 && pszPath[2] != '\\' && pszPath[2] != '/')607 { /* Skip first slash in a unc path. */608 pszSrc++;609 *pszTrg++ = '/';610 fUnc = 1;611 }612 613 for (;;)614 {615 char ch = *pszSrc++;616 if (ch == '/' || ch == '\\')617 {618 *pszTrg++ = '/';619 for (;;)620 {621 do ch = *pszSrc++;622 while (ch == '/' || ch == '\\');623 624 /* Remove '/./' and '/.'. */625 if (ch != '.' || (*pszSrc && *pszSrc != '/' && *pszSrc != '\\'))626 break;627 }628 }629 *pszTrg = ch;630 if (!ch)631 break;632 pszTrg++;633 }634 635 /*636 * Remove trailing slash if the path may be pointing to a directory.637 * A symlink search is converted to a directory search if this is encountered.638 */639 int cch = pszTrg - pszPath;640 if ( (fFlags & (BACKFS_FLAGS_RESOLVE_DIR | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK))641 && cch > 1642 && pszTrg[-1] == '/'643 && pszTrg[-2] != ':'644 && pszTrg[-2] != '/')645 {646 pszPath[--cch] = '\0';647 if (pfFlags)648 {649 *pfFlags &= ~(BACKFS_FLAGS_RESOLVE_DIR_MAYBE_ | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK);650 if (fFlags & BACKFS_FLAGS_RESOLVE_FULL_SYMLINK)651 *pfFlags |= BACKFS_FLAGS_RESOLVE_DIR | BACKFS_FLAGS_RESOLVE_FULL;652 }653 }654 655 return cch;656 }657 658 659 /**660 * Resolves and verifies the user path to a native path.661 *662 * @returns 0 on success.663 * @returns Negative error code (errno.h) on failiure.664 * @param pszUserPath The user path.665 * @parm fFlags Flags controlling the operation of the function.666 * See the BACKFS_FLAGS_* defines.667 * @param pszNativePath Where to store the native path. This buffer is at668 * least PATH_MAX bytes big.669 * @param pfInUnixTree Where to store the result-in-unix-tree indicator. Optional.670 */671 int __libc_back_fsResolve(const char *pszUserPath, unsigned fFlags, char *pszNativePath, int *pfInUnixTree)672 {673 if (pszUserPath && *pszUserPath)674 {675 if (!__libc_gfNoUnix)676 return fsResolveUnix(pszUserPath, fFlags, pszNativePath, pfInUnixTree);677 else678 return fsResolveOS2(pszUserPath, fFlags, pszNativePath, pfInUnixTree);679 }680 681 /* failure */682 *pszNativePath = '\0';683 if (pfInUnixTree)684 *pfInUnixTree = 0;685 686 LIBC_ASSERT(pszUserPath);687 if (!pszUserPath)688 return -EINVAL;689 return -ENOENT;690 }691 692 693 /**694 * Resolves and verifies the user path to a native path.695 *696 * @returns 0 on success.697 * @returns Negative error code (errno.h) on failiure.698 * @param pszUserPath The user path.699 * @parm fFlags Flags controlling the operation of the function.700 * See the BACKFS_FLAGS_* defines.701 * @param pszNativePath Where to store the native path. This buffer is at702 * least PATH_MAX bytes big.703 * @param pfInUnixTree Where to store the result-in-unix-tree indicator. Optional.704 */705 static int fsResolveUnix(const char *pszUserPath, unsigned fFlags, char *pszNativePath, int *pfInUnixTree)706 {707 LIBCLOG_ENTER("pszUserPath=%p:{%s} pszNativePath=%p *pfInUnixTree=%p\n",708 (void *)pszUserPath, pszUserPath, (void *)pszNativePath, (void *)pfInUnixTree);709 const char *pszUserPathIn = pszUserPath;710 char _achBuffer[SIZEOF_ACHBUFFER + 4];711 char *pachBuffer = (char *)((uintptr_t)&_achBuffer[3] & ~3);712 unsigned cLoopsLeft = 8;713 int fInUnixTree = __libc_gfInUnixTree;714 int rcRet = 0;715 HDIR hDir = HDIR_CREATE;716 __LIBC_PFSINFO pFsInfo = NULL;717 int fUnixEAs;718 FS_VAR()719 FS_SAVE_LOAD();720 for (;;)721 {722 /*723 * Determin root slash position.724 */725 int iRoot;726 if (pszUserPath[0] == '/' || pszUserPath[0] == '\\')727 {728 iRoot = 0;729 fInUnixTree = __libc_gfInUnixTree;730 }731 else if ( pszUserPath[0] && pszUserPath[1] == ':'732 && (pszUserPath[2] == '/' || pszUserPath[2] == '\\'))733 {734 iRoot = 2;735 fInUnixTree = 0;736 }737 /*738 * No root slash? Make one!739 * This can only happen in the first pass (unless something BAD happens of course).740 */741 else742 {743 ULONG ul;744 int rc;745 if (pszUserPath[1] != ':')746 {747 /*748 * Current drive.749 */750 ULONG ulDisk;751 rc = DosQueryCurrentDisk(&ulDisk, &ul);752 pszNativePath[0] = ulDisk + 'A' - 1;753 ul = PATH_MAX - 2;754 if (!rc)755 rc = DosQueryCurrentDir(0, (PSZ)&pszNativePath[3], &ul);756 iRoot = __libc_gfInUnixTree ? __libc_gcchUnixRoot : 2;757 /* fInUnixTree remains whatever it is */758 }759 else760 {761 /*762 * Drive letter but no root slash.763 */764 pszNativePath[0] = pszUserPath[0];765 ul = PATH_MAX - 2;766 rc = DosQueryCurrentDir(pszUserPath[0] - (pszUserPath[0] >= 'A' && pszUserPath[0] <= 'Z' ? 'A' : 'a') + 1, (PSZ)&pszNativePath[3], &ul);767 pszUserPath += 2;768 iRoot = 2;769 fInUnixTree = 0;770 }771 /* failed? */772 if (rc)773 {774 rcRet = -__libc_native2errno(rc);775 break;776 }777 778 /*779 * Add the path stuff from the user.780 */781 pszNativePath[1] = ':';782 pszNativePath[2] = '/';783 int cch = strlen(pszNativePath);784 pszNativePath[cch++] = '/';785 int cchUserPath = strlen(pszUserPath) + 1;786 if (cch + cchUserPath > PATH_MAX)787 {788 rcRet = -ENAMETOOLONG;789 break;790 }791 memcpy(&pszNativePath[cch], pszUserPath, cchUserPath);792 pszUserPath = memcpy(pachBuffer, pszNativePath, cch + cchUserPath);793 }794 795 /*796 * Verify any drive specifier.797 */798 if (pszUserPath[1] == ':')799 {800 if (*pszUserPath >= 'a' && *pszUserPath <= 'z')801 {802 if ((uintptr_t)(pszUserPath - pachBuffer) > SIZEOF_ACHBUFFER)803 pszUserPath = strcpy(pachBuffer, pszUserPath);804 *(char *)(void *)pszUserPath += 'A' - 'a';805 }806 else if (!(*pszUserPath >= 'A' && *pszUserPath <= 'Z'))807 {808 rcRet = -ENOENT;809 break;810 }811 }812 813 /*814 * Apply rewrite rules.815 * Path now goes to pszNativePath buffer.816 */817 int cchNativePath = __libc_PathRewrite(pszUserPath, pszNativePath, PATH_MAX);818 if (cchNativePath > 0)819 {820 /*821 * Redetermin root because of rewrite.822 */823 iRoot = pszNativePath[1] == ':' ? 2 : 0;824 }825 else if (!cchNativePath)826 {827 cchNativePath = strlen(pszUserPath);828 if (cchNativePath + 2 > PATH_MAX)829 {830 rcRet = -ENAMETOOLONG;831 break;832 }833 memcpy(pszNativePath, pszUserPath, cchNativePath + 1);834 }835 else836 {837 rcRet = -EINVAL;838 break;839 }840 841 /*842 * Check if special OS/2 name.843 */844 if (pszNativePath[0] == '/' || pszNativePath[0] == '\\')845 {846 int fDone = 0;847 if ( (pszNativePath[1] == 'p' || pszNativePath[1] == 'P')848 && (pszNativePath[2] == 'i' || pszNativePath[2] == 'I')849 && (pszNativePath[3] == 'p' || pszNativePath[3] == 'P')850 && (pszNativePath[4] == 'e' || pszNativePath[4] == 'E')851 && (pszNativePath[5] == '/' || pszNativePath[5] == '\\'))852 fDone = 1;853 else if ((pszNativePath[1]== 'd' || pszNativePath[1] == 'D')854 && (pszNativePath[2] == 'e' || pszNativePath[2] == 'E')855 && (pszNativePath[3] == 'v' || pszNativePath[3] == 'V')856 && (pszNativePath[4] == '/' || pszNativePath[4] == '\\')857 )858 {859 PFSQBUFFER2 pfsqb = (PFSQBUFFER2)pachBuffer;860 ULONG cb = SIZEOF_ACHBUFFER;861 fDone = !DosQueryFSAttach((PCSZ)pszNativePath, 0, FSAIL_QUERYNAME, pfsqb, &cb);862 }863 864 /* If it was, copy path to pszNativePath and go to exit code. */865 if (fDone)866 {867 int cch = strlen(pszNativePath) + 1;868 if (cch <= PATH_MAX)869 {870 fsCleanPath(pszNativePath, fFlags, NULL);871 rcRet = 0;872 }873 else874 rcRet = -ENAMETOOLONG;875 break;876 }877 }878 879 /*880 * Remove excessive slashing and convert all slashes to '/'.881 */882 cchNativePath = fsCleanPath(pszNativePath, fFlags, &fFlags);883 884 /*885 * Expand unix root or add missing drive letter.886 */887 if (pszNativePath[0] == '/' && pszNativePath[1] != '/')888 {889 memcpy(pachBuffer, pszNativePath, cchNativePath + 1);890 if (__libc_gcchUnixRoot)891 {892 iRoot = __libc_gcchUnixRoot;893 if (cchNativePath + iRoot >= PATH_MAX)894 {895 rcRet = -ENAMETOOLONG;896 break;897 }898 memcpy(pszNativePath, __libc_gszUnixRoot, iRoot);899 fInUnixTree = 1;900 }901 else902 {903 iRoot = 2;904 ULONG ulDisk = 0;905 ULONG ul;906 DosQueryCurrentDisk(&ulDisk, &ul);907 if (cchNativePath + iRoot >= PATH_MAX)908 {909 rcRet = -ENAMETOOLONG;910 break;911 }912 pszNativePath[0] = ulDisk + 'A' - 1;913 pszNativePath[1] = ':';914 }915 if (cchNativePath != 1 || iRoot <= 2)916 memcpy(&pszNativePath[iRoot], pachBuffer, cchNativePath + 1);917 else918 pszNativePath[iRoot] = pszNativePath[iRoot + 1] = '\0'; /* The +1 fixes '/' access in an compartement (pszPrev below). */919 cchNativePath += iRoot;920 }921 922 923 /*924 * Check all directory components.925 *926 * We actually don't bother checking if they're directories, only that927 * they exists. This shouldn't matter much since any operation on the928 * next/final component will assume the previous one being a directory.929 *930 * While walking we will clean up all use of '.' and '..' so we'll end931 * up with an optimal path in the end.932 */933 /** @todo If we've retreived the current directory, we can safely save of the effort of validating it! */934 935 /*936 * Find the end of the first component (start and end + 1).937 */938 char *pszPrev;939 char *psz;940 if (pszNativePath[0] == '/' && pszNativePath[1] == '/' && pszNativePath[2] != '/')941 {942 /* UNC - skip past the share name. */943 psz = strchr(&pszNativePath[2], '/');944 if (!psz)945 {946 rcRet = -ENOENT;947 break;948 }949 psz = strchr(psz + 1, '/');950 if (!psz)951 {952 strupr(pszNativePath); /* The server + share is uppercased for consistant ino_t calculations. */953 rcRet = 0;954 break;955 }956 *psz = '\0'; /* The server + share is uppercased for consistant ino_t calculations. */957 strupr(pszNativePath);958 *psz = '/';959 pszPrev = ++psz;960 fInUnixTree = 0; /* Unix root cannot be UNC. */961 iRoot = psz - pszNativePath;962 psz = strchr(psz, '/');963 964 /* We don't do UNIX EAs on UNCs */965 fUnixEAs = 0;966 }967 else968 {969 /* drive letters are always uppercase! (inode dev number req) */970 LIBC_ASSERT(pszNativePath[1] == ':');971 if (pszNativePath[0] >= 'a' && pszNativePath[0] <= 'z')972 pszNativePath[0] -= 'a' - 'A';973 pszPrev = &pszNativePath[iRoot + 1];974 psz = strchr(pszPrev, '/');975 976 /* Unix EAs? */977 pFsInfo = __libc_back_fsInfoObjByPathCached(pszNativePath, pFsInfo);978 LIBC_ASSERTM(pFsInfo, "%s\n", pszNativePath);979 fUnixEAs = pFsInfo ? pFsInfo->fUnixEAs : 0;980 }981 LIBC_ASSERTM(pszPrev - pszNativePath >= iRoot, "iRoot=%d pszPrev offset %d pszNativePath=%s\n", iRoot, pszPrev - pszNativePath, pszNativePath);982 /* If only one component, we'll check if the fVerifyLast was requested. */983 if ( !psz984 && (fFlags & (BACKFS_FLAGS_RESOLVE_FULL | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK))985 && *pszPrev)986 psz = strchr(pszNativePath, '\0');987 988 /*989 * Walking loop.990 */991 int fDone = 1;992 while (psz)993 {994 char chSlash = *psz;995 *psz = '\0';996 997 /*998 * Kill . and .. specs.999 */1000 if ( pszPrev[0] == '.'1001 && ( pszPrev[1] == '\0'1002 || (pszPrev[1] == '.' && pszPrev[2] == '\0') ) )1003 {1004 if ( pszPrev[1] != '\0'1005 && (uintptr_t)(pszPrev - pszNativePath) != iRoot + 1)1006 {1007 for (pszPrev -= 2; *pszPrev != '/'; pszPrev--)1008 /* noop */;1009 pszPrev++;1010 }1011 *psz = chSlash;1012 memmove(pszPrev - 1, psz, cchNativePath - (psz - pszNativePath) + 1);1013 cchNativePath -= psz - (pszPrev - 1);1014 1015 /*1016 * Next path component and restart loop.1017 */1018 if (!chSlash)1019 {1020 rcRet = 0;1021 break;1022 }1023 psz = pszPrev;1024 while (*psz != '/')1025 {1026 if (*psz)1027 psz++;1028 else1029 {1030 if (!(fFlags & (BACKFS_FLAGS_RESOLVE_FULL | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK)))1031 {1032 rcRet = 0;1033 psz = NULL;1034 }1035 break;1036 }1037 }1038 continue;1039 }1040 1041 /*1042 * Check for obviously illegal characters in this path component1043 * saving us from having DosFindFirst getting '*' and '?'.1044 */1045 if (strpbrk(pszPrev, "*?"))1046 {1047 rcRet = -ENOENT; /* hmm. will this be correct for all situation? */1048 break;1049 }1050 1051 /*1052 * Find the correct name and to check if it is a directory or not.1053 * This'll of course also provide proper verification of the path too. :-)1054 *1055 * This is a little bit messed up since we'll have to use wildcard for1056 * getting the casing resolved.1057 *1058 * The two find buffers are assumed to be equal down thru attrFile.1059 */1060 //LIBC_ASSERT(psz - pszNativePath == cchNativePath); - figure this one.1061 PFILEFINDBUF4 pFindBuf4 = (PFILEFINDBUF4)pachBuffer;1062 PFILEFINDBUF3 pFindBuf3 = (PFILEFINDBUF3)pachBuffer;1063 ULONG cFiles = 1;1064 char chNext = psz[1];1065 psz[0] = '?';1066 psz[1] = '\0';1067 int rc = DosFindFirst((PCSZ)pszNativePath, &hDir, FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED,1068 pachBuffer, SIZEOF_ACHBUFFER, &cFiles, fUnixEAs ? FIL_QUERYEASIZE : FIL_STANDARD);1069 psz[0] = '\0';1070 psz[1] = chNext;1071 if (rc || cFiles == 0)1072 hDir = HDIR_CREATE;1073 while (!rc && cFiles == 1 && (fUnixEAs ? pFindBuf4->cchName : pFindBuf3->cchName) != psz - pszPrev)1074 rc = DosFindNext(hDir, pachBuffer, SIZEOF_ACHBUFFER, &cFiles);1075 if (rc || cFiles == 0)1076 {1077 LIBCLOG_MSG("DosFindFirst/Next('%s',,,,,) -> %d resolving '%s'\n", pszNativePath, rc, pszUserPathIn);1078 if ((fFlags & BACKFS_FLAGS_RESOLVE_FULL_MAYBE_) && !chSlash)1079 {1080 *psz = chSlash;1081 rcRet = 0;1082 }1083 else1084 rcRet = rc == ERROR_FILE_NOT_FOUND && chSlash ? -ENOENT : -__libc_native2errno(rc);1085 break;1086 }1087 memcpy(pszPrev, fUnixEAs ? pFindBuf4->achName : pFindBuf3->achName, psz - pszPrev);1088 int fIsDirectory = (pFindBuf4->attrFile & FILE_DIRECTORY) != 0;1089 1090 /*1091 * Try querying the symlink EA value.1092 * (This operation will reuse the achBuffer overwriting the pFindBuf[3/4] data!)1093 *1094 * Yeah, we could do this in the same operation as the DosFindFirst() but1095 * a little bird told me that level 3 DosFindFirst request had not been1096 * returning the right things at some point, and besides it's return data1097 * is rather clumsily laid out. So, I decided not to try my luck on it.1098 *1099 * On second thought, we seems to end up having to use DosFindFirst in some1100 * cases anyway... very nice.1101 */1102 if ( fUnixEAs1103 && pFindBuf4->cbList > sizeof(USHORT) * 2 + 11104 && ( (fFlags & BACKFS_FLAGS_RESOLVE_FULL)1105 || chSlash)1106 && !fIsDirectory)1107 {1108 PEAOP2 pEaOp2 = (PEAOP2)pachBuffer;1109 pEaOp2->fpGEA2List = (PGEA2LIST)&gGEA2ListSymlink;1110 pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);1111 pEaOp2->oError = 0;1112 pEaOp2->fpFEA2List->cbList = SIZEOF_ACHBUFFER - sizeof(*pEaOp2);1113 rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_QUERYEASFROMLIST, pEaOp2, sizeof(*pEaOp2));1114 if (rc)1115 {1116 cFiles = 1;1117 pEaOp2->fpGEA2List = (PGEA2LIST)&gGEA2ListSymlink;1118 pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);1119 pEaOp2->oError = 0;1120 pEaOp2->fpFEA2List->cbList = SIZEOF_ACHBUFFER - sizeof(*pEaOp2);1121 rc = DosFindFirst((PCSZ)pszNativePath, &hDir, 0, pEaOp2, pEaOp2->fpFEA2List->cbList + sizeof(*pEaOp2), &cFiles, FIL_QUERYEASFROMLIST);1122 if (rc || cFiles == 0)1123 {1124 hDir = HDIR_CREATE;1125 LIBCLOG_MSG("DosFindFirst('%s',,,pEaOp2,) -> %d resolving '%s'\n", pszNativePath, rc, pszUserPathIn);1126 if ((fFlags & BACKFS_FLAGS_RESOLVE_FULL_MAYBE_) && !chSlash)1127 rcRet = 0;1128 else1129 rcRet = rc == ERROR_FILE_NOT_FOUND && chSlash ? -ENOENT : -__libc_native2errno(rc);1130 break;1131 }1132 pEaOp2->fpFEA2List = (PFEA2LIST)((char *)pEaOp2 + sizeof(EAOP2) + offsetof(FILEFINDBUF3, cchName));1133 }1134 1135 /*1136 * Did we find any symlink EA?1137 */1138 if ( pEaOp2->fpFEA2List->cbList > sizeof(pEaOp2->fpFEA2List->list[0])1139 && pEaOp2->fpFEA2List->list[0].cbValue)1140 {1141 /* Validate the EA. */1142 PUSHORT pusType = (PUSHORT)((char *)&pEaOp2->fpFEA2List->list[1] + pEaOp2->fpFEA2List->list[0].cbName);1143 char *pszSymlink = (char *)&pusType[2];1144 if ( pusType[0] != EAT_ASCII1145 || pusType[1] > pEaOp2->fpFEA2List->list[0].cbValue1146 || !pusType[1]1147 || !*pszSymlink)1148 {1149 LIBCLOG_ERROR("Invalid symlink EA! type=%x len=%d cbValue=%d *pszSymlink=%c\n",1150 pusType[0], pusType[1], pEaOp2->fpFEA2List->list[0].cbValue, *pszSymlink);1151 rcRet = -EFTYPE;1152 break;1153 }1154 1155 /* Check if we've reached the max number of symlink loops before we continue. */1156 if (cLoopsLeft-- <= 0)1157 {1158 rcRet = -ELOOP;1159 break;1160 }1161 1162 /* Cleanup the symlink and find it's length. */1163 pszSymlink[pusType[1]] = '\0';1164 int cchSymlink = fsCleanPath(pszSymlink, fFlags, NULL);1165 1166 /* Merge the symlink with the path. */1167 int cchLeft = cchNativePath - (psz - pszNativePath);1168 if (*pszSymlink == '/' || *pszSymlink == '\\' || pszSymlink[1] == ':')1169 {1170 /*1171 * Replace the path up to the current point with the symlink,1172 */1173 if (cchSymlink + cchLeft + 2 >= PATH_MAX)1174 {1175 rcRet = -ENAMETOOLONG;1176 break;1177 }1178 if (cchLeft)1179 {1180 if (pszSymlink[cchSymlink - 1] != '/')1181 pszSymlink[cchSymlink++] = '/';1182 memcpy(&pszSymlink[cchSymlink], psz + 1, cchLeft + 1);1183 }1184 1185 /* restart the whole shebang. */1186 pszUserPath = pszSymlink;1187 fDone = 0;1188 break;1189 }1190 else1191 {1192 /*1193 * Squeeze the symlink in instead of the current path component.1194 */1195 if (cchSymlink + cchNativePath + 2 >= PATH_MAX)1196 {1197 rcRet = -ENAMETOOLONG;1198 break;1199 }1200 if (cchLeft)1201 {1202 pszSymlink[cchSymlink++] = '/';1203 memcpy(&pszSymlink[cchSymlink], psz + 1, cchLeft + 1);1204 cchSymlink += cchLeft;1205 }1206 memcpy(pszPrev, pszSymlink, cchSymlink + 1);1207 cchNativePath += cchSymlink - (psz - pszPrev);1208 1209 /* restart this component. */1210 psz = pszPrev;1211 while (*psz != '/')1212 {1213 if (*psz)1214 psz++;1215 else1216 {1217 if (!(fFlags & (BACKFS_FLAGS_RESOLVE_FULL | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK)))1218 {1219 rcRet = 0;1220 psz = NULL;1221 }1222 break;1223 }1224 }1225 continue;1226 }1227 }1228 }1229 1230 /*1231 * If we get here it was not a symlink and we should check how the directoryness1232 * of it fit's into the big picture...1233 */1234 if (!fIsDirectory && chSlash)1235 {1236 LIBCLOG_ERROR("'%s' is not a directory (resolving '%s')\n", pszNativePath, pszUserPathIn);1237 rcRet = -ENOTDIR;1238 break;1239 }1240 1241 /*1242 * Next path component.1243 */1244 *psz++ = chSlash;1245 if (!chSlash)1246 {1247 rcRet = 0;1248 if ( (fFlags & (BACKFS_FLAGS_RESOLVE_DIR | BACKFS_FLAGS_RESOLVE_DIR_MAYBE_)) == BACKFS_FLAGS_RESOLVE_DIR1249 && !fIsDirectory1250 && ( !fUnixEAs1251 || pFindBuf4->cbList <= sizeof(USHORT) * 2 + 11252 || !fsIsSymlink(pszNativePath)))1253 rcRet = -ENOTDIR;1254 break;1255 }1256 pszPrev = psz;1257 while (*psz != '/')1258 {1259 if (!*psz)1260 {1261 if (!(fFlags & (BACKFS_FLAGS_RESOLVE_FULL | BACKFS_FLAGS_RESOLVE_FULL_SYMLINK)))1262 {1263 rcRet = 0;1264 psz = NULL;1265 }1266 break;1267 }1268 psz++;1269 }1270 } /* inner loop */1271 1272 if (fDone)1273 break;1274 } /* outer loop */1275 1276 /*1277 * Cleanup find handle and fs object.1278 */1279 if (hDir != HDIR_CREATE)1280 DosFindClose(hDir);1281 if (pFsInfo)1282 __libc_back_fsInfoObjRelease(pFsInfo);1283 FS_RESTORE();1284 1285 /*1286 * Copy the resolved path the the caller buffer.1287 */1288 if (pfInUnixTree)1289 *pfInUnixTree = fInUnixTree;1290 if (!rcRet)1291 {1292 int cch = strlen(pszNativePath) + 1;1293 if (cch == 1 || (cch == 3 && pszNativePath[1] == ':'))1294 {1295 pszNativePath[cch - 1] = '/';1296 pszNativePath[cch] = '\0';1297 }1298 LIBCLOG_RETURN_MSG(0, "ret 0 pszNativePath=%p:{%s}\n", (void *)pszNativePath, pszNativePath);1299 }1300 1301 /* failure */1302 LIBCLOG_ERROR_RETURN_MSG(rcRet, "ret %d pszNativePath=%p:{%s}\n", rcRet, (void *)pszNativePath, pszNativePath);1303 pszUserPathIn = pszUserPathIn;1304 }1305 1306 1307 /**1308 * Resolves and verifies the user path to a native path.1309 *1310 * @returns 0 on success.1311 * @returns Negative error code (errno.h) on failiure.1312 * @param pszUserPath The user path.1313 * @parm fFlags Flags controlling the operation of the function.1314 * See the BACKFS_FLAGS_* defines.1315 * @param pszNativePath Where to store the native path. This buffer is at1316 * least PATH_MAX bytes big.1317 * @param pfInUnixTree Where to store the result-in-unix-tree indicator. Optional.1318 */1319 static int fsResolveOS2(const char *pszUserPath, unsigned fFlags, char *pszNativePath, int *pfInUnixTree)1320 {1321 LIBCLOG_ENTER("pszUserPath=%p:{%s} fFlags=%x pszNativePath=%p pfInUnixTree=%p\n",1322 (void *)pszUserPath, pszUserPath, fFlags, (void *)pszNativePath, (void *)pfInUnixTree);1323 1324 /*1325 * Apply rewrite rule.1326 */1327 int cch = __libc_PathRewrite(pszUserPath, pszNativePath, PATH_MAX);1328 if (cch < 0)1329 LIBCLOG_ERROR_RETURN_INT(-EINVAL);1330 if (cch == 0)1331 {1332 cch = strlen(pszUserPath);1333 if (cch >= PATH_MAX)1334 LIBCLOG_ERROR_RETURN_INT(-ENAMETOOLONG);1335 memcpy(pszNativePath, pszUserPath, cch + 1);1336 }1337 1338 /*1339 * Convert slashes.1340 */1341 char *psz = strchr(pszNativePath, '/');1342 while (psz)1343 {1344 *psz++ = '\\';1345 psz = strchr(psz, '/');1346 }1347 1348 /** @todo Validate the path? hopefully not necessary. */1349 1350 if (pfInUnixTree)1351 *pfInUnixTree = 0;1352 1353 LIBCLOG_RETURN_INT(0);1354 }1355 1356 1357 /**1358 * Initializes a unix attribute structure before creating a new inode.1359 * The call must have assigned default values to the the structure before doing this call!1360 *1361 * @returns Device number.1362 * @param pFEas The attribute structure to fill with actual values.1363 * @param pszNativePath The native path, used to calculate the inode number.1364 * @param Mode The correct mode (the caller have fixed this!).1365 */1366 dev_t __libc_back_fsUnixAttribsInit(struct __LIBC_FSUNIXATTRIBSCREATEFEA2LIST *pFEas, char *pszNativePath, mode_t Mode)1367 {1368 /*1369 * Calc Inode number.1370 * We replace the lower 32-bit with a random value.1371 */1372 /* low 32-bit - random */1373 static union1374 {1375 uint64_t u64TSC;1376 unsigned short ausSeed[4];1377 } s_Seed = {0};1378 static _smutex s_smtxSeed = 0;1379 _smutex_request(&s_smtxSeed);1380 /* seed it ? */1381 if (!s_Seed.ausSeed[3])1382 {1383 __asm__ __volatile__ ("rdtsc" : "=A" (s_Seed.u64TSC));1384 s_Seed.ausSeed[3] = 1;1385 }1386 pFEas->u64INO = nrand48(&s_Seed.ausSeed[0]) & 0xffffffff;1387 _smutex_release(&s_smtxSeed);1388 1389 /* high 32-bit - crc32 */1390 const char *psz = pszNativePath;1391 if (psz[1] == ':')1392 psz += 2;1393 pFEas->u64INO |= (uint64_t)crc32str(psz) << 32;1394 1395 /*1396 * The other stuff.1397 */1398 pFEas->u32UID = __libc_spmGetId(__LIBC_SPMID_EUID);1399 pFEas->u32GID = __libc_spmGetId(__LIBC_SPMID_EGID); /** @todo sticky bit! */1400 pFEas->u32Mode = Mode;1401 LIBC_ASSERT(pFEas->u32RDev == 0);1402 LIBC_ASSERT(pFEas->u32Gen == 0);1403 LIBC_ASSERT(pFEas->u32Flags == 0);1404 1405 /*1406 * Calc device.1407 */1408 char chDrv = *pszNativePath;1409 if (chDrv == '/' || chDrv == '\\')1410 return makedev('U', 0); /* U as in UNC */1411 LIBC_ASSERT(chDrv >= 'A' && chDrv <= 'Z');1412 return makedev('V', chDrv); /* V as in Volume */1413 }1414 1415 1416 /**1417 * Reads the unix EAs for a file which is being stat'ed.1418 *1419 * @returns 0 on success.1420 * @returns Negative errno on failure.1421 * @param hFile File handle to the fs object. If no handle handy, set to -1.1422 * @param pszNativePath Native path to the fs object. If handle is give this will be ignored.1423 * @param pStat Pointer to the stat buffer.1424 * The buffer is only updated if and with the EAs we find,1425 * so the caller must fill the fields with defaults before1426 * calling this function.1427 */1428 int __libc_back_fsUnixAttribsGet(int hFile, const char *pszNativePath, struct stat *pStat)1429 {1430 LIBCLOG_ENTER("hFile=%d pszNativePath=%p:{%s} pStat=%p\n", hFile, (void *)pszNativePath, pszNativePath, (void *)pStat);1431 1432 /* Try come up with an accurate max estimate of a maximum result. */1433 char achBuffer[sizeof(EAOP2) + sizeof(FILEFINDBUF3) + sizeof(__libc_gFsUnixAttribsGEA2List) + 7 * (sizeof(USHORT) * 2 + sizeof(BYTE)) + CCHMAXPATH + 6 * sizeof(uint32_t) + 0x30];1434 char *pachBuffer = (char *)((uintptr_t)&achBuffer[3] & ~3);1435 PEAOP2 pEaOp2 = (PEAOP2)pachBuffer;1436 int rc = -1000;1437 1438 /*1439 * Issue the query.1440 */1441 if (hFile >= 0)1442 {1443 pEaOp2->fpGEA2List = (PGEA2LIST)&__libc_gFsUnixAttribsGEA2List;1444 pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);1445 pEaOp2->oError = 0;1446 pEaOp2->fpFEA2List->cbList = sizeof(achBuffer) - 4 - sizeof(EAOP2);1447 rc = DosQueryFileInfo(hFile, FIL_QUERYEASFROMLIST, pEaOp2, sizeof(EAOP2));1448 }1449 if (rc && pszNativePath)1450 {1451 pEaOp2->fpGEA2List = (PGEA2LIST)&__libc_gFsUnixAttribsGEA2List;1452 pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);1453 pEaOp2->oError = 0;1454 pEaOp2->fpFEA2List->cbList = sizeof(achBuffer) - 4 - sizeof(EAOP2);1455 rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_QUERYEASFROMLIST, pEaOp2, sizeof(EAOP2));1456 if (rc == ERROR_SHARING_VIOLATION || rc == ERROR_ACCESS_DENIED || rc == ERROR_INVALID_ACCESS)1457 {1458 HDIR hDir = HDIR_CREATE;1459 ULONG cFiles = 1;1460 pEaOp2->fpGEA2List = (PGEA2LIST)&__libc_gFsUnixAttribsGEA2List;1461 pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);1462 pEaOp2->oError = 0;1463 pEaOp2->fpFEA2List->cbList = sizeof(achBuffer) - 4 - sizeof(EAOP2);1464 rc = DosFindFirst((PCSZ)pszNativePath, &hDir, 0, pEaOp2, pEaOp2->fpFEA2List->cbList + sizeof(*pEaOp2), &cFiles, FIL_QUERYEASFROMLIST);1465 if (!rc)1466 {1467 DosFindClose(hDir);1468 pEaOp2->fpFEA2List = (PFEA2LIST)((char *)pEaOp2 + sizeof(EAOP2) + offsetof(FILEFINDBUF3, cchName));1469 }1470 }1471 }1472 if (rc)1473 {1474 LIBC_ASSERTM(rc == ERROR_ACCESS_DENIED || rc == ERROR_SHARING_VIOLATION || rc == ERROR_EAS_NOT_SUPPORTED,1475 "Bogus EAs? rc=%d oError=%ld\n", rc, pEaOp2->oError);1476 rc = -__libc_native2errno(rc);1477 LIBCLOG_ERROR_RETURN_INT(rc);1478 }1479 if (pEaOp2->fpFEA2List->cbList < LIBC_UNIX_EA_MIN)1480 LIBCLOG_RETURN_INT(0);1481 1482 /*1483 * Parse the result.1484 */1485 PFEA2 pFea2 = &pEaOp2->fpFEA2List->list[0];1486 for (;;)1487 {1488 if (pFea2->cbValue > 0)1489 {1490 #define COMPARE_EANAME(name) (pFea2->cbName == sizeof(name) - 1 && !memcmp(name, pFea2->szName, sizeof(name) - 1))1491 if (COMPARE_EANAME(__libc_gszSymlinkEA))1492 pStat->st_mode = (pStat->st_mode & ~S_IFMT) | S_IFLNK;1493 else1494 {1495 PUSHORT pusType = (PUSHORT)&pFea2->szName[pFea2->cbName + 1];1496 if (*pusType == EAT_BINARY)1497 {1498 pusType++;1499 if (*pusType == sizeof(uint32_t))1500 {1501 uint32_t u32 = *(uint32_t *)++pusType;1502 if (COMPARE_EANAME(__libc_gszUidEA))1503 pStat->st_uid = u32;1504 else if (COMPARE_EANAME(__libc_gszGidEA))1505 pStat->st_gid = u32;1506 else if (COMPARE_EANAME(__libc_gszModeEA))1507 {1508 if ( S_ISDIR(u32) || S_ISCHR(u32) || S_ISBLK(u32) || S_ISREG(u32)1509 || S_ISFIFO(u32) || S_ISLNK(u32) || S_ISSOCK(u32) || S_ISWHT(u32))1510 pStat->st_mode = u32;1511 else1512 LIBC_ASSERTM_FAILED("Invalid file mode EA: u32=0%o (st_mode=0%o)\n", u32, pStat->st_mode);1513 }1514 else if (COMPARE_EANAME(__libc_gszRDevEA))1515 pStat->st_rdev = u32;1516 else if (COMPARE_EANAME(__libc_gszGenEA))1517 pStat->st_gen = u32;1518 else if (COMPARE_EANAME(__libc_gszFlagsEA))1519 pStat->st_flags = u32;1520 else1521 LIBC_ASSERTM_FAILED("Huh?!? got an ea named '%s', namelen=%d! u32=%#x (%d)\n", pFea2->szName, pFea2->cbName, u32, u32);1522 }1523 else if (*pusType == sizeof(uint64_t))1524 {1525 uint64_t u64 = *(uint64_t *)++pusType;1526 if (COMPARE_EANAME(__libc_gszInoEA))1527 pStat->st_ino = u64;1528 else1529 LIBC_ASSERTM_FAILED("Huh?!? got an ea named '%s', namelen=%d! u64=%#llx (%lld)\n", pFea2->szName, pFea2->cbName, u64, u64);1530 }1531 else1532 LIBC_ASSERTM_FAILED("Invalid LIBC EA! '%s' len=%#x and len=4 or 8.\n", pFea2->szName, *pusType);1533 }1534 else1535 LIBC_ASSERTM_FAILED("Invalid LIBC EA! '%s' type=%#x len=%#x, expected type=%#x and len=4 or 8.\n",1536 pFea2->szName, pusType[0], pusType[1], EAT_BINARY);1537 }1538 #undef COMPARE_EANAME1539 }1540 1541 /* next */1542 if (pFea2->oNextEntryOffset <= sizeof(FEA2))1543 break;1544 pFea2 = (PFEA2)((uintptr_t)pFea2 + pFea2->oNextEntryOffset);1545 }1546 1547 /*1548 * Calc st_ino and st_dev if not found.1549 */1550 if ((!pStat->st_ino || !pStat->st_dev) && pszNativePath)1551 {1552 ino_t Inode;1553 dev_t Dev = __libc_back_fsPathCalcInodeAndDev(pszNativePath, &Inode);1554 if (!pStat->st_ino)1555 pStat->st_ino = Inode;1556 if (!pStat->st_dev)1557 pStat->st_dev = Dev;1558 }1559 1560 LIBCLOG_RETURN_INT(0);1561 }1562 1563 1564 /**1565 * Reads the unix file mode EA.1566 *1567 * @returns 0 on success.1568 * @returns -ENOTSUP if the file mode EA is not present or if Unix EAs isn't supported on the volume.1569 * @returns Negative errno on failure.1570 * @param hFile File handle to the fs object. If no handle handy, set to -1.1571 * @param pszNativePath Native path to the fs object. If handle is give this will be ignored.1572 * @param pMode Where to store the mode mask.1573 */1574 int __libc_back_fsUnixAttribsGetMode(int hFile, const char *pszNativePath, mode_t *pMode)1575 {1576 LIBCLOG_ENTER("hFile=%d pszNativePath=%p:{%s} pMode=%p\n", hFile, (void *)pszNativePath, pszNativePath, (void *)pMode);1577 1578 /* Try come up with an accurate max estimate of a maximum result. */1579 char achBuffer[sizeof(EAOP2) + sizeof(FILEFINDBUF3) + sizeof(gGEA2ListMode) + 1 * (sizeof(USHORT) * 2 + sizeof(BYTE)) + 1 * sizeof(uint32_t) + 0x30];1580 char *pachBuffer = (char *)((uintptr_t)&achBuffer[3] & ~3);1581 PEAOP2 pEaOp2 = (PEAOP2)pachBuffer;1582 int rc = -1000;1583 1584 *pMode = 0;1585 1586 /** @todo the following query is generic! It's repeated 3 times already in this file (only the gea list and buffer size varies). */1587 /*1588 * Issue the query.1589 */1590 if (hFile >= 0)1591 {1592 pEaOp2->fpGEA2List = (PGEA2LIST)&gGEA2ListMode;1593 pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);1594 pEaOp2->oError = 0;1595 pEaOp2->fpFEA2List->cbList = sizeof(achBuffer) - 4 - sizeof(EAOP2);1596 rc = DosQueryFileInfo(hFile, FIL_QUERYEASFROMLIST, pEaOp2, sizeof(EAOP2));1597 }1598 if (rc && pszNativePath)1599 {1600 pEaOp2->fpGEA2List = (PGEA2LIST)&gGEA2ListMode;1601 pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);1602 pEaOp2->oError = 0;1603 pEaOp2->fpFEA2List->cbList = sizeof(achBuffer) - 4 - sizeof(EAOP2);1604 rc = DosQueryPathInfo((PCSZ)pszNativePath, FIL_QUERYEASFROMLIST, pEaOp2, sizeof(EAOP2));1605 if (rc == ERROR_SHARING_VIOLATION || rc == ERROR_ACCESS_DENIED || rc == ERROR_INVALID_ACCESS)1606 {1607 HDIR hDir = HDIR_CREATE;1608 ULONG cFiles = 1;1609 pEaOp2->fpGEA2List = (PGEA2LIST)&gGEA2ListMode;1610 pEaOp2->fpFEA2List = (PFEA2LIST)(pEaOp2 + 1);1611 pEaOp2->oError = 0;1612 pEaOp2->fpFEA2List->cbList = sizeof(achBuffer) - 4 - sizeof(EAOP2);1613 rc = DosFindFirst((PCSZ)pszNativePath, &hDir, 0, pEaOp2, pEaOp2->fpFEA2List->cbList + sizeof(*pEaOp2), &cFiles, FIL_QUERYEASFROMLIST);1614 if (!rc)1615 {1616 DosFindClose(hDir);1617 pEaOp2->fpFEA2List = (PFEA2LIST)((char *)pEaOp2 + sizeof(EAOP2) + offsetof(FILEFINDBUF3, cchName));1618 }1619 }1620 }1621 if (rc)1622 {1623 LIBC_ASSERTM(rc == ERROR_ACCESS_DENIED || rc == ERROR_SHARING_VIOLATION || rc == ERROR_EAS_NOT_SUPPORTED,1624 "Bogus EAs? rc=%d oError=%ld\n", rc, pEaOp2->oError);1625 rc = -__libc_native2errno(rc);1626 LIBCLOG_ERROR_RETURN_INT(rc);1627 }1628 1629 /*1630 * Parse the result.1631 * There is only one EA here, so this is gonna be pretty simple...1632 */1633 rc = -ENOTSUP;1634 PFEA2 pFea2 = &pEaOp2->fpFEA2List->list[0];1635 if ( pEaOp2->fpFEA2List->cbList > sizeof(*pFea2)1636 && pFea2->cbValue > 01637 && pFea2->cbName == sizeof(EA_MODE) - 11638 && !memcmp(EA_MODE, pFea2->szName, sizeof(EA_MODE) - 1)1639 )1640 {1641 PUSHORT pusType = (PUSHORT)&pFea2->szName[pFea2->cbName + 1];1642 if ( pusType[0] == EAT_BINARY1643 && pusType[1] == sizeof(uint32_t)1644 )1645 {1646 uint32_t u32 = *(uint32_t *)(pusType + 2);1647 if ( S_ISDIR(u32) || S_ISCHR(u32) || S_ISBLK(u32) || S_ISREG(u32)1648 || S_ISFIFO(u32) || S_ISLNK(u32) || S_ISSOCK(u32) || S_ISWHT(u32))1649 {1650 *pMode = u32;1651 rc = 0;1652 }1653 else1654 LIBC_ASSERTM_FAILED("Invalid file mode EA: u32=0%o\n", u32);1655 }1656 else1657 LIBC_ASSERTM_FAILED("Invalid LIBC EA! '%s' type=%#x len=%#x, expected type=%#x and len=4.\n",1658 pFea2->szName, pusType[0], pusType[1], EAT_BINARY);1659 }1660 1661 LIBCLOG_RETURN_MSG(rc, "ret %d *pMode=#%x\n", rc, *pMode);1662 312 } 1663 313 … … 1700 350 1701 351 1702 /** 1703 * Updates the FS info object. 1704 */ 1705 static void fsInfoObjUpdate(__LIBC_PFSINFO pFsInfo, dev_t Dev) 1706 { 1707 static char achBuffer[384]; /* we're protected by the mutex, don't assume too much stack! */ 1708 ULONG cb = sizeof(achBuffer); 1709 PFSQBUFFER2 pfsqb = (PFSQBUFFER2)achBuffer; 1710 1711 /* init the structure */ 1712 pFsInfo->fZeroNewBytes = 0; 1713 pFsInfo->fUnixEAs = 0; 1714 pFsInfo->Dev = Dev; 1715 pFsInfo->szName[0] = '\0'; 1716 pFsInfo->szMountpoint[0] = minor(Dev); 1717 pFsInfo->szMountpoint[1] = ':'; 1718 pFsInfo->szMountpoint[2] = '\0'; 1719 pFsInfo->szMountpoint[3] = '\0'; 1720 1721 /* query fs info */ 1722 FS_VAR_SAVE_LOAD(); 1723 int rc = DosQueryFSAttach((PCSZ)pFsInfo->szMountpoint, 0, FSAIL_QUERYNAME, pfsqb, &cb); 1724 LIBC_ASSERTM(!rc, "rc=%d\n", rc); 1725 if (!rc) 1726 strncat(pFsInfo->szName, (const char *)&pfsqb->szName[pfsqb->cbName + 1], sizeof(pFsInfo->szName) - 1); 1727 if ( !strcmp(pFsInfo->szName, "JFS") 1728 || !strcmp(pFsInfo->szName, "HPFS") 1729 || !strcmp(pFsInfo->szName, "FAT")) 1730 { 1731 pFsInfo->fZeroNewBytes = 1; 1732 pFsInfo->fUnixEAs = 1; 1733 } 1734 else if (!strcmp(pFsInfo->szName, "LAN")) 1735 { 1736 /* should find a way of getting the remote fs... */ 1737 pFsInfo->fZeroNewBytes = 1; /* for performance reasons, assume it zeros. */ 1738 pFsInfo->fUnixEAs = 0; 1739 } 1740 else if (!strcmp(pFsInfo->szName, "RAMFS")) 1741 { 1742 pFsInfo->fZeroNewBytes = 0; 1743 pFsInfo->fUnixEAs = 1; /* but it doesn't zero */ 1744 } 1745 /*else if (!strcmp(pFsInfo->szName, "FAT32")) 1746 { 1747 pFsInfo->fZeroNewBytes = 0; 1748 pFsInfo->fUnixEAs = 0; 1749 }*/ 1750 else 1751 { 1752 pFsInfo->fZeroNewBytes = 0; 1753 pFsInfo->fUnixEAs = 0; 1754 } 1755 1756 LIBCLOG_MSG2("fsInfoObjUpdate: dev:%#x mp:%s fsd:%s fZeroNewBytes=%d fUnixEAs=%d\n", 1757 pFsInfo->Dev, pFsInfo->szMountpoint, pFsInfo->szName, pFsInfo->fZeroNewBytes, 1758 pFsInfo->fUnixEAs); 1759 FS_RESTORE(); 1760 } 1761 1762 352 #ifdef __OS2__ 1763 353 /** 1764 354 * Gets the fs info object for the specfied path. … … 1846 436 return __libc_back_fsInfoObjByDev(Dev); 1847 437 } 438 #endif 1848 439 1849 440 … … 1883 474 1884 475 476 #ifdef __OS2__ 1885 477 /** 1886 478 * Checks if the path supports Unix EAs or not. … … 1899 491 return fUnixEAs; 1900 492 } 493 #endif 1901 494 1902 495 -
trunk/libc/src/kNIX/nt/b_fsUnlink.c
r2738 r2742 29 29 * Header Files * 30 30 *******************************************************************************/ 31 #include "libc-alias.h" 32 #define INCL_FSMACROS 33 #define INCL_ERRORS 34 #define INCL_DOSFILEMGR 35 #define INCL_DOSMISC 36 #include <os2emx.h> 37 #include "b_fs.h" 31 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_FS 32 #include "../kNIX.h" 33 #include <klibc/nt/nt.h> 34 //#include "b_fs.h" - later? 38 35 #include <errno.h> 39 36 #include <string.h> 40 37 #include <sys/stat.h> 41 #include <InnoTekLIBC/backend.h> 42 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_FS 43 #include <InnoTekLIBC/logstrict.h> 38 #include <klibc/backend.h> 39 #include <klibc/logstrict.h> 44 40 45 41 … … 61 57 LIBCLOG_ERROR_RETURN_INT(-ENOENT); 62 58 59 #if 0 /* later */ 63 60 /* 64 61 * Resolve the path. … … 167 164 LIBCLOG_RETURN_INT(rc); 168 165 LIBCLOG_ERROR_RETURN_INT(rc); 166 167 #else 168 169 LIBCLOG_ERROR_RETURN_INT(-ENOSYS); 170 #endif 169 171 } 170 172 -
trunk/libc/src/kNIX/nt/b_signalMask.c
r2738 r2742 2 2 /** @file 3 3 * 4 * LIBC SYS Backend- sigprocmask().4 * kNIX - sigprocmask(). 5 5 * 6 * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>6 * Copyright (c) 2004-2006 knut st. osmundsen <bird-srcspam@anduin.net> 7 7 * 8 8 * 9 * This file is part of InnoTekLIBC.9 * This file is part of kLIBC. 10 10 * 11 * InnoTekLIBC is free software; you can redistribute it and/or modify11 * kLIBC is free software; you can redistribute it and/or modify 12 12 * it under the terms of the GNU Lesser General Public License as published 13 13 * by the Free Software Foundation; either version 2 of the License, or 14 14 * (at your option) any later version. 15 15 * 16 * InnoTekLIBC is distributed in the hope that it will be useful,16 * kLIBC is distributed in the hope that it will be useful, 17 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the … … 20 20 * 21 21 * You should have received a copy of the GNU Lesser General Public License 22 * along with InnoTekLIBC; if not, write to the Free Software22 * along with kLIBC; if not, write to the Free Software 23 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 24 * … … 29 29 * Header Files * 30 30 *******************************************************************************/ 31 #include "libc-alias.h" 32 #define INCL_BASE 33 #define INCL_FSMACROS 34 #define INCL_DOSSIGNALS 35 #include <os2emx.h> 36 31 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_SIGNAL 32 #include "../kNIX.h" 37 33 #include <signal.h> 38 34 #include <errno.h> 39 #include <InnoTekLIBC/thread.h> 40 #include <InnoTekLIBC/backend.h> 41 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_SIGNAL 42 #include <InnoTekLIBC/logstrict.h> 43 #include "b_signal.h" 35 #include <klibc/thread.h> 36 #include <klibc/backend.h> 37 #include <klibc/logstrict.h> 38 //#include "b_signal.h" - later? 44 39 45 40 … … 94 89 __SIGSET_EMPTY(&SigSetNew); 95 90 91 #if 0 /* this will be a server call later. */ 96 92 /* 97 93 * Gain exclusive access to the signal stuff. … … 157 153 SigSetNew.__bitmap[1], SigSetNew.__bitmap[0]); 158 154 LIBCLOG_RETURN_INT(0); 155 #else 156 LIBCLOG_ERROR_RETURN_INT(-ENOSYS); 157 #endif 159 158 } 160 159 -
trunk/libc/src/kNIX/nt/b_threadCleanup.c
r2738 r2742 2 2 /** @file 3 3 * 4 * LIBC SYS Backend - Thread structure cleanup.4 * kNIX - Thread structure cleanup, NT. 5 5 * 6 * Copyright (c) 200 4knut st. osmundsen <bird-srcspam@anduin.net>6 * Copyright (c) 2006 knut st. osmundsen <bird-srcspam@anduin.net> 7 7 * 8 8 * 9 * This file is part of InnoTekLIBC.9 * This file is part of kLIBC. 10 10 * 11 * InnoTekLIBC is free software; you can redistribute it and/or modify11 * kLIBC is free software; you can redistribute it and/or modify 12 12 * it under the terms of the GNU Lesser General Public License as published 13 13 * by the Free Software Foundation; either version 2 of the License, or 14 14 * (at your option) any later version. 15 15 * 16 * InnoTekLIBC is distributed in the hope that it will be useful,16 * kLIBC is distributed in the hope that it will be useful, 17 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the … … 20 20 * 21 21 * You should have received a copy of the GNU Lesser General Public License 22 * along with InnoTekLIBC; if not, write to the Free Software22 * along with kLIBC; if not, write to the Free Software 23 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 24 * 25 25 */ 26 26 27 27 28 /******************************************************************************* 28 29 * Header Files * 29 30 *******************************************************************************/ 30 # include "libc-alias.h"31 # define INCL_DOS32 # define INCL_FSMACROS33 #include < os2emx.h>34 #include "syscalls.h"35 #include < InnoTekLIBC/thread.h>36 #include <InnoTekLIBC/backend.h> 31 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_THREAD 32 #include "../kNIX.h" 33 #include <sys/signal.h> 34 #include <klibc/thread.h> 35 #include <klibc/backend.h> 36 #include <klibc/logstrict.h> 37 37 38 38 39 void __libc_Back_threadCleanup(__LIBC_PTHREAD pThrd) … … 40 41 if (!pThrd) 41 42 return; 42 43 if (pThrd->b.sys.fd.hdir != HDIR_CREATE) 44 { 45 FS_VAR(); 46 FS_SAVE_LOAD(); 47 DosFindClose(pThrd->b.sys.fd.hdir); 48 FS_RESTORE(); 49 pThrd->b.sys.fd.hdir = HDIR_CREATE; 50 } 43 /** @todo later... */ 51 44 } -
trunk/libc/src/kNIX/nt/b_threadInit.c
r2738 r2742 2 2 /** @file 3 3 * 4 * LIBC SYS Backend - thread structure init.4 * kNIX - thread structure init, NT. 5 5 * 6 * Copyright (c) 200 4knut st. osmundsen <bird-srcspam@anduin.net>6 * Copyright (c) 2006 knut st. osmundsen <bird-srcspam@anduin.net> 7 7 * 8 8 * 9 * This file is part of InnoTekLIBC.9 * This file is part of kLIBC. 10 10 * 11 * InnoTekLIBC is free software; you can redistribute it and/or modify11 * kLIBC is free software; you can redistribute it and/or modify 12 12 * it under the terms of the GNU Lesser General Public License as published 13 13 * by the Free Software Foundation; either version 2 of the License, or 14 14 * (at your option) any later version. 15 15 * 16 * InnoTekLIBC is distributed in the hope that it will be useful,16 * kLIBC is distributed in the hope that it will be useful, 17 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the … … 20 20 * 21 21 * You should have received a copy of the GNU Lesser General Public License 22 * along with InnoTekLIBC; if not, write to the Free Software22 * along with kLIBC; if not, write to the Free Software 23 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 24 24 * … … 28 28 * Header Files * 29 29 *******************************************************************************/ 30 #include "libc-alias.h" 31 #define INCL_DOSEXCEPTIONS 32 #define INCL_FSMACROS 33 #include <os2emx.h> 30 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_BACK_THREAD 31 #include "../kNIX.h" 34 32 #include <sys/signal.h> 35 #include <emx/syscalls.h> 36 #include "syscalls.h" 37 #include "b_signal.h" 38 #include <InnoTekLIBC/thread.h> 39 #include <InnoTekLIBC/backend.h> 33 #include <klibc/thread.h> 34 #include <klibc/backend.h> 35 #include <klibc/logstrict.h> 40 36 41 37 42 38 void __libc_Back_threadInit(__LIBC_PTHREAD pThrd, const __LIBC_PTHREAD pParentThrd) 43 39 { 44 pThrd->b.sys.fd.hdir = HDIR_CREATE; 45 pThrd->b.sys.fd.cFiles = 0; 40 /** @todo Tell server about this (unless it's the primary thread which it should know about already). */ 46 41 47 if (pParentThrd && pParentThrd->tid)48 {49 /*50 * We don't mess with the signal semaphore here because that *will*51 * cause deadlocks. So to protect ourselves against signals52 * we'll simply enter a must complete section while accessing the53 * variables. This naturally assumes that WE are the parent!54 */55 FS_VAR_SAVE_LOAD();56 ULONG ulNesting = 0;57 DosEnterMustComplete(&ulNesting);58 59 /*60 * Copy signal stuff.61 */62 pThrd->SigSetBlocked = pParentThrd->SigSetBlocked;63 if (pParentThrd->fSigSetBlockedOld)64 {65 pThrd->SigSetBlockedOld = pParentThrd->SigSetBlockedOld;66 pThrd->fSigSetBlockedOld = pParentThrd->fSigSetBlockedOld;67 }68 69 /*70 * Exit must complete section.71 */72 DosExitMustComplete(&ulNesting);73 FS_RESTORE();74 }75 42 } 76 43 -
trunk/libc/src/kNIX/nt/fhNtFile.c
r2739 r2742 35 35 #include <klibc/logstrict.h> 36 36 37 /** 38 * Helper function for waiting on pending I/O. 39 * 40 * @returns nt status of the completed operation. 41 * @param pFH The handle. 42 */ 43 static NTSTATUS fhNtFileWaitPending(__LIBC_PFH pFH) 44 { 45 for (;;) 46 { 47 LARGE_INTEGER Interval; 48 Interval.QuadPart = -3000*10000; /* 3 sec */ 49 NTSTATUS rc = NtWaitForSingleObject((HANDLE)pFH->hNative, TRUE, &Interval); 50 if ( rc != STATUS_TIMEOUT 51 && rc != STATUS_ALERTED 52 && rc != STATUS_USER_APC 53 && rc != STATUS_KERNEL_APC /* yea sure */ 54 && rc != STATUS_PENDING /* yea sure */ 55 ) 56 return rc; 57 /** @todo check if we're exitting or something. */ 58 } 59 } 37 60 38 61 … … 76 99 NULL, /* ByteOffset */ 77 100 NULL); /* Key */ 101 if (rc == STATUS_PENDING) 102 rc = fhNtFileWaitPending(pFH); 78 103 if (NT_SUCCESS(rc)) 79 104 { … … 109 134 NULL, /* ByteOffset */ 110 135 NULL); /* Key */ 136 if (rc == STATUS_PENDING) 137 rc = fhNtFileWaitPending(pFH); 111 138 if (NT_SUCCESS(rc)) 112 139 { … … 114 141 LIBCLOG_RETURN_MSG(0, "ret 0 *pcbWritten=%zu\n", *pcbWritten); 115 142 } 143 rc = -__libc_back_NtStatus2Errno(rc); 144 LIBCLOG_ERROR_RETURN_INT(rc); 145 } 146 147 148 /** Seek operation. 149 * @returns 0 on success. 150 * @returns Negated errno on failure. 151 * @param pFH Pointer to the handle structure to operate on. 152 * @param off The seek offset. 153 * @param iMethod The seek method (SEEK_SET, SEEK_CUR, SEEK_END). 154 * @param poffActual Where to store the new offset. 155 */ 156 static int fhNtFileSeek(__LIBC_PFH pFH, off_t off, int iMethod, off_t *poffActual) 157 { 158 LIBCLOG_ENTER("pFH=%p:{.fh=%d} off=%llx iMethod=%d poffActual=%p\n", pFH, pFH->fh, off, iMethod, poffActual); 159 160 NTSTATUS rc; 161 IO_STATUS_BLOCK IoSB = {0}; 162 163 /* 164 * Figure out the seek target. 165 * Only SEEK_SET is simple here, for the two other methods we'll have to query the 166 * value it's relative to first. 167 */ 168 FILE_POSITION_INFORMATION FilePosInfo = {0}; 169 switch (iMethod) 170 { 171 case SEEK_SET: 172 FilePosInfo.CurrentByteOffset.QuadPart = off; 173 break; 174 175 case SEEK_CUR: 176 { 177 rc = ZwQueryInformationFile((HANDLE)pFH->hNative, /* FileHandle */ 178 &IoSB, /* IoStatusBlock */ 179 &FilePosInfo, /* FileInformation */ 180 sizeof(FilePosInfo), /* Length */ 181 FilePositionInformation); /* FileInformationClass */ 182 if (rc == STATUS_PENDING) /* paranoia */ 183 rc = fhNtFileWaitPending(pFH); 184 if (!NT_SUCCESS(rc)) 185 { 186 rc = -__libc_back_NtStatus2Errno(rc); 187 LIBCLOG_ERROR_RETURN_INT(rc); 188 } 189 /** @todo Could we return here if off is 0, or do we really have to set the file position? 190 * The only reasons why we should set it are: 191 * -# permission check. 192 * -# could be resetting EOF and similar flags. 193 * It would speed up tell() if we could skip the NtSetInformationFile stuff. 194 */ 195 FilePosInfo.CurrentByteOffset.QuadPart += off; 196 break; 197 } 198 199 case SEEK_END: 200 { 201 FILE_END_OF_FILE_INFORMATION FileEofInfo = {0}; 202 rc = ZwQueryInformationFile((HANDLE)pFH->hNative, /* FileHandle */ 203 &IoSB, /* IoStatusBlock */ 204 &FileEofInfo, /* FileInformation */ 205 sizeof(FileEofInfo), /* Length */ 206 FileEndOfFileInformation); /* FileInformationClass */ 207 if (rc == STATUS_PENDING) /* paranoia */ 208 rc = fhNtFileWaitPending(pFH); 209 if (!NT_SUCCESS(rc)) 210 { 211 rc = -__libc_back_NtStatus2Errno(rc); 212 LIBCLOG_ERROR_RETURN_INT(rc); 213 } 214 FilePosInfo.CurrentByteOffset.QuadPart = FileEofInfo.EndOfFile.QuadPart + off; 215 break; 216 } 217 218 default: 219 LIBC_ASSERTM_FAILED("iMethod=%d\n", iMethod); 220 LIBCLOG_ERROR_RETURN_INT(-EINVAL); 221 } 222 223 /* 224 * Try change the file position. 225 */ 226 *poffActual = FilePosInfo.CurrentByteOffset.QuadPart; 227 rc = ZwSetInformationFile((HANDLE)pFH->hNative, /* FileHandle */ 228 &IoSB, /* IoStatusBlock */ 229 &FilePosInfo, /* FileInformation */ 230 sizeof(FilePosInfo), /* Length */ 231 FilePositionInformation); /* FileInformationClass */ 232 if (rc == STATUS_PENDING) /* paranoia */ 233 rc = fhNtFileWaitPending(pFH); 234 if (NT_SUCCESS(rc)) 235 LIBCLOG_RETURN_MSG(0, "ret 0 *poffActual=%llx\n", *poffActual); 236 rc = -__libc_back_NtStatus2Errno(rc); 237 LIBCLOG_ERROR_RETURN_INT(rc); 238 } 239 240 241 /** 242 * Sets the size of an open file. 243 * 244 * @returns 0 on success. 245 * @returns Negative error code (errno.h) on failure. 246 * @param pFH The file handle structure. 247 * @param cbFile The new filesize. 248 * @param fZero If set any new allocated file space should be initialized to zero. 249 */ 250 static int fhNtFileSizeSet(__LIBC_PFH pFH, off_t cbFile, int fZero) 251 { 252 LIBCLOG_ENTER("fh=%d cbFile=%lld fZero=%d\n", fh, cbFile, fZero); 253 254 /** @todo Check if having a file position *AFTER* the new EOF is a problem. */ 255 /** @todo Check if all file systems on NT will initialize new space with zeros. */ 256 IO_STATUS_BLOCK IoSB = {0}; 257 FILE_END_OF_FILE_INFORMATION FileEofInfo = {0}; 258 FileEofInfo.EndOfFile.QuadPart = cbFile; 259 NTSTATUS rc = ZwSetInformationFile((HANDLE)pFH->hNative, /* FileHandle */ 260 &IoSB, /* IoStatusBlock */ 261 &FileEofInfo, /* FileInformation */ 262 sizeof(FileEofInfo), /* Length */ 263 FileEndOfFileInformation); /* FileInformationClass */ 264 if (rc == STATUS_PENDING) /* paranoia */ 265 rc = fhNtFileWaitPending(pFH); 266 if (NT_SUCCESS(rc)) 267 LIBCLOG_RETURN_INT(0); 116 268 rc = -__libc_back_NtStatus2Errno(rc); 117 269 LIBCLOG_ERROR_RETURN_INT(rc); … … 199 351 fhNtFileRead, 200 352 fhNtFileWrite, 353 fhNtFileSeek, 354 fhNtFileSizeSet, 201 355 fhNtFileDuplicate, 202 356 fhNtFileFileControl, -
trunk/libc/src/kNIX/os2/fhOS2File.c
r2739 r2742 27 27 28 28 /******************************************************************************* 29 * Global Variables * 30 *******************************************************************************/ 31 /** A page of zeros. 32 * @todo Make this a separate segment for optimal thunking effiency! */ 33 static const char __libc_gachZeros[65536 - 4096]; 34 35 36 /******************************************************************************* 29 37 * Internal Functions * 30 38 *******************************************************************************/ 31 static int fhOs2FileClose(__LIBC_PFH pFH); 32 33 /** Operations on sockets. */ 34 static const __LIBC_FHOPS gSocketOps = 35 { 36 enmFH_File, /* Handle type. */ 37 fhOs2FileClose, 38 fhOs2FileRead, 39 fhOs2FileWrite, 40 fhOs2FileDuplicate, 41 fhOs2FileFileControl, 42 fhOs2FileIOControl, 43 fhOs2FileSelect, 44 NULL /* fork parent */, 45 NULL /* for child */ 46 }; 39 static inline int getFileSize(HFILE hFile, off_t *pcb); 40 static inline int setFileSize(HFILE hFile, off_t cbFile); 41 static inline int seekFile(HFILE hFile, off_t cbFile, int iMethod, off_t *poffFile); 42 47 43 48 44 … … 124 120 * @returns Negated errno on failure. 125 121 * @param pFH Pointer to the handle structure to operate on. 126 * @param fh It's associated filehandle.127 122 * @param pvBuf Pointer to the buffer which contains the data to write. 128 123 * @param cbToWrite Number of bytes to write. … … 172 167 173 168 169 /** Seek operation. 170 * @returns 0 on success. 171 * @returns Negated errno on failure. 172 * @param pFH Pointer to the handle structure to operate on. 173 * @param off The seek offset. 174 * @param iMethod The seek method (SEEK_SET, SEEK_CUR, SEEK_END). 175 * @param poffActual Where to store the new offset. 176 */ 177 static int fhOs2FileSeek(__LIBC_PFH pFH, off_t off, int iMethod, off_t *poffActual) 178 { 179 LIBCLOG_ENTER("pFH=%p:{.fh=%d} off=%llx iMethod=%d poffActual=%p\n", pFH, pFH->fh, off, iMethod, poffActual); 180 FS_VAR_SAVE_LOAD(); 181 union 182 { 183 off_t off; 184 LONGLONG ll; 185 ULONG ul; 186 } u; 187 #if OFF_MAX > LONG_MAX 188 if (__libc_gpfnDosSetFilePtrL) 189 rc = __libc_gpfnDosSetFilePtrL(hFile, off, iMethod, &u.ll); 190 else 191 { 192 if (off > LONG_MAX || off < LONG_MIN) 193 { 194 FS_RESTORE(); 195 LIBCLOG_ERROR_RETURN_INT(-EOVERFLOW); 196 } 197 u.off = 0; 198 rc = DosSetFilePtr(hFile, off, iMethod, &u.ul); 199 } 200 #else 201 { 202 u.off = 0; 203 rc = DosSetFilePtr(hFile, off, iMethod, &u.ul); 204 } 205 #endif 206 FS_RESTORE(); 207 if (__predict_true(!rc)) 208 { 209 poffActual = u.off; 210 LIBCLOG_RETURN_INT(0); 211 } 212 rc = -__libc_native2errno(rc); 213 LIBCLOG_ERROR_RETURN_INT(rc); 214 } 215 216 217 /** 218 * Calls the correct OS/2 api for this operation. 219 * FS is saved and loaded by caller. 220 * @returns OS/2 error code or negative errno. 221 */ 222 static inline int getFileSize(HFILE hFile, off_t *pcb) 223 { 224 union 225 { 226 FILESTATUS3 fsts3; 227 FILESTATUS3L fsts3L; 228 } info; 229 int rc; 230 #if OFF_MAX > LONG_MAX 231 if (__libc_gpfnDosOpenL) 232 { 233 rc = DosQueryFileInfo(hFile, FIL_STANDARDL, &info, sizeof(info.fsts3L)); 234 *pcb = info.fsts3L.cbFile; 235 } 236 else 237 #endif 238 { 239 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &info, sizeof(info.fsts3)); 240 *pcb = info.fsts3.cbFile; 241 } 242 return rc; 243 } 244 245 /** 246 * Calls the correct OS/2 api for this operation. 247 * FS is saved and loaded by caller. 248 * @returns OS/2 error code or negative errno. 249 */ 250 static inline int setFileSize(HFILE hFile, off_t cbFile) 251 { 252 int rc; 253 #if OFF_MAX > LONG_MAX 254 if (__libc_gpfnDosSetFileSizeL) 255 rc = __libc_gpfnDosSetFileSizeL(hFile, cbFile); 256 else 257 { 258 if (cbFile > __LONG_MAX) 259 return -EOVERFLOW; 260 rc = DosSetFileSize(hFile, cbFile); 261 } 262 #else 263 rc = DosSetFileSize(hFile, cbFile); 264 #endif 265 return rc; 266 } 267 268 /** 269 * Calls the correct OS/2 api for this operation. 270 * FS is saved and loaded by caller. 271 * @returns OS/2 error code or negative errno. 272 */ 273 static inline int seekFile(HFILE hFile, off_t off, int iMethod, off_t *poffFile) 274 { 275 int rc; 276 #if OFF_MAX > LONG_MAX 277 if (__libc_gpfnDosSetFilePtrL) 278 { 279 LONGLONG cbNewTmp; 280 rc = __libc_gpfnDosSetFilePtrL(hFile, off, iMethod, &cbNewTmp); 281 off = cbNewTmp; 282 } 283 else 284 { 285 ULONG cbNewTmp; 286 if (off > LONG_MAX || off < LONG_MIN) 287 return -EOVERFLOW; 288 rc = DosSetFilePtr(hFile, off, iMethod, &cbNewTmp); 289 off = cbNewTmp; 290 } 291 #else 292 { 293 ULONG cbNewTmp; 294 rc = DosSetFilePtr(hFile, off, iMethod, &cbNewTmp); 295 off = cbNewTmp; 296 } 297 #endif 298 if (poffFile) 299 *poffFile = off; 300 return rc; 301 } 302 303 304 /** 305 * Sets the size of an open file. 306 * 307 * @returns 0 on success. 308 * @returns Negative error code (errno.h) on failure. 309 * @param pFH The file handle structure. 310 * @param cbFile The new filesize. 311 * @param fZero If set any new allocated file space should be initialized to zero. 312 */ 313 static int fhOS2FileSizeSet(__LIBC_PFH pFH, off_t cbFile, int fZero) 314 { 315 LIBCLOG_ENTER("fh=%d cbFile=%lld fZero=%d\n", fh, cbFile, fZero); 316 FS_VAR_SAVE_LOAD(); 317 318 /* 319 * Get the current file size so we can perform 320 * any necessary zero padding. 321 */ 322 off_t cbCur; 323 int rc = getFileSize(fh, &cbCur); 324 if (!rc) 325 { 326 if (cbCur != cbFile) 327 { 328 /* 329 * File size change needed. 330 */ 331 rc = setFileSize(fh, cbFile); 332 if (!rc) 333 { 334 /* 335 * We're done if it was a truncation, or if we don't have to zero new 336 * bytes, or if the file system driver will zero new bytes. 337 */ 338 off_t cbLeft = cbFile - cbCur; 339 if ( cbLeft <= 0 340 || !fZero 341 || ( pFH->pFsInfo 342 && pFH->pFsInfo->fZeroNewBytes)) 343 { 344 FS_RESTORE(); 345 LIBCLOG_RETURN_INT(0); 346 } 347 348 /* 349 * Must fill the allocated file space with zeros. 350 */ 351 off_t offSaved, offIgnored; 352 rc = fhOs2FileSeek(pFH, 0, SEEK_CUR, &offSaved); 353 if (!rc) 354 rc = fhOs2FileSeek(pFH, cbCur, SEEK_SET, &offIgnored); 355 while (!rc && cbLeft > 0) 356 { 357 ULONG cb = cbLeft >= sizeof(__libc_gachZeros) ? sizeof(__libc_gachZeros) : cbLeft; 358 rc = DosWrite(fh, &__libc_gachZeros[0], cb, &cb); 359 cbLeft -= cb; 360 } 361 int rc2 = fhOs2FileSeek(fh, offSaved, SEEK_SET, &offIgnored); 362 if (!rc && !rc2) 363 { 364 FS_RESTORE(); 365 LIBCLOG_RETURN_INT(0); 366 } 367 368 /* 369 * Shit, we failed writing zeros. Try undo the expand operation. 370 */ 371 setFileSize(fh, cbCur); 372 if (rc2) 373 { 374 fhOs2FileSeek(fh, offSaved, SEEK_SET, &offIgnored); 375 if (!rc) 376 rc = rc2; 377 } 378 } 379 } 380 } 381 382 FS_RESTORE(); 383 if (rc > 0) 384 rc = -__libc_native2errno(rc); 385 LIBCLOG_ERROR_RETURN_INT(rc); 386 } 387 388 174 389 /** Duplicate handle operation. 175 390 * @returns 0 on success. 176 391 * @returns Negated errno on failure. 177 392 * @param pFH Pointer to the handle structure to operate on. 178 * @param fh It's associated filehandle.179 393 * @param pfhNew Where to store the duplicate filehandle. 180 394 * The input value describe how the handle is to be … … 193 407 * @returns Negated errno on failure. 194 408 * @param pFH Pointer to the handle structure to operate on. 195 * @param fh It's associated filehandle.196 409 * @param iRequest Which file file descriptior request to perform. 197 410 * @param iArg Argument which content is specific to each … … 209 422 * @returns Negated errno on failure. 210 423 * @param pFH Pointer to the handle structure to operate on. 211 * @param fh It's associated filehandle.212 424 * @param iIOControl Which I/O control operation to perform. 213 425 * @param iArg Argument which content is specific to each … … 240 452 } 241 453 454 455 456 /** Operations on sockets. */ 457 static const __LIBC_FHOPS gSocketOps = 458 { 459 enmFH_File, /* Handle type. */ 460 fhOs2FileClose, 461 fhOs2FileRead, 462 fhOs2FileWrite, 463 fhOs2FileSeek, 464 fhOS2FileSizeSet, 465 fhOs2FileDuplicate, 466 fhOs2FileFileControl, 467 fhOs2FileIOControl, 468 fhOs2FileSelect, 469 NULL /* fork parent */, 470 NULL /* for child */ 471 }; 472 -
trunk/libc/src/libc/startup/_exit.c
r2259 r2742 2 2 3 3 #include <stdlib.h> 4 #include <emx/syscalls.h>5 4 #define __LIBC_LOG_GROUP __LIBC_LOG_GRP_INITTERM 6 #include <InnoTekLIBC/logstrict.h> 5 #include <klibc/backend.h> 6 #include <klibc/logstrict.h> 7 7 8 8 /* mkstd.awk: NOUNDERSCORE(exit) */ … … 11 11 LIBCLOG_ENTER("ret=%d\n", ret); 12 12 for (;;) 13 __ exit(ret);13 __libc_Back_processExit(ret); 14 14 LIBCLOG_MSG("shut up\n"); 15 15 }
Note:
See TracChangeset
for help on using the changeset viewer.