home *** CD-ROM | disk | FTP | other *** search
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /*
- * The contents of this file are subject to the Netscape Public License
- * Version 1.0 (the "NPL"); you may not use this file except in
- * compliance with the NPL. You may obtain a copy of the NPL at
- * http://www.mozilla.org/NPL/
- *
- * Software distributed under the NPL is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
- * for the specific language governing rights and limitations under the
- * NPL.
- *
- * The Initial Developer of this code under the NPL is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1998 Netscape Communications Corporation. All Rights
- * Reserved.
- */
-
- /* OS2 IO module
- *
- * Assumes synchronous I/O.
- *
- */
-
- #include "primpl.h"
- #include <direct.h>
-
- struct _MDLock _pr_ioq_lock;
-
- PR_IMPLEMENT(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.sem, msecs);
- DosResetEventSem(thread->md.blocked_sema.sem, &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.sem, 0);
- DosResetEventSem(thread->md.blocked_sema.sem, &count);
- PR_ASSERT(rv == NO_ERROR);
- }
- }
- return PR_SUCCESS;
- break;
- default:
- break;
- }
- return PR_FAILURE;
- }
- PR_IMPLEMENT(PRStatus)
- _PR_MD_WAKEUP_WAITER(PRThread *thread)
- {
- if ( _PR_IS_NATIVE_THREAD(thread) )
- {
- if (DosPostEventSem(thread->md.blocked_sema.sem) != 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 = OPEN_ACTION_OPEN_IF_EXISTS;
- PRInt32 rc;
- PRUword actionTaken;
-
- ULONG CurMaxFH = 0;
- LONG ReqCount = 1;
-
- 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)
- flags |= OPEN_ACTION_CREATE_IF_NEW;
- else if (osflags & PR_TRUNCATE){
- flags &= ~OPEN_ACTION_OPEN_IF_EXISTS;
- flags |= OPEN_ACTION_REPLACE_IF_EXISTS;
- }
-
- /* OS/2 sets the Max file handles per process to 20 by default */
- DosSetRelMaxFH(&ReqCount, &CurMaxFH);
-
- 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 != NO_ERROR) {
- _PR_MD_MAP_OPEN_ERROR(rc);
- return -1;
- }
-
- return (PRInt32)file;
- }
-
- PRInt32
- _PR_MD_READ(PRFileDesc *fd, void *buf, PRInt32 len)
- {
- PRUword 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 bytes;
- }
-
- PRInt32
- _PR_MD_WRITE(PRFileDesc *fd, const void *buf, PRInt32 len)
- {
- PRUword bytes;
- int rv;
-
- /* No longer using DosWrite since it doesn't convert \n to \n\r like C runtime does */
- #if 0
- rv = DosWrite((HFILE)fd->secret->md.osfd,
- (PVOID)buf,
- len,
- &bytes);
-
- if (rv != NO_ERROR)
- {
- _PR_MD_MAP_WRITE_ERROR(rv);
- return -1;
- }
- #else
- bytes = write(fd->secret->md.osfd, buf, len);
- if (rv == -1)
- _PR_MD_MAP_WRITE_ERROR(errno);
- #endif
-
- return bytes;
- } /* --- end _PR_MD_WRITE() --- */
-
- PRInt32
- _PR_MD_LSEEK(PRFileDesc *fd, PRInt32 offset, int 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, int whence)
- {
- 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 = hi;
- result.hi = newLocation;
- return result;
- }
-
- 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) (d)->d_entry.achName
-
- 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;
-
- PR_snprintf(filename, CCHMAXPATH, "%s%s%s",
- name, PR_DIRECTORY_SEPARATOR_STR, "*.*");
- FlipSlashes( filename, strlen(filename) );
-
- d->d_hdl = HDIR_CREATE;
-
- rc = DosFindFirst( filename, &d->d_hdl, FILE_DIRECTORY, &(d->d_entry), sizeof(d->d_entry), &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;
-
- 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);
- 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_HIDDEN) && (fileName[0] == '.'))
- 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;
-
- rv = _stat((char*)fn, 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;
-
- 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;
- info->modifyTime.lo = sb.st_mtime;
- info->creationTime.lo = sb.st_ctime;
- }
- }
- return rv;
- }
-
- PRInt32
- _PR_MD_GETFILEINFO64(const char *fn, PRFileInfo64 *info)
- {
- PRFileInfo info32;
- PRInt32 rv = _PR_MD_GETFILEINFO(fn, &info32);
- if (0 == rv)
- {
- info->type = info32.type;
- info->size.lo = info32.size;
- info->modifyTime = info32.modifyTime;
- info->creationTime = info32.creationTime;
- }
- 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;
-
- _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;
- info->modifyTime.lo = hinfo.st_mtime;
- info->creationTime.lo = hinfo.st_ctime;
-
- 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;
- info->size.lo = info32.size;
- info->modifyTime = info32.modifyTime;
- info->creationTime = info32.creationTime;
- }
- 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, PRIntn 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;
- }
- }
-
- PR_IMPLEMENT(PRStatus)
- _PR_MD_LOCKFILE(PRInt32 f)
- {
- PRInt32 rv;
- FILELOCK lock, unlock;
-
- lock.lOffset = 0;
- lock.lRange = 0xffffffff;
- unlock.lOffset = 0;
- unlock.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 */ )
- {
-
- 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() */
-
- PR_IMPLEMENT(PRStatus)
- _PR_MD_TLOCKFILE(PRInt32 f)
- {
- return _PR_MD_LOCKFILE(f);
- } /* end _PR_MD_TLOCKFILE() */
-
-
- PR_IMPLEMENT(PRStatus)
- _PR_MD_UNLOCKFILE(PRInt32 f)
- {
- PRInt32 rv;
- FILELOCK lock, unlock;
-
- lock.lOffset = 0;
- lock.lRange = 0;
- unlock.lOffset = 0;
- unlock.lRange = 0xffffffff;
-
- rv = DosSetFileLocks( (HFILE) f,
- &unlock, &lock,
- 0, 0);
-
- if ( rv != NO_ERROR )
- {
- return PR_SUCCESS;
- }
- else
- {
- return PR_FAILURE;
- }
- } /* end _PR_MD_UNLOCKFILE() */
-
-