| /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| /* ***** BEGIN LICENSE BLOCK ***** |
| * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| * |
| * The contents of this file are subject to the Mozilla Public License Version |
| * 1.1 (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * http://www.mozilla.org/MPL/ |
| * |
| * Software distributed under the License is distributed on an "AS IS" basis, |
| * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
| * for the specific language governing rights and limitations under the |
| * License. |
| * |
| * The Original Code is the Netscape Portable Runtime (NSPR). |
| * |
| * The Initial Developer of the Original Code is |
| * Netscape Communications Corporation. |
| * Portions created by the Initial Developer are Copyright (C) 1998-2000 |
| * the Initial Developer. All Rights Reserved. |
| * |
| * Contributor(s): |
| * |
| * Alternatively, the contents of this file may be used under the terms of |
| * either the GNU General Public License Version 2 or later (the "GPL"), or |
| * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
| * in which case the provisions of the GPL or the LGPL are applicable instead |
| * of those above. If you wish to allow use of your version of this file only |
| * under the terms of either the GPL or the LGPL, and not to allow others to |
| * use your version of this file under the terms of the MPL, indicate your |
| * decision by deleting the provisions above and replace them with the notice |
| * and other provisions required by the GPL or the LGPL. If you do not delete |
| * the provisions above, a recipient may use your version of this file under |
| * the terms of any one of the MPL, the GPL or the LGPL. |
| * |
| * ***** END LICENSE BLOCK ***** */ |
| |
| /* OS2 IO module |
| * |
| * Assumes synchronous I/O. |
| * |
| */ |
| |
| #include "primpl.h" |
| #include "prio.h" |
| #include <ctype.h> |
| #include <string.h> |
| #include <limits.h> |
| #include <dirent.h> |
| #include <fcntl.h> |
| #include <io.h> |
| |
| struct _MDLock _pr_ioq_lock; |
| |
| static PRBool isWSEB = PR_FALSE; /* whether we are using an OS/2 kernel that supports large files */ |
| |
| typedef APIRET (*DosOpenLType)(PSZ pszFileName, PHFILE pHf, PULONG pulAction, |
| LONGLONG cbFile, ULONG ulAttribute, |
| ULONG fsOpenFlags, ULONG fsOpenMode, |
| PEAOP2 peaop2); |
| |
| typedef APIRET (*DosSetFileLocksLType)(HFILE hFile, PFILELOCKL pflUnlock, |
| PFILELOCKL pflLock, ULONG timeout, |
| ULONG flags); |
| |
| typedef APIRET (*DosSetFilePtrLType)(HFILE hFile, LONGLONG ib, ULONG method, |
| PLONGLONG ibActual); |
| |
| DosOpenLType myDosOpenL; |
| DosSetFileLocksLType myDosSetFileLocksL; |
| DosSetFilePtrLType myDosSetFilePtrL; |
| |
| void |
| _PR_MD_INIT_IO() |
| { |
| APIRET rc; |
| HMODULE module; |
| |
| sock_init(); |
| |
| rc = DosLoadModule(NULL, 0, "DOSCALL1", &module); |
| if (rc != NO_ERROR) |
| { |
| return; |
| } |
| rc = DosQueryProcAddr(module, 981, NULL, (PFN*) &myDosOpenL); |
| if (rc != NO_ERROR) |
| { |
| return; |
| } |
| rc = DosQueryProcAddr(module, 986, NULL, (PFN*) &myDosSetFileLocksL); |
| if (rc != NO_ERROR) |
| { |
| return; |
| } |
| rc = DosQueryProcAddr(module, 988, NULL, (PFN*) &myDosSetFilePtrL); |
| if (rc != NO_ERROR) |
| { |
| return; |
| } |
| isWSEB = PR_TRUE; |
| } |
| |
| PRStatus |
| _PR_MD_WAIT(PRThread *thread, PRIntervalTime ticks) |
| { |
| PRInt32 rv; |
| ULONG count; |
| |
| PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT) ? |
| SEM_INDEFINITE_WAIT : PR_IntervalToMilliseconds(ticks); |
| rv = DosWaitEventSem(thread->md.blocked_sema, msecs); |
| DosResetEventSem(thread->md.blocked_sema, &count); |
| switch(rv) |
| { |
| case NO_ERROR: |
| return PR_SUCCESS; |
| break; |
| case ERROR_TIMEOUT: |
| _PR_THREAD_LOCK(thread); |
| if (thread->state == _PR_IO_WAIT) { |
| ; |
| } else { |
| if (thread->wait.cvar != NULL) { |
| thread->wait.cvar = NULL; |
| _PR_THREAD_UNLOCK(thread); |
| } else { |
| /* The CVAR was notified just as the timeout |
| * occurred. This led to us being notified twice. |
| * call SemRequest() to clear the semaphore. |
| */ |
| _PR_THREAD_UNLOCK(thread); |
| rv = DosWaitEventSem(thread->md.blocked_sema, 0); |
| DosResetEventSem(thread->md.blocked_sema, &count); |
| PR_ASSERT(rv == NO_ERROR); |
| } |
| } |
| return PR_SUCCESS; |
| break; |
| default: |
| break; |
| } |
| return PR_FAILURE; |
| } |
| PRStatus |
| _PR_MD_WAKEUP_WAITER(PRThread *thread) |
| { |
| if ( _PR_IS_NATIVE_THREAD(thread) ) |
| { |
| if (DosPostEventSem(thread->md.blocked_sema) != NO_ERROR) |
| return PR_FAILURE; |
| else |
| return PR_SUCCESS; |
| } |
| } |
| |
| |
| /* --- FILE IO ----------------------------------------------------------- */ |
| /* |
| * _PR_MD_OPEN() -- Open a file |
| * |
| * returns: a fileHandle |
| * |
| * The NSPR open flags (osflags) are translated into flags for OS/2 |
| * |
| * Mode seems to be passed in as a unix style file permissions argument |
| * as in 0666, in the case of opening the logFile. |
| * |
| */ |
| PRInt32 |
| _PR_MD_OPEN(const char *name, PRIntn osflags, int mode) |
| { |
| HFILE file; |
| PRInt32 access = OPEN_SHARE_DENYNONE; |
| PRInt32 flags = 0L; |
| APIRET rc = 0; |
| PRUword actionTaken; |
| |
| #ifdef MOZ_OS2_HIGH_MEMORY |
| /* |
| * All the pointer arguments (&file, &actionTaken and name) have to be in |
| * low memory for DosOpen to use them. |
| * The following moves name to low memory. |
| */ |
| if ((ULONG)name >= 0x20000000) |
| { |
| size_t len = strlen(name) + 1; |
| char *copy = (char *)alloca(len); |
| memcpy(copy, name, len); |
| name = copy; |
| } |
| #endif |
| |
| if (osflags & PR_SYNC) access |= OPEN_FLAGS_WRITE_THROUGH; |
| |
| if (osflags & PR_RDONLY) |
| access |= OPEN_ACCESS_READONLY; |
| else if (osflags & PR_WRONLY) |
| access |= OPEN_ACCESS_WRITEONLY; |
| else if(osflags & PR_RDWR) |
| access |= OPEN_ACCESS_READWRITE; |
| |
| if ( osflags & PR_CREATE_FILE && osflags & PR_EXCL ) |
| { |
| flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS; |
| } |
| else if (osflags & PR_CREATE_FILE) |
| { |
| if (osflags & PR_TRUNCATE) |
| flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS; |
| else |
| flags = OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS; |
| } |
| else |
| { |
| if (osflags & PR_TRUNCATE) |
| flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS; |
| else |
| flags = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS; |
| } |
| |
| do { |
| if (isWSEB) |
| { |
| rc = myDosOpenL((char*)name, |
| &file, /* file handle if successful */ |
| &actionTaken, /* reason for failure */ |
| 0, /* initial size of new file */ |
| FILE_NORMAL, /* file system attributes */ |
| flags, /* Open flags */ |
| access, /* Open mode and rights */ |
| 0); /* OS/2 Extended Attributes */ |
| } |
| else |
| { |
| rc = DosOpen((char*)name, |
| &file, /* file handle if successful */ |
| &actionTaken, /* reason for failure */ |
| 0, /* initial size of new file */ |
| FILE_NORMAL, /* file system attributes */ |
| flags, /* Open flags */ |
| access, /* Open mode and rights */ |
| 0); /* OS/2 Extended Attributes */ |
| }; |
| if (rc == ERROR_TOO_MANY_OPEN_FILES) { |
| ULONG CurMaxFH = 0; |
| LONG ReqCount = 20; |
| APIRET rc2; |
| rc2 = DosSetRelMaxFH(&ReqCount, &CurMaxFH); |
| if (rc2 != NO_ERROR) { |
| break; |
| } |
| } |
| } while (rc == ERROR_TOO_MANY_OPEN_FILES); |
| |
| if (rc != NO_ERROR) { |
| _PR_MD_MAP_OPEN_ERROR(rc); |
| return -1; |
| } |
| |
| return (PRInt32)file; |
| } |
| |
| PRInt32 |
| _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len) |
| { |
| ULONG bytes; |
| int rv; |
| |
| rv = DosRead((HFILE)fd->secret->md.osfd, |
| (PVOID)buf, |
| len, |
| &bytes); |
| |
| if (rv != NO_ERROR) |
| { |
| /* ERROR_HANDLE_EOF can only be returned by async io */ |
| PR_ASSERT(rv != ERROR_HANDLE_EOF); |
| if (rv == ERROR_BROKEN_PIPE) |
| return 0; |
| else { |
| _PR_MD_MAP_READ_ERROR(rv); |
| return -1; |
| } |
| } |
| return (PRInt32)bytes; |
| } |
| |
| PRInt32 |
| _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len) |
| { |
| PRInt32 bytes; |
| int rv; |
| |
| rv = DosWrite((HFILE)fd->secret->md.osfd, |
| (PVOID)buf, |
| len, |
| (PULONG)&bytes); |
| |
| if (rv != NO_ERROR) |
| { |
| _PR_MD_MAP_WRITE_ERROR(rv); |
| return -1; |
| } |
| |
| if (len != bytes) { |
| rv = ERROR_DISK_FULL; |
| _PR_MD_MAP_WRITE_ERROR(rv); |
| return -1; |
| } |
| |
| return bytes; |
| } /* --- end _PR_MD_WRITE() --- */ |
| |
| PRInt32 |
| _PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, PRSeekWhence whence) |
| { |
| PRInt32 rv; |
| PRUword newLocation; |
| |
| rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, offset, whence, &newLocation); |
| |
| if (rv != NO_ERROR) { |
| _PR_MD_MAP_LSEEK_ERROR(rv); |
| return -1; |
| } else |
| return newLocation; |
| } |
| |
| PRInt64 |
| _PR_MD_LSEEK64(PRFileDesc *fd, PRInt64 offset, PRSeekWhence whence) |
| { |
| #ifdef NO_LONG_LONG |
| PRInt64 result; |
| PRInt32 rv, low = offset.lo, hi = offset.hi; |
| PRUword newLocation; |
| |
| rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, low, whence, &newLocation); |
| rv = DosSetFilePtr((HFILE)fd->secret->md.osfd, hi, FILE_CURRENT, &newLocation); |
| |
| if (rv != NO_ERROR) { |
| _PR_MD_MAP_LSEEK_ERROR(rv); |
| hi = newLocation = -1; |
| } |
| |
| result.lo = newLocation; |
| result.hi = hi; |
| return result; |
| |
| #else |
| PRInt32 where, rc, lo = (PRInt32)offset, hi = (PRInt32)(offset >> 32); |
| PRUint64 rv; |
| PRUint32 newLocation, uhi; |
| PRUint64 newLocationL; |
| |
| switch (whence) |
| { |
| case PR_SEEK_SET: |
| where = FILE_BEGIN; |
| break; |
| case PR_SEEK_CUR: |
| where = FILE_CURRENT; |
| break; |
| case PR_SEEK_END: |
| where = FILE_END; |
| break; |
| default: |
| PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); |
| return -1; |
| } |
| if (isWSEB) |
| { |
| rc = myDosSetFilePtrL((HFILE)fd->secret->md.osfd, offset, where, (PLONGLONG)&newLocationL); |
| } |
| else |
| { |
| rc = DosSetFilePtr((HFILE)fd->secret->md.osfd, lo, where, (PULONG)&newLocation); |
| } |
| |
| if (rc != NO_ERROR) { |
| _PR_MD_MAP_LSEEK_ERROR(rc); |
| return -1; |
| } |
| |
| if (isWSEB) |
| { |
| return newLocationL; |
| } |
| |
| uhi = (PRUint32)hi; |
| PR_ASSERT((PRInt32)uhi >= 0); |
| rv = uhi; |
| PR_ASSERT((PRInt64)rv >= 0); |
| rv = (rv << 32); |
| PR_ASSERT((PRInt64)rv >= 0); |
| rv += newLocation; |
| PR_ASSERT((PRInt64)rv >= 0); |
| return (PRInt64)rv; |
| #endif |
| } |
| |
| PRInt32 |
| _PR_MD_FSYNC(PRFileDesc *fd) |
| { |
| PRInt32 rc = DosResetBuffer((HFILE)fd->secret->md.osfd); |
| |
| if (rc != NO_ERROR) { |
| if (rc != ERROR_ACCESS_DENIED) { |
| _PR_MD_MAP_FSYNC_ERROR(rc); |
| return -1; |
| } |
| } |
| return 0; |
| } |
| |
| PRInt32 |
| _MD_CloseFile(PRInt32 osfd) |
| { |
| PRInt32 rv; |
| |
| rv = DosClose((HFILE)osfd); |
| if (rv != NO_ERROR) |
| _PR_MD_MAP_CLOSE_ERROR(rv); |
| return rv; |
| } |
| |
| |
| /* --- DIR IO ------------------------------------------------------------ */ |
| #define GetFileFromDIR(d) (isWSEB?(d)->d_entry.large.achName:(d)->d_entry.small.achName) |
| #define GetFileAttr(d) (isWSEB?(d)->d_entry.large.attrFile:(d)->d_entry.small.attrFile) |
| |
| void FlipSlashes(char *cp, int len) |
| { |
| while (--len >= 0) { |
| if (cp[0] == '/') { |
| cp[0] = PR_DIRECTORY_SEPARATOR; |
| } |
| cp++; |
| } |
| } |
| |
| /* |
| ** |
| ** Local implementations of standard Unix RTL functions which are not provided |
| ** by the VAC RTL. |
| ** |
| */ |
| |
| PRInt32 |
| _PR_MD_CLOSE_DIR(_MDDir *d) |
| { |
| PRInt32 rc; |
| |
| if ( d ) { |
| rc = DosFindClose(d->d_hdl); |
| if(rc == NO_ERROR){ |
| d->magic = (PRUint32)-1; |
| return PR_SUCCESS; |
| } else { |
| _PR_MD_MAP_CLOSEDIR_ERROR(rc); |
| return PR_FAILURE; |
| } |
| } |
| PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); |
| return PR_FAILURE; |
| } |
| |
| |
| PRStatus |
| _PR_MD_OPEN_DIR(_MDDir *d, const char *name) |
| { |
| char filename[ CCHMAXPATH ]; |
| PRUword numEntries, rc; |
| |
| numEntries = 1; |
| |
| PR_snprintf(filename, CCHMAXPATH, "%s%s%s", |
| name, PR_DIRECTORY_SEPARATOR_STR, "*.*"); |
| FlipSlashes( filename, strlen(filename) ); |
| |
| d->d_hdl = HDIR_CREATE; |
| |
| if (isWSEB) |
| { |
| rc = DosFindFirst( filename, |
| &d->d_hdl, |
| FILE_DIRECTORY | FILE_HIDDEN, |
| &(d->d_entry.large), |
| sizeof(d->d_entry.large), |
| &numEntries, |
| FIL_STANDARDL); |
| } |
| else |
| { |
| rc = DosFindFirst( filename, |
| &d->d_hdl, |
| FILE_DIRECTORY | FILE_HIDDEN, |
| &(d->d_entry.small), |
| sizeof(d->d_entry.small), |
| &numEntries, |
| FIL_STANDARD); |
| } |
| if ( rc != NO_ERROR ) { |
| _PR_MD_MAP_OPENDIR_ERROR(rc); |
| return PR_FAILURE; |
| } |
| d->firstEntry = PR_TRUE; |
| d->magic = _MD_MAGIC_DIR; |
| return PR_SUCCESS; |
| } |
| |
| char * |
| _PR_MD_READ_DIR(_MDDir *d, PRIntn flags) |
| { |
| PRUword numFiles = 1; |
| BOOL rv; |
| char *fileName; |
| USHORT fileAttr; |
| |
| if ( d ) { |
| while (1) { |
| if (d->firstEntry) { |
| d->firstEntry = PR_FALSE; |
| rv = NO_ERROR; |
| } else { |
| rv = DosFindNext(d->d_hdl, |
| &(d->d_entry), |
| sizeof(d->d_entry), |
| &numFiles); |
| } |
| if (rv != NO_ERROR) { |
| break; |
| } |
| fileName = GetFileFromDIR(d); |
| fileAttr = GetFileAttr(d); |
| if ( (flags & PR_SKIP_DOT) && |
| (fileName[0] == '.') && (fileName[1] == '\0')) |
| continue; |
| if ( (flags & PR_SKIP_DOT_DOT) && |
| (fileName[0] == '.') && (fileName[1] == '.') && |
| (fileName[2] == '\0')) |
| continue; |
| /* |
| * XXX |
| * Is this the correct definition of a hidden file on OS/2? |
| */ |
| if ((flags & PR_SKIP_NONE) && (fileAttr & FILE_HIDDEN)) |
| return fileName; |
| else if ((flags & PR_SKIP_HIDDEN) && (fileAttr & FILE_HIDDEN)) |
| continue; |
| return fileName; |
| } |
| PR_ASSERT(NO_ERROR != rv); |
| _PR_MD_MAP_READDIR_ERROR(rv); |
| return NULL; |
| } |
| PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); |
| return NULL; |
| } |
| |
| PRInt32 |
| _PR_MD_DELETE(const char *name) |
| { |
| PRInt32 rc = DosDelete((char*)name); |
| if(rc == NO_ERROR) { |
| return 0; |
| } else { |
| _PR_MD_MAP_DELETE_ERROR(rc); |
| return -1; |
| } |
| } |
| |
| PRInt32 |
| _PR_MD_STAT(const char *fn, struct stat *info) |
| { |
| PRInt32 rv; |
| char filename[CCHMAXPATH]; |
| |
| PR_snprintf(filename, CCHMAXPATH, "%s", fn); |
| FlipSlashes(filename, strlen(filename)); |
| |
| rv = _stat((char*)filename, info); |
| if (-1 == rv) { |
| /* |
| * Check for MSVC runtime library _stat() bug. |
| * (It's really a bug in FindFirstFile().) |
| * If a pathname ends in a backslash or slash, |
| * e.g., c:\temp\ or c:/temp/, _stat() will fail. |
| * Note: a pathname ending in a slash (e.g., c:/temp/) |
| * can be handled by _stat() on NT but not on Win95. |
| * |
| * We remove the backslash or slash at the end and |
| * try again. |
| * |
| * Not sure if this happens on OS/2 or not, |
| * but it doesn't hurt to be careful. |
| */ |
| |
| int len = strlen(fn); |
| if (len > 0 && len <= _MAX_PATH |
| && (fn[len - 1] == '\\' || fn[len - 1] == '/')) { |
| char newfn[_MAX_PATH + 1]; |
| |
| strcpy(newfn, fn); |
| newfn[len - 1] = '\0'; |
| rv = _stat(newfn, info); |
| } |
| } |
| |
| if (-1 == rv) { |
| _PR_MD_MAP_STAT_ERROR(errno); |
| } |
| return rv; |
| } |
| |
| PRInt32 |
| _PR_MD_GETFILEINFO(const char *fn, PRFileInfo *info) |
| { |
| struct stat sb; |
| PRInt32 rv; |
| PRInt64 s, s2us; |
| |
| if ( (rv = _PR_MD_STAT(fn, &sb)) == 0 ) { |
| if (info) { |
| if (S_IFREG & sb.st_mode) |
| info->type = PR_FILE_FILE ; |
| else if (S_IFDIR & sb.st_mode) |
| info->type = PR_FILE_DIRECTORY; |
| else |
| info->type = PR_FILE_OTHER; |
| info->size = sb.st_size; |
| LL_I2L(s2us, PR_USEC_PER_SEC); |
| LL_I2L(s, sb.st_mtime); |
| LL_MUL(s, s, s2us); |
| info->modifyTime = s; |
| LL_I2L(s, sb.st_ctime); |
| LL_MUL(s, s, s2us); |
| info->creationTime = s; |
| } |
| } |
| return rv; |
| } |
| |
| PRInt32 |
| _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info) |
| { |
| PRFileInfo info32; |
| PRInt32 rv = _PR_MD_GETFILEINFO(fn, &info32); |
| if (rv != 0) |
| { |
| return rv; |
| } |
| info->type = info32.type; |
| LL_UI2L(info->size,info32.size); |
| info->modifyTime = info32.modifyTime; |
| info->creationTime = info32.creationTime; |
| |
| if (isWSEB) |
| { |
| APIRET rc ; |
| FILESTATUS3L fstatus; |
| |
| rc = DosQueryPathInfo(fn, FIL_STANDARDL, &fstatus, sizeof(fstatus)); |
| |
| if (NO_ERROR != rc) |
| { |
| _PR_MD_MAP_OPEN_ERROR(rc); |
| return -1; |
| } |
| |
| if (! (fstatus.attrFile & FILE_DIRECTORY)) |
| { |
| info->size = fstatus.cbFile; |
| } |
| } |
| |
| return rv; |
| } |
| |
| PRInt32 |
| _PR_MD_GETOPENFILEINFO(const PRFileDesc *fd, PRFileInfo *info) |
| { |
| /* For once, the VAC compiler/library did a nice thing. |
| * The file handle used by the C runtime is the same one |
| * returned by the OS when you call DosOpen(). This means |
| * that you can take an OS HFILE and use it with C file |
| * functions. The only caveat is that you have to call |
| * _setmode() first to initialize some junk. This is |
| * immensely useful because I did not have a clue how to |
| * implement this function otherwise. The windows folks |
| * took the source from the Microsoft C library source, but |
| * IBM wasn't kind enough to ship the source with VAC. |
| * On second thought, the needed function could probably |
| * be gotten from the OS/2 GNU library source, but the |
| * point is now moot. |
| */ |
| struct stat hinfo; |
| PRInt64 s, s2us; |
| |
| _setmode(fd->secret->md.osfd, O_BINARY); |
| if(fstat((int)fd->secret->md.osfd, &hinfo) != NO_ERROR) { |
| _PR_MD_MAP_FSTAT_ERROR(errno); |
| return -1; |
| } |
| |
| if (hinfo.st_mode & S_IFDIR) |
| info->type = PR_FILE_DIRECTORY; |
| else |
| info->type = PR_FILE_FILE; |
| |
| info->size = hinfo.st_size; |
| LL_I2L(s2us, PR_USEC_PER_SEC); |
| LL_I2L(s, hinfo.st_mtime); |
| LL_MUL(s, s, s2us); |
| info->modifyTime = s; |
| LL_I2L(s, hinfo.st_ctime); |
| LL_MUL(s, s, s2us); |
| info->creationTime = s; |
| |
| return 0; |
| } |
| |
| PRInt32 |
| _PR_MD_GETOPENFILEINFO64(const PRFileDesc *fd, PRFileInfo64 *info) |
| { |
| PRFileInfo info32; |
| PRInt32 rv = _PR_MD_GETOPENFILEINFO(fd, &info32); |
| if (0 == rv) |
| { |
| info->type = info32.type; |
| LL_UI2L(info->size,info32.size); |
| |
| info->modifyTime = info32.modifyTime; |
| info->creationTime = info32.creationTime; |
| } |
| |
| if (isWSEB) |
| { |
| APIRET rc ; |
| FILESTATUS3L fstatus; |
| |
| rc = DosQueryFileInfo(fd->secret->md.osfd, FIL_STANDARDL, &fstatus, sizeof(fstatus)); |
| |
| if (NO_ERROR != rc) |
| { |
| _PR_MD_MAP_OPEN_ERROR(rc); |
| return -1; |
| } |
| |
| if (! (fstatus.attrFile & FILE_DIRECTORY)) |
| { |
| info->size = fstatus.cbFile; |
| } |
| } |
| |
| return rv; |
| } |
| |
| |
| PRInt32 |
| _PR_MD_RENAME(const char *from, const char *to) |
| { |
| PRInt32 rc; |
| /* Does this work with dot-relative pathnames? */ |
| if ( (rc = DosMove((char *)from, (char *)to)) == NO_ERROR) { |
| return 0; |
| } else { |
| _PR_MD_MAP_RENAME_ERROR(rc); |
| return -1; |
| } |
| } |
| |
| PRInt32 |
| _PR_MD_ACCESS(const char *name, PRAccessHow how) |
| { |
| PRInt32 rv; |
| switch (how) { |
| case PR_ACCESS_WRITE_OK: |
| rv = access(name, 02); |
| break; |
| case PR_ACCESS_READ_OK: |
| rv = access(name, 04); |
| break; |
| case PR_ACCESS_EXISTS: |
| return access(name, 00); |
| break; |
| default: |
| PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); |
| return -1; |
| } |
| if (rv < 0) |
| _PR_MD_MAP_ACCESS_ERROR(errno); |
| return rv; |
| } |
| |
| PRInt32 |
| _PR_MD_MKDIR(const char *name, PRIntn mode) |
| { |
| PRInt32 rc; |
| /* XXXMB - how to translate the "mode"??? */ |
| if ((rc = DosCreateDir((char *)name, NULL))== NO_ERROR) { |
| return 0; |
| } else { |
| _PR_MD_MAP_MKDIR_ERROR(rc); |
| return -1; |
| } |
| } |
| |
| PRInt32 |
| _PR_MD_RMDIR(const char *name) |
| { |
| PRInt32 rc; |
| if ( (rc = DosDeleteDir((char *)name)) == NO_ERROR) { |
| return 0; |
| } else { |
| _PR_MD_MAP_RMDIR_ERROR(rc); |
| return -1; |
| } |
| } |
| |
| PRStatus |
| _PR_MD_LOCKFILE(PRInt32 f) |
| { |
| PRInt32 rv; |
| FILELOCK lock, unlock; |
| FILELOCKL lockL, unlockL; |
| |
| lock.lOffset = 0; |
| lockL.lOffset = 0; |
| lock.lRange = 0xffffffff; |
| lockL.lRange = 0xffffffffffffffff; |
| unlock.lOffset = 0; |
| unlock.lRange = 0; |
| unlockL.lOffset = 0; |
| unlockL.lRange = 0; |
| |
| /* |
| * loop trying to DosSetFileLocks(), |
| * pause for a few miliseconds when can't get the lock |
| * and try again |
| */ |
| for( rv = FALSE; rv == FALSE; /* do nothing */ ) |
| { |
| if (isWSEB) |
| { |
| rv = myDosSetFileLocksL( (HFILE) f, |
| &unlockL, &lockL, |
| 0, 0); |
| } |
| else |
| { |
| rv = DosSetFileLocks( (HFILE) f, |
| &unlock, &lock, |
| 0, 0); |
| } |
| if ( rv != NO_ERROR ) |
| { |
| DosSleep( 50 ); /* Sleep() a few milisecs and try again. */ |
| } |
| } /* end for() */ |
| return PR_SUCCESS; |
| } /* end _PR_MD_LOCKFILE() */ |
| |
| PRStatus |
| _PR_MD_TLOCKFILE(PRInt32 f) |
| { |
| return _PR_MD_LOCKFILE(f); |
| } /* end _PR_MD_TLOCKFILE() */ |
| |
| |
| PRStatus |
| _PR_MD_UNLOCKFILE(PRInt32 f) |
| { |
| PRInt32 rv; |
| FILELOCK lock, unlock; |
| FILELOCKL lockL, unlockL; |
| |
| lock.lOffset = 0; |
| lockL.lOffset = 0; |
| lock.lRange = 0; |
| lockL.lRange = 0; |
| unlock.lOffset = 0; |
| unlockL.lOffset = 0; |
| unlock.lRange = 0xffffffff; |
| unlockL.lRange = 0xffffffffffffffff; |
| |
| if (isWSEB) |
| { |
| rv = myDosSetFileLocksL( (HFILE) f, |
| &unlockL, &lockL, |
| 0, 0); |
| } |
| else |
| { |
| rv = DosSetFileLocks( (HFILE) f, |
| &unlock, &lock, |
| 0, 0); |
| } |
| |
| if ( rv != NO_ERROR ) |
| { |
| return PR_SUCCESS; |
| } |
| else |
| { |
| return PR_FAILURE; |
| } |
| } /* end _PR_MD_UNLOCKFILE() */ |
| |
| PRStatus |
| _PR_MD_SET_FD_INHERITABLE(PRFileDesc *fd, PRBool inheritable) |
| { |
| APIRET rc = 0; |
| ULONG flags; |
| switch (fd->methods->file_type) |
| { |
| case PR_DESC_PIPE: |
| case PR_DESC_FILE: |
| rc = DosQueryFHState((HFILE)fd->secret->md.osfd, &flags); |
| if (rc != NO_ERROR) { |
| PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); |
| return PR_FAILURE; |
| } |
| |
| if (inheritable) |
| flags &= ~OPEN_FLAGS_NOINHERIT; |
| else |
| flags |= OPEN_FLAGS_NOINHERIT; |
| |
| /* Mask off flags DosSetFHState don't want. */ |
| flags &= (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE | OPEN_FLAGS_NOINHERIT); |
| rc = DosSetFHState((HFILE)fd->secret->md.osfd, flags); |
| if (rc != NO_ERROR) { |
| PR_SetError(PR_UNKNOWN_ERROR, _MD_ERRNO()); |
| return PR_FAILURE; |
| } |
| break; |
| |
| case PR_DESC_LAYERED: |
| /* what to do here? */ |
| PR_SetError(PR_UNKNOWN_ERROR, 87 /*ERROR_INVALID_PARAMETER*/); |
| return PR_FAILURE; |
| |
| case PR_DESC_SOCKET_TCP: |
| case PR_DESC_SOCKET_UDP: |
| /* These are global on OS/2. */ |
| break; |
| } |
| |
| return PR_SUCCESS; |
| } |
| |
| void |
| _PR_MD_INIT_FD_INHERITABLE(PRFileDesc *fd, PRBool imported) |
| { |
| /* XXX this function needs to be implemented */ |
| fd->secret->inheritable = _PR_TRI_UNKNOWN; |
| } |
| |
| void |
| _PR_MD_QUERY_FD_INHERITABLE(PRFileDesc *fd) |
| { |
| /* XXX this function needs to be reviewed */ |
| ULONG flags; |
| |
| PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable); |
| if (DosQueryFHState((HFILE)fd->secret->md.osfd, &flags) == 0) { |
| if (flags & OPEN_FLAGS_NOINHERIT) { |
| fd->secret->inheritable = _PR_TRI_FALSE; |
| } else { |
| fd->secret->inheritable = _PR_TRI_TRUE; |
| } |
| } |
| } |