Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Firefox/nsprpub/pr/src/md/windows/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 32 kB image not shown  

Quelle  w95io.c   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


/* Windows 95 IO module
 *
 * Assumes synchronous I/O.
 *
 */


#include "primpl.h"
#include <direct.h>
#include <mbstring.h>
#ifdef MOZ_UNICODE
#  include <wchar.h>
#endif /* MOZ_UNICODE */

struct _MDLock _pr_ioq_lock;

/*
 * NSPR-to-NT access right mapping table for files.
 */

static DWORD fileAccessTable[] = {FILE_GENERIC_READ, FILE_GENERIC_WRITE,
                                  FILE_GENERIC_EXECUTE};

/*
 * NSPR-to-NT access right mapping table for directories.
 */

static DWORD dirAccessTable[] = {FILE_GENERIC_READ,
                                 FILE_GENERIC_WRITE | FILE_DELETE_CHILD,
                                 FILE_GENERIC_EXECUTE};

static PRBool IsPrevCharSlash(const char* str, const char* current);

void _PR_MD_INIT_IO() {
  WORD WSAVersion = 0x0101;
  WSADATA WSAData;
  int err;

  err = WSAStartup(WSAVersion, &WSAData);
  PR_ASSERT(0 == err);

#ifdef DEBUG
  /* Doublecheck _pr_filetime_offset's hard-coded value is correct. */
  {
    SYSTEMTIME systime;
    union {
      PRTime prt;
      FILETIME ft;
    } filetime;
    BOOL rv;

    systime.wYear = 1970;
    systime.wMonth = 1;
    /* wDayOfWeek is ignored */
    systime.wDay = 1;
    systime.wHour = 0;
    systime.wMinute = 0;
    systime.wSecond = 0;
    systime.wMilliseconds = 0;

    rv = SystemTimeToFileTime(&systime, &filetime.ft);
    PR_ASSERT(0 != rv);
    PR_ASSERT(filetime.prt == _pr_filetime_offset);
  }
#endif /* DEBUG */

  _PR_NT_InitSids();

  _PR_MD_InitSockets();
}

PRStatus _PR_MD_WAIT(PRThread* thread, PRIntervalTime ticks) {
  DWORD rv;

  PRUint32 msecs = (ticks == PR_INTERVAL_NO_TIMEOUT)
                       ? INFINITE
                       : PR_IntervalToMilliseconds(ticks);
  rv = WaitForSingleObject(thread->md.blocked_sema, msecs);
  switch (rv) {
    case WAIT_OBJECT_0:
      return PR_SUCCESS;
    case WAIT_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 WaitForSingleObject() to clear the semaphore.
           */

          _PR_THREAD_UNLOCK(thread);
          rv = WaitForSingleObject(thread->md.blocked_sema, 0);
          PR_ASSERT(rv == WAIT_OBJECT_0);
        }
      }
      return PR_SUCCESS;
    default:
      return PR_FAILURE;
  }
}
PRStatus _PR_MD_WAKEUP_WAITER(PRThread* thread) {
  if (_PR_IS_NATIVE_THREAD(thread)) {
    if (ReleaseSemaphore(thread->md.blocked_sema, 1, NULL) == FALSE) {
      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 Win95
 *
 *  Mode seems to be passed in as a unix style file permissions argument
 *  as in 0666, in the case of opening the logFile.
 *
 */

PROsfd _PR_MD_OPEN(const char* name, PRIntn osflags, int mode) {
  HANDLE file;
  PRInt32 access = 0;
  PRInt32 flags = 0;
  PRInt32 flag6 = 0;

  if (osflags & PR_SYNC) {
    flag6 = FILE_FLAG_WRITE_THROUGH;
  }

  if (osflags & PR_RDONLY || osflags & PR_RDWR) {
    access |= GENERIC_READ;
  }
  if (osflags & PR_WRONLY || osflags & PR_RDWR) {
    access |= GENERIC_WRITE;
  }

  if (osflags & PR_CREATE_FILE && osflags & PR_EXCL) {
    flags = CREATE_NEW;
  } else if (osflags & PR_CREATE_FILE) {
    if (osflags & PR_TRUNCATE) {
      flags = CREATE_ALWAYS;
    } else {
      flags = OPEN_ALWAYS;
    }
  } else {
    if (osflags & PR_TRUNCATE) {
      flags = TRUNCATE_EXISTING;
    } else {
      flags = OPEN_EXISTING;
    }
  }

  file = CreateFileA(name, access, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                     flags, flag6, NULL);
  if (file == INVALID_HANDLE_VALUE) {
    _PR_MD_MAP_OPEN_ERROR(GetLastError());
    return -1;
  }

  return (PROsfd)file;
}

PROsfd _PR_MD_OPEN_FILE(const char* name, PRIntn osflags, int mode) {
  HANDLE file;
  PRInt32 access = 0;
  PRInt32 flags = 0;
  PRInt32 flag6 = 0;
  SECURITY_ATTRIBUTES sa;
  LPSECURITY_ATTRIBUTES lpSA = NULL;
  PSECURITY_DESCRIPTOR pSD = NULL;
  PACL pACL = NULL;

  if (osflags & PR_CREATE_FILE) {
    if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable, &pSD, &pACL) ==
        PR_SUCCESS) {
      sa.nLength = sizeof(sa);
      sa.lpSecurityDescriptor = pSD;
      sa.bInheritHandle = FALSE;
      lpSA = &sa;
    }
  }

  if (osflags & PR_SYNC) {
    flag6 = FILE_FLAG_WRITE_THROUGH;
  }

  if (osflags & PR_RDONLY || osflags & PR_RDWR) {
    access |= GENERIC_READ;
  }
  if (osflags & PR_WRONLY || osflags & PR_RDWR) {
    access |= GENERIC_WRITE;
  }

  if (osflags & PR_CREATE_FILE && osflags & PR_EXCL) {
    flags = CREATE_NEW;
  } else if (osflags & PR_CREATE_FILE) {
    if (osflags & PR_TRUNCATE) {
      flags = CREATE_ALWAYS;
    } else {
      flags = OPEN_ALWAYS;
    }
  } else {
    if (osflags & PR_TRUNCATE) {
      flags = TRUNCATE_EXISTING;
    } else {
      flags = OPEN_EXISTING;
    }
  }

  file = CreateFileA(name, access, FILE_SHARE_READ | FILE_SHARE_WRITE, lpSA,
                     flags, flag6, NULL);
  if (lpSA != NULL) {
    _PR_NT_FreeSecurityDescriptorACL(pSD, pACL);
  }
  if (file == INVALID_HANDLE_VALUE) {
    _PR_MD_MAP_OPEN_ERROR(GetLastError());
    return -1;
  }

  return (PROsfd)file;
}

PRInt32 _PR_MD_READ(PRFileDesc* fd, void* buf, PRInt32 len) {
  PRUint32 bytes;
  int rv, err;

  rv = ReadFile((HANDLE)fd->secret->md.osfd, (LPVOID)buf, len, &bytes, NULL);

  if (rv == 0) {
    err = GetLastError();
    /* ERROR_HANDLE_EOF can only be returned by async io */
    PR_ASSERT(err != ERROR_HANDLE_EOF);
    if (err == ERROR_BROKEN_PIPE) {
      return 0;
    } else {
      _PR_MD_MAP_READ_ERROR(err);
      return -1;
    }
  }
  return bytes;
}

PRInt32 _PR_MD_WRITE(PRFileDesc* fd, const void* buf, PRInt32 len) {
  PROsfd f = fd->secret->md.osfd;
  PRInt32 bytes;
  int rv;

  rv = WriteFile((HANDLE)f, buf, len, &bytes, NULL);

  if (rv == 0) {
    _PR_MD_MAP_WRITE_ERROR(GetLastError());
    return -1;
  }
  return bytes;
/* --- end _PR_MD_WRITE() --- */

PROffset32 _PR_MD_LSEEK(PRFileDesc* fd, PROffset32 offset,
                        PRSeekWhence whence) {
  DWORD moveMethod;
  PROffset32 rv;

  switch (whence) {
    case PR_SEEK_SET:
      moveMethod = FILE_BEGIN;
      break;
    case PR_SEEK_CUR:
      moveMethod = FILE_CURRENT;
      break;
    case PR_SEEK_END:
      moveMethod = FILE_END;
      break;
    default:
      PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
      return -1;
  }

  rv = SetFilePointer((HANDLE)fd->secret->md.osfd, offset, NULL, moveMethod);

  /*
   * If the lpDistanceToMoveHigh argument (third argument) is
   * NULL, SetFilePointer returns 0xffffffff on failure.
   */

  if (-1 == rv) {
    _PR_MD_MAP_LSEEK_ERROR(GetLastError());
  }
  return rv;
}

PROffset64 _PR_MD_LSEEK64(PRFileDesc* fd, PROffset64 offset,
                          PRSeekWhence whence) {
  DWORD moveMethod;
  LARGE_INTEGER li;
  DWORD err;

  switch (whence) {
    case PR_SEEK_SET:
      moveMethod = FILE_BEGIN;
      break;
    case PR_SEEK_CUR:
      moveMethod = FILE_CURRENT;
      break;
    case PR_SEEK_END:
      moveMethod = FILE_END;
      break;
    default:
      PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
      return -1;
  }

  li.QuadPart = offset;
  li.LowPart = SetFilePointer((HANDLE)fd->secret->md.osfd, li.LowPart,
                              &li.HighPart, moveMethod);

  if (0xffffffff == li.LowPart && (err = GetLastError()) != NO_ERROR) {
    _PR_MD_MAP_LSEEK_ERROR(err);
    li.QuadPart = -1;
  }
  return li.QuadPart;
}

/*
 * This is documented to succeed on read-only files, but Win32's
 * FlushFileBuffers functions fails with "access denied" in such a
 * case.  So we only signal an error if the error is *not* "access
 * denied".
 */

PRInt32 _PR_MD_FSYNC(PRFileDesc* fd) {
  /*
   * From the documentation:
   *
   *     On Windows NT, the function FlushFileBuffers fails if hFile
   *     is a handle to console output. That is because console
   *     output is not buffered. The function returns FALSE, and
   *     GetLastError returns ERROR_INVALID_HANDLE.
   *
   * On the other hand, on Win95, it returns without error.  I cannot
   * assume that 0, 1, and 2 are console, because if someone closes
   * System.out and then opens a file, they might get file descriptor
   * 1.  An error on *that* version of 1 should be reported, whereas
   * an error on System.out (which was the original 1) should be
   * ignored.  So I use isatty() to ensure that such an error was due
   * to this bogosity, and if it was, I ignore the error.
   */


  BOOL ok = FlushFileBuffers((HANDLE)fd->secret->md.osfd);

  if (!ok) {
    DWORD err = GetLastError();
    if (err != ERROR_ACCESS_DENIED) {  // from winerror.h
      _PR_MD_MAP_FSYNC_ERROR(err);
      return -1;
    }
  }
  return 0;
}

PRInt32 _MD_CloseFile(PROsfd osfd) {
  PRInt32 rv;

  rv = (CloseHandle((HANDLE)osfd)) ? 0 : -1;
  if (rv == -1) {
    _PR_MD_MAP_CLOSE_ERROR(GetLastError());
  }
  return rv;
}

/* --- DIR IO ------------------------------------------------------------ */
#define GetFileFromDIR(d) (d)->d_entry.cFileName
#define FileIsHidden(d) ((d)->d_entry.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)

static void FlipSlashes(char* cp, size_t len) {
  while (len-- > 0) {
    if (cp[0] == '/') {
      cp[0] = PR_DIRECTORY_SEPARATOR;
    }
    cp = _mbsinc(cp);
  }
/* end FlipSlashes() */

/*
**
** Local implementations of standard Unix RTL functions which are not provided
** by the VC RTL.
**
*/


PRInt32 _PR_MD_CLOSE_DIR(_MDDir* d) {
  if (d) {
    if (FindClose(d->d_hdl)) {
      d->magic = (PRUint32)-1;
      return 0;
    } else {
      _PR_MD_MAP_CLOSEDIR_ERROR(GetLastError());
      return -1;
    }
  }
  PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  return -1;
}

PRStatus _PR_MD_OPEN_DIR(_MDDir* d, const char* name) {
  char filename[MAX_PATH];
  size_t len;

  len = strlen(name);
  /* Need 5 bytes for \*.* and the trailing null byte. */
  if (len + 5 > MAX_PATH) {
    PR_SetError(PR_NAME_TOO_LONG_ERROR, 0);
    return PR_FAILURE;
  }
  strcpy(filename, name);

  /*
   * If 'name' ends in a slash or backslash, do not append
   * another backslash.
   */

  if (IsPrevCharSlash(filename, filename + len)) {
    len--;
  }
  strcpy(&filename[len], "\\*.*");
  FlipSlashes(filename, strlen(filename));

  d->d_hdl = FindFirstFileA(filename, &(d->d_entry));
  if (d->d_hdl == INVALID_HANDLE_VALUE) {
    _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
    return PR_FAILURE;
  }
  d->firstEntry = PR_TRUE;
  d->magic = _MD_MAGIC_DIR;
  return PR_SUCCESS;
}

char* _PR_MD_READ_DIR(_MDDir* d, PRIntn flags) {
  PRInt32 err;
  BOOL rv;
  char* fileName;

  if (d) {
    while (1) {
      if (d->firstEntry) {
        d->firstEntry = PR_FALSE;
        rv = 1;
      } else {
        rv = FindNextFileA(d->d_hdl, &(d->d_entry));
      }
      if (rv == 0) {
        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;
      }
      if ((flags & PR_SKIP_HIDDEN) && FileIsHidden(d)) {
        continue;
      }
      return fileName;
    }
    err = GetLastError();
    PR_ASSERT(NO_ERROR != err);
    _PR_MD_MAP_READDIR_ERROR(err);
    return NULL;
  }
  PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  return NULL;
}

PRInt32 _PR_MD_DELETE(const char* name) {
  if (DeleteFileA(name)) {
    return 0;
  } else {
    _PR_MD_MAP_DELETE_ERROR(GetLastError());
    return -1;
  }
}

void _PR_FileTimeToPRTime(const FILETIME* filetime, PRTime* prtm) {
  PR_ASSERT(sizeof(FILETIME) == sizeof(PRTime));
  CopyMemory(prtm, filetime, sizeof(PRTime));
#if defined(__MINGW32__)
  *prtm = (*prtm - _pr_filetime_offset) / 10LL;
#else
  *prtm = (*prtm - _pr_filetime_offset) / 10i64;
#endif

#ifdef DEBUG
  /* Doublecheck our calculation. */
  {
    SYSTEMTIME systime;
    PRExplodedTime etm;
    PRTime cmp; /* for comparison */
    BOOL rv;

    rv = FileTimeToSystemTime(filetime, &systime);
    PR_ASSERT(0 != rv);

    /*
     * PR_ImplodeTime ignores wday and yday.
     */

    etm.tm_usec = systime.wMilliseconds * PR_USEC_PER_MSEC;
    etm.tm_sec = systime.wSecond;
    etm.tm_min = systime.wMinute;
    etm.tm_hour = systime.wHour;
    etm.tm_mday = systime.wDay;
    etm.tm_month = systime.wMonth - 1;
    etm.tm_year = systime.wYear;
    /*
     * It is not well-documented what time zone the FILETIME's
     * are in.  WIN32_FIND_DATA is documented to be in UTC (GMT).
     * But BY_HANDLE_FILE_INFORMATION is unclear about this.
     * By our best judgement, we assume that FILETIME is in UTC.
     */

    etm.tm_params.tp_gmt_offset = 0;
    etm.tm_params.tp_dst_offset = 0;
    cmp = PR_ImplodeTime(&etm);

    /*
     * SYSTEMTIME is in milliseconds precision, so we convert PRTime's
     * microseconds to milliseconds before doing the comparison.
     */

    PR_ASSERT((cmp / PR_USEC_PER_MSEC) == (*prtm / PR_USEC_PER_MSEC));
  }
#endif /* DEBUG */
}

PRInt32 _PR_MD_STAT(const char* fn, struct stat* info) {
  PRInt32 rv;

  rv = _stat(fn, (struct _stat*)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.
     */


    size_t len = strlen(fn);
    if (len > 0 && len <= _MAX_PATH && IsPrevCharSlash(fn, fn + len)) {
      char newfn[_MAX_PATH + 1];

      strcpy(newfn, fn);
      newfn[len - 1] = '\0';
      rv = _stat(newfn, (struct _stat*)info);
    }
  }

  if (-1 == rv) {
    _PR_MD_MAP_STAT_ERROR(errno);
  }
  return rv;
}

#define _PR_IS_SLASH(ch) ((ch) == '/' || (ch) == '\\')

static PRBool IsPrevCharSlash(const char* str, const char* current) {
  const char* prev;

  if (str >= current) {
    return PR_FALSE;
  }
  prev = _mbsdec(str, current);
  return (prev == current - 1) && _PR_IS_SLASH(*prev);
}

/*
 * IsRootDirectory --
 *
 * Return PR_TRUE if the pathname 'fn' is a valid root directory,
 * else return PR_FALSE.  The char buffer pointed to by 'fn' must
 * be writable.  During the execution of this function, the contents
 * of the buffer pointed to by 'fn' may be modified, but on return
 * the original contents will be restored.  'buflen' is the size of
 * the buffer pointed to by 'fn'.
 *
 * Root directories come in three formats:
 * 1. / or \, meaning the root directory of the current drive.
 * 2. C:/ or C:\, where C is a drive letter.
 * 3. \\<server name>\<share point name>\ or
 *    \\<server name>\<share point name>, meaning the root directory
 *    of a UNC (Universal Naming Convention) name.
 */


static PRBool IsRootDirectory(char* fn, size_t buflen) {
  char* p;
  PRBool slashAdded = PR_FALSE;
  PRBool rv = PR_FALSE;

  if (_PR_IS_SLASH(fn[0]) && fn[1] == '\0') {
    return PR_TRUE;
  }

  if (isalpha(fn[0]) && fn[1] == ':' && _PR_IS_SLASH(fn[2]) && fn[3] == '\0') {
    rv = GetDriveType(fn) > 1 ? PR_TRUE : PR_FALSE;
    return rv;
  }

  /* The UNC root directory */

  if (_PR_IS_SLASH(fn[0]) && _PR_IS_SLASH(fn[1])) {
    /* The 'server' part should have at least one character. */
    p = &fn[2];
    if (*p == '\0' || _PR_IS_SLASH(*p)) {
      return PR_FALSE;
    }

    /* look for the next slash */
    do {
      p = _mbsinc(p);
    } while (*p != '\0' && !_PR_IS_SLASH(*p));
    if (*p == '\0') {
      return PR_FALSE;
    }

    /* The 'share' part should have at least one character. */
    p++;
    if (*p == '\0' || _PR_IS_SLASH(*p)) {
      return PR_FALSE;
    }

    /* look for the final slash */
    do {
      p = _mbsinc(p);
    } while (*p != '\0' && !_PR_IS_SLASH(*p));
    if (_PR_IS_SLASH(*p) && p[1] != '\0') {
      return PR_FALSE;
    }
    if (*p == '\0') {
      /*
       * GetDriveType() doesn't work correctly if the
       * path is of the form \\server\share, so we add
       * a final slash temporarily.
       */

      if ((p + 1) < (fn + buflen)) {
        *p++ = '\\';
        *p = '\0';
        slashAdded = PR_TRUE;
      } else {
        return PR_FALSE; /* name too long */
      }
    }
    rv = GetDriveType(fn) > 1 ? PR_TRUE : PR_FALSE;
    /* restore the 'fn' buffer */
    if (slashAdded) {
      *--p = '\0';
    }
  }
  return rv;
}

PRInt32 _PR_MD_GETFILEINFO64(const char* fn, PRFileInfo64* info) {
  WIN32_FILE_ATTRIBUTE_DATA findFileData;
  BOOL rv;

  if (NULL == fn || '\0' == *fn) {
    PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
    return -1;
  }

  rv = GetFileAttributesEx(fn, GetFileExInfoStandard, &findFileData);
  if (!rv) {
    _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
    return -1;
  }

  if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
    info->type = PR_FILE_DIRECTORY;
  } else {
    info->type = PR_FILE_FILE;
  }

  info->size = findFileData.nFileSizeHigh;
  info->size = (info->size << 32) + findFileData.nFileSizeLow;

  _PR_FileTimeToPRTime(&findFileData.ftLastWriteTime, &info->modifyTime);

  if (0 == findFileData.ftCreationTime.dwLowDateTime &&
      0 == findFileData.ftCreationTime.dwHighDateTime) {
    info->creationTime = info->modifyTime;
  } else {
    _PR_FileTimeToPRTime(&findFileData.ftCreationTime, &info->creationTime);
  }

  return 0;
}

PRInt32 _PR_MD_GETFILEINFO(const char* fn, PRFileInfo* info) {
  PRFileInfo64 info64;
  PRInt32 rv = _PR_MD_GETFILEINFO64(fn, &info64);
  if (0 == rv) {
    info->type = info64.type;
    info->size = (PRUint32)info64.size;
    info->modifyTime = info64.modifyTime;
    info->creationTime = info64.creationTime;
  }
  return rv;
}

PRInt32 _PR_MD_GETOPENFILEINFO64(const PRFileDesc* fd, PRFileInfo64* info) {
  int rv;

  BY_HANDLE_FILE_INFORMATION hinfo;

  rv = GetFileInformationByHandle((HANDLE)fd->secret->md.osfd, &hinfo);
  if (rv == FALSE) {
    _PR_MD_MAP_FSTAT_ERROR(GetLastError());
    return -1;
  }

  if (hinfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
    info->type = PR_FILE_DIRECTORY;
  } else {
    info->type = PR_FILE_FILE;
  }

  info->size = hinfo.nFileSizeHigh;
  info->size = (info->size << 32) + hinfo.nFileSizeLow;

  _PR_FileTimeToPRTime(&hinfo.ftLastWriteTime, &(info->modifyTime));
  _PR_FileTimeToPRTime(&hinfo.ftCreationTime, &(info->creationTime));

  return 0;
}

PRInt32 _PR_MD_GETOPENFILEINFO(const PRFileDesc* fd, PRFileInfo* info) {
  PRFileInfo64 info64;
  int rv = _PR_MD_GETOPENFILEINFO64(fd, &info64);
  if (0 == rv) {
    info->type = info64.type;
    info->modifyTime = info64.modifyTime;
    info->creationTime = info64.creationTime;
    LL_L2I(info->size, info64.size);
  }
  return rv;
}

PRStatus _PR_MD_SET_FD_INHERITABLE(PRFileDesc* fd, PRBool inheritable) {
  BOOL rv;

  /*
   * The SetHandleInformation function fails with the
   * ERROR_CALL_NOT_IMPLEMENTED error on Win95.
   */

  rv = SetHandleInformation((HANDLE)fd->secret->md.osfd, HANDLE_FLAG_INHERIT,
                            inheritable ? HANDLE_FLAG_INHERIT : 0);
  if (0 == rv) {
    _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
    return PR_FAILURE;
  }
  return PR_SUCCESS;
}

void _PR_MD_INIT_FD_INHERITABLE(PRFileDesc* fd, PRBool imported) {
  if (imported) {
    fd->secret->inheritable = _PR_TRI_UNKNOWN;
  } else {
    fd->secret->inheritable = _PR_TRI_FALSE;
  }
}

void _PR_MD_QUERY_FD_INHERITABLE(PRFileDesc* fd) {
  DWORD flags;

  PR_ASSERT(_PR_TRI_UNKNOWN == fd->secret->inheritable);
  if (GetHandleInformation((HANDLE)fd->secret->md.osfd, &flags)) {
    if (flags & HANDLE_FLAG_INHERIT) {
      fd->secret->inheritable = _PR_TRI_TRUE;
    } else {
      fd->secret->inheritable = _PR_TRI_FALSE;
    }
  }
}

PRInt32 _PR_MD_RENAME(const char* from, const char* to) {
  /* Does this work with dot-relative pathnames? */
  if (MoveFileA(from, to)) {
    return 0;
  } else {
    _PR_MD_MAP_RENAME_ERROR(GetLastError());
    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) {
  /* XXXMB - how to translate the "mode"??? */
  if (CreateDirectoryA(name, NULL)) {
    return 0;
  } else {
    _PR_MD_MAP_MKDIR_ERROR(GetLastError());
    return -1;
  }
}

PRInt32 _PR_MD_MAKE_DIR(const char* name, PRIntn mode) {
  BOOL rv;
  SECURITY_ATTRIBUTES sa;
  LPSECURITY_ATTRIBUTES lpSA = NULL;
  PSECURITY_DESCRIPTOR pSD = NULL;
  PACL pACL = NULL;

  if (_PR_NT_MakeSecurityDescriptorACL(mode, dirAccessTable, &pSD, &pACL) ==
      PR_SUCCESS) {
    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = pSD;
    sa.bInheritHandle = FALSE;
    lpSA = &sa;
  }
  rv = CreateDirectoryA(name, lpSA);
  if (lpSA != NULL) {
    _PR_NT_FreeSecurityDescriptorACL(pSD, pACL);
  }
  if (rv) {
    return 0;
  } else {
    _PR_MD_MAP_MKDIR_ERROR(GetLastError());
    return -1;
  }
}

PRInt32 _PR_MD_RMDIR(const char* name) {
  if (RemoveDirectoryA(name)) {
    return 0;
  } else {
    _PR_MD_MAP_RMDIR_ERROR(GetLastError());
    return -1;
  }
}

PRStatus _PR_MD_LOCKFILE(PROsfd f) {
  PRStatus rc = PR_SUCCESS;
  DWORD rv;

  rv = LockFile((HANDLE)f, 0l, 0l, 0x0l, 0xffffffffl);
  if (rv == 0) {
    DWORD err = GetLastError();
    _PR_MD_MAP_DEFAULT_ERROR(err);
    PR_LOG(_pr_io_lm, PR_LOG_ERROR,
           ("_PR_MD_LOCKFILE() failed. Error: %d", err));
    rc = PR_FAILURE;
  }

  return rc;
/* end _PR_MD_LOCKFILE() */

PRStatus _PR_MD_TLOCKFILE(PROsfd f) {
  PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
  return PR_FAILURE;
/* end _PR_MD_TLOCKFILE() */

PRStatus _PR_MD_UNLOCKFILE(PROsfd f) {
  PRInt32 rv;

  rv = UnlockFile((HANDLE)f, 0l, 0l, 0x0l, 0xffffffffl);

  if (rv) {
    return PR_SUCCESS;
  } else {
    _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
    return PR_FAILURE;
  }
/* end _PR_MD_UNLOCKFILE() */

PRInt32 _PR_MD_PIPEAVAILABLE(PRFileDesc* fd) {
  if (NULL == fd) {
    PR_SetError(PR_BAD_DESCRIPTOR_ERROR, 0);
  } else {
    PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
  }
  return -1;
}

#ifdef MOZ_UNICODE

typedef HANDLE(WINAPI* CreateFileWFn)(LPCWSTR, DWORD, DWORD,
                                      LPSECURITY_ATTRIBUTES, DWORD, DWORD,
                                      HANDLE);
static CreateFileWFn createFileW = CreateFileW;
typedef HANDLE(WINAPI* FindFirstFileWFn)(LPCWSTR, LPWIN32_FIND_DATAW);
static FindFirstFileWFn findFirstFileW = FindFirstFileW;
typedef BOOL(WINAPI* FindNextFileWFn)(HANDLE, LPWIN32_FIND_DATAW);
static FindNextFileWFn findNextFileW = FindNextFileW;
typedef DWORD(WINAPI* GetFullPathNameWFn)(LPCWSTR, DWORD, LPWSTR, LPWSTR*);
static GetFullPathNameWFn getFullPathNameW = GetFullPathNameW;
typedef UINT(WINAPI* GetDriveTypeWFn)(LPCWSTR);
static GetDriveTypeWFn getDriveTypeW = GetDriveTypeW;

#endif /* MOZ_UNICODE */

#ifdef MOZ_UNICODE

/* ================ UTF16 Interfaces ================================ */
static void FlipSlashesW(PRUnichar* cp, size_t len) {
  while (len-- > 0) {
    if (cp[0] == L'/') {
      cp[0] = L'\\';
    }
    cp++;
  }
/* end FlipSlashesW() */

PROsfd _PR_MD_OPEN_FILE_UTF16(const PRUnichar* name, PRIntn osflags, int mode) {
  HANDLE file;
  PRInt32 access = 0;
  PRInt32 flags = 0;
  PRInt32 flag6 = 0;
  SECURITY_ATTRIBUTES sa;
  LPSECURITY_ATTRIBUTES lpSA = NULL;
  PSECURITY_DESCRIPTOR pSD = NULL;
  PACL pACL = NULL;

  if (osflags & PR_CREATE_FILE) {
    if (_PR_NT_MakeSecurityDescriptorACL(mode, fileAccessTable, &pSD, &pACL) ==
        PR_SUCCESS) {
      sa.nLength = sizeof(sa);
      sa.lpSecurityDescriptor = pSD;
      sa.bInheritHandle = FALSE;
      lpSA = &sa;
    }
  }

  if (osflags & PR_SYNC) {
    flag6 = FILE_FLAG_WRITE_THROUGH;
  }

  if (osflags & PR_RDONLY || osflags & PR_RDWR) {
    access |= GENERIC_READ;
  }
  if (osflags & PR_WRONLY || osflags & PR_RDWR) {
    access |= GENERIC_WRITE;
  }

  if (osflags & PR_CREATE_FILE && osflags & PR_EXCL) {
    flags = CREATE_NEW;
  } else if (osflags & PR_CREATE_FILE) {
    if (osflags & PR_TRUNCATE) {
      flags = CREATE_ALWAYS;
    } else {
      flags = OPEN_ALWAYS;
    }
  } else {
    if (osflags & PR_TRUNCATE) {
      flags = TRUNCATE_EXISTING;
    } else {
      flags = OPEN_EXISTING;
    }
  }

  file = createFileW(name, access, FILE_SHARE_READ | FILE_SHARE_WRITE, lpSA,
                     flags, flag6, NULL);
  if (lpSA != NULL) {
    _PR_NT_FreeSecurityDescriptorACL(pSD, pACL);
  }
  if (file == INVALID_HANDLE_VALUE) {
    _PR_MD_MAP_OPEN_ERROR(GetLastError());
    return -1;
  }

  return (PROsfd)file;
}

PRStatus _PR_MD_OPEN_DIR_UTF16(_MDDirUTF16* d, const PRUnichar* name) {
  PRUnichar filename[MAX_PATH];
  int len;

  len = wcslen(name);
  /* Need 5 bytes for \*.* and the trailing null byte. */
  if (len + 5 > MAX_PATH) {
    PR_SetError(PR_NAME_TOO_LONG_ERROR, 0);
    return PR_FAILURE;
  }
  wcscpy(filename, name);

  /*
   * If 'name' ends in a slash or backslash, do not append
   * another backslash.
   */

  if (filename[len - 1] == L'/' || filename[len - 1] == L'\\') {
    len--;
  }
  wcscpy(&filename[len], L"\\*.*");
  FlipSlashesW(filename, wcslen(filename));

  d->d_hdl = findFirstFileW(filename, &(d->d_entry));
  if (d->d_hdl == INVALID_HANDLE_VALUE) {
    _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
    return PR_FAILURE;
  }
  d->firstEntry = PR_TRUE;
  d->magic = _MD_MAGIC_DIR;
  return PR_SUCCESS;
}

PRUnichar* _PR_MD_READ_DIR_UTF16(_MDDirUTF16* d, PRIntn flags) {
  PRInt32 err;
  BOOL rv;
  PRUnichar* fileName;

  if (d) {
    while (1) {
      if (d->firstEntry) {
        d->firstEntry = PR_FALSE;
        rv = 1;
      } else {
        rv = findNextFileW(d->d_hdl, &(d->d_entry));
      }
      if (rv == 0) {
        break;
      }
      fileName = GetFileFromDIR(d);
      if ((flags & PR_SKIP_DOT) && (fileName[0] == L'.') &&
          (fileName[1] == L'\0')) {
        continue;
      }
      if ((flags & PR_SKIP_DOT_DOT) && (fileName[0] == L'.') &&
          (fileName[1] == L'.') && (fileName[2] == L'\0')) {
        continue;
      }
      if ((flags & PR_SKIP_HIDDEN) && FileIsHidden(d)) {
        continue;
      }
      return fileName;
    }
    err = GetLastError();
    PR_ASSERT(NO_ERROR != err);
    _PR_MD_MAP_READDIR_ERROR(err);
    return NULL;
  }
  PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  return NULL;
}

PRInt32 _PR_MD_CLOSE_DIR_UTF16(_MDDirUTF16* d) {
  if (d) {
    if (FindClose(d->d_hdl)) {
      d->magic = (PRUint32)-1;
      return 0;
    } else {
      _PR_MD_MAP_CLOSEDIR_ERROR(GetLastError());
      return -1;
    }
  }
  PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
  return -1;
}

#  define _PR_IS_W_SLASH(ch) ((ch) == L'/' || (ch) == L'\\')

/*
 * IsRootDirectoryW --
 *
 * Return PR_TRUE if the pathname 'fn' is a valid root directory,
 * else return PR_FALSE.  The PRUnichar buffer pointed to by 'fn' must
 * be writable.  During the execution of this function, the contents
 * of the buffer pointed to by 'fn' may be modified, but on return
 * the original contents will be restored.  'buflen' is the size of
 * the buffer pointed to by 'fn', in PRUnichars.
 *
 * Root directories come in three formats:
 * 1. / or \, meaning the root directory of the current drive.
 * 2. C:/ or C:\, where C is a drive letter.
 * 3. \\<server name>\<share point name>\ or
 *    \\<server name>\<share point name>, meaning the root directory
 *    of a UNC (Universal Naming Convention) name.
 */


static PRBool IsRootDirectoryW(PRUnichar* fn, size_t buflen) {
  PRUnichar* p;
  PRBool slashAdded = PR_FALSE;
  PRBool rv = PR_FALSE;

  if (_PR_IS_W_SLASH(fn[0]) && fn[1] == L'\0') {
    return PR_TRUE;
  }

  if (iswalpha(fn[0]) && fn[1] == L':' && _PR_IS_W_SLASH(fn[2]) &&
      fn[3] == L'\0') {
    rv = getDriveTypeW(fn) > 1 ? PR_TRUE : PR_FALSE;
    return rv;
  }

  /* The UNC root directory */

  if (_PR_IS_W_SLASH(fn[0]) && _PR_IS_W_SLASH(fn[1])) {
    /* The 'server' part should have at least one character. */
    p = &fn[2];
    if (*p == L'\0' || _PR_IS_W_SLASH(*p)) {
      return PR_FALSE;
    }

    /* look for the next slash */
    do {
      p++;
    } while (*p != L'\0' && !_PR_IS_W_SLASH(*p));
    if (*p == L'\0') {
      return PR_FALSE;
    }

    /* The 'share' part should have at least one character. */
    p++;
    if (*p == L'\0' || _PR_IS_W_SLASH(*p)) {
      return PR_FALSE;
    }

    /* look for the final slash */
    do {
      p++;
    } while (*p != L'\0' && !_PR_IS_W_SLASH(*p));
    if (_PR_IS_W_SLASH(*p) && p[1] != L'\0') {
      return PR_FALSE;
    }
    if (*p == L'\0') {
      /*
       * GetDriveType() doesn't work correctly if the
       * path is of the form \\server\share, so we add
       * a final slash temporarily.
       */

      if ((p + 1) < (fn + buflen)) {
        *p++ = L'\\';
        *p = L'\0';
        slashAdded = PR_TRUE;
      } else {
        return PR_FALSE; /* name too long */
      }
    }
    rv = getDriveTypeW(fn) > 1 ? PR_TRUE : PR_FALSE;
    /* restore the 'fn' buffer */
    if (slashAdded) {
      *--p = L'\0';
    }
  }
  return rv;
}

PRInt32 _PR_MD_GETFILEINFO64_UTF16(const PRUnichar* fn, PRFileInfo64* info) {
  HANDLE hFindFile;
  WIN32_FIND_DATAW findFileData;
  PRUnichar pathbuf[MAX_PATH + 1];

  if (NULL == fn || L'\0' == *fn) {
    PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
    return -1;
  }

  /*
   * FindFirstFile() expands wildcard characters.  So
   * we make sure the pathname contains no wildcard.
   */

  if (NULL != wcspbrk(fn, L"?*")) {
    PR_SetError(PR_FILE_NOT_FOUND_ERROR, 0);
    return -1;
  }

  hFindFile = findFirstFileW(fn, &findFileData);
  if (INVALID_HANDLE_VALUE == hFindFile) {
    DWORD len;
    PRUnichar* filePart;

    /*
     * FindFirstFile() does not work correctly on root directories.
     * It also doesn't work correctly on a pathname that ends in a
     * slash.  So we first check to see if the pathname specifies a
     * root directory.  If not, and if the pathname ends in a slash,
     * we remove the final slash and try again.
     */


    /*
     * If the pathname does not contain ., \, and /, it cannot be
     * a root directory or a pathname that ends in a slash.
     */

    if (NULL == wcspbrk(fn, L".\\/")) {
      _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
      return -1;
    }
    len = getFullPathNameW(fn, sizeof(pathbuf) / sizeof(pathbuf[0]), pathbuf,
                           &filePart);
    if (0 == len) {
      _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
      return -1;
    }
    if (len > sizeof(pathbuf) / sizeof(pathbuf[0])) {
      PR_SetError(PR_NAME_TOO_LONG_ERROR, 0);
      return -1;
    }
    if (IsRootDirectoryW(pathbuf, sizeof(pathbuf) / sizeof(pathbuf[0]))) {
      info->type = PR_FILE_DIRECTORY;
      info->size = 0;
      /*
       * These timestamps don't make sense for root directories.
       */

      info->modifyTime = 0;
      info->creationTime = 0;
      return 0;
    }
    if (!_PR_IS_W_SLASH(pathbuf[len - 1])) {
      _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
      return -1;
    } else {
      pathbuf[len - 1] = L'\0';
      hFindFile = findFirstFileW(pathbuf, &findFileData);
      if (INVALID_HANDLE_VALUE == hFindFile) {
        _PR_MD_MAP_OPENDIR_ERROR(GetLastError());
        return -1;
      }
    }
  }

  FindClose(hFindFile);

  if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
    info->type = PR_FILE_DIRECTORY;
  } else {
    info->type = PR_FILE_FILE;
  }

  info->size = findFileData.nFileSizeHigh;
  info->size = (info->size << 32) + findFileData.nFileSizeLow;

  _PR_FileTimeToPRTime(&findFileData.ftLastWriteTime, &info->modifyTime);

  if (0 == findFileData.ftCreationTime.dwLowDateTime &&
      0 == findFileData.ftCreationTime.dwHighDateTime) {
    info->creationTime = info->modifyTime;
  } else {
    _PR_FileTimeToPRTime(&findFileData.ftCreationTime, &info->creationTime);
  }

  return 0;
}
/* ================ end of UTF16 Interfaces ================================ */
#endif /* MOZ_UNICODE */

Messung V0.5
C=96 H=92 G=93

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.