📄 osutil.cxx
字号:
/*
* osutil.cxx
*
* Operating System classes implementation
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (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 Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Revision: 19008 $
* $Author: rjongbloed $
* $Date: 2007-11-29 09:17:41 +0000 (Thu, 29 Nov 2007) $
*/
#define _OSUTIL_CXX
#pragma implementation "timer.h"
#pragma implementation "pdirect.h"
#pragma implementation "file.h"
#pragma implementation "textfile.h"
#pragma implementation "conchan.h"
#pragma implementation "ptime.h"
#pragma implementation "timeint.h"
#pragma implementation "filepath.h"
#pragma implementation "lists.h"
#pragma implementation "pstring.h"
#pragma implementation "dict.h"
#pragma implementation "array.h"
#pragma implementation "object.h"
#pragma implementation "contain.h"
#if defined(P_LINUX)
#ifndef _REENTRANT
#define _REENTRANT
#endif
#elif defined(P_SOLARIS)
#define _POSIX_PTHREAD_SEMANTICS
#endif
#include <ptlib.h>
#include <fcntl.h>
#ifdef P_VXWORKS
#include <sys/times.h>
#else
#include <time.h>
#include <sys/time.h>
#endif
#include <ctype.h>
#if defined(P_LINUX)
#include <mntent.h>
#include <sys/vfs.h>
#if (__GNUC_MINOR__ < 7 && __GNUC__ < 3)
#include <localeinfo.h>
#else
#define P_USE_LANGINFO
#endif
#elif defined(P_FREEBSD) || defined(P_OPENBSD) || defined(P_NETBSD) || defined(P_MACOSX) || defined(P_MACOS)
#define P_USE_STRFTIME
#include <sys/param.h>
#include <sys/mount.h>
#elif defined(P_HPUX9)
#define P_USE_LANGINFO
#elif defined(P_AIX)
#define P_USE_STRFTIME
#include <fstab.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#elif defined(P_SOLARIS)
#define P_USE_LANGINFO
#include <sys/timeb.h>
#include <sys/statvfs.h>
#include <sys/mnttab.h>
#elif defined(P_SUN4)
#include <sys/timeb.h>
#elif defined(__BEOS__)
#define P_USE_STRFTIME
#elif defined(P_IRIX)
#define P_USE_LANGINFO
#include <sys/stat.h>
#include <sys/statfs.h>
#include <stdio.h>
#include <mntent.h>
#elif defined(P_VXWORKS)
#define P_USE_STRFTIME
#elif defined(P_RTEMS)
#define P_USE_STRFTIME
#include <time.h>
#include <stdio.h>
#define random() rand()
#define srandom(a) srand(a)
#elif defined(P_QNX)
#include <sys/dcmd_blk.h>
#include <sys/statvfs.h>
#define P_USE_STRFTIME
#endif
#ifdef P_USE_LANGINFO
#include <langinfo.h>
#endif
#define LINE_SIZE_STEP 100
#define DEFAULT_FILE_MODE (S_IRUSR|S_IWUSR|S_IROTH|S_IRGRP)
#include <ptlib/pprocess.h>
#if !P_USE_INLINES
#include "ptlib/osutil.inl"
#ifdef _WIN32
#include "ptlib/win32/ptlib/ptlib.inl"
#else
#include "ptlib/unix/ptlib/ptlib.inl"
#endif
#endif
#ifdef P_SUN4
extern "C" {
int on_exit(void (*f)(void), caddr_t);
int atexit(void (*f)(void))
{
return on_exit(f, 0);
}
static char *tzname[2] = { "STD", "DST" };
};
#endif
#define new PNEW
static PMutex waterMarkMutex;
static int lowWaterMark = INT_MAX;
static int highWaterMark = 0;
int PX_NewHandle(const char * clsName, int fd)
{
if (fd < 0)
return fd;
PWaitAndSignal m(waterMarkMutex);
if (fd > highWaterMark) {
highWaterMark = fd;
lowWaterMark = fd;
int maxHandles = PProcess::Current().GetMaxHandles();
if (fd < (maxHandles-maxHandles/20))
PTRACE(4, "PWLib\tFile handle high water mark set: " << fd << ' ' << clsName);
else
PTRACE(1, "PWLib\tFile handle high water mark within 5% of maximum: " << fd << ' ' << clsName);
}
if (fd < lowWaterMark) {
lowWaterMark = fd;
PTRACE(4, "PWLib\tFile handle low water mark set: " << fd << ' ' << clsName);
}
return fd;
}
static PString CanonicaliseDirectory (const PString & path)
{
PString canonical_path;
if (path[0] == '/')
canonical_path = '/';
else {
char *p = getcwd(canonical_path.GetPointer(P_MAX_PATH), P_MAX_PATH);
PAssertOS (p != NULL);
// if the path doesn't end in a slash, add one
if (canonical_path[canonical_path.GetLength()-1] != '/')
canonical_path += '/';
}
const char * ptr = path;
const char * end;
for (;;) {
// ignore slashes
while (*ptr == '/' && *ptr != '\0')
ptr++;
// finished if end of string
if (*ptr == '\0')
break;
// collect non-slash characters
end = ptr;
while (*end != '/' && *end != '\0')
end++;
// make a string out of the element
PString element(ptr, end - ptr);
if (element == "..") {
PINDEX last_char = canonical_path.GetLength()-1;
if (last_char > 0)
canonical_path = canonical_path.Left(canonical_path.FindLast('/', last_char-1)+1);
} else if (element == "." || element == "") {
} else {
canonical_path += element;
canonical_path += '/';
}
ptr = end;
}
return canonical_path;
}
static PString CanonicaliseFilename(const PString & filename)
{
if (filename.IsEmpty())
return filename;
PINDEX p;
PString dirname;
// if there is a slash in the string, extract the dirname
if ((p = filename.FindLast('/')) != P_MAX_INDEX) {
dirname = filename(0,p);
while (filename[p] == '/')
p++;
} else
p = 0;
return CanonicaliseDirectory(dirname) + filename(p, P_MAX_INDEX);
}
PInt64 PString::AsInt64(unsigned base) const
{
char * dummy;
#if defined(P_SOLARIS) || defined(__BEOS__) || defined (P_AIX) || defined(P_IRIX) || defined (P_QNX)
return strtoll(theArray, &dummy, base);
#elif defined(P_VXWORKS) || defined(P_RTEMS)
return strtol(theArray, &dummy, base);
#else
return strtoq(theArray, &dummy, base);
#endif
}
PUInt64 PString::AsUnsigned64(unsigned base) const
{
char * dummy;
#if defined(P_SOLARIS) || defined(__BEOS__) || defined (P_AIX) || defined (P_IRIX) || defined (P_QNX)
return strtoull(theArray, &dummy, base);
#elif defined(P_VXWORKS) || defined(P_RTEMS)
return strtoul(theArray, &dummy, base);
#else
return strtouq(theArray, &dummy, base);
#endif
}
///////////////////////////////////////////////////////////////////////////////
//
// timer
PTimeInterval PTimer::Tick()
{
#ifdef P_VXWORKS
struct timespec ts;
clock_gettime(0,&ts);
return (int)(ts.tv_sec*10000) + ts.tv_nsec/100000L;
#else
struct timeval tv;
::gettimeofday (&tv, NULL);
return (PInt64)(tv.tv_sec) * 1000 + tv.tv_usec/1000L;
#endif // P_VXWORKS
}
///////////////////////////////////////////////////////////////////////////////
//
// PDirectory
//
void PDirectory::CopyContents(const PDirectory & d)
{
if (d.entryInfo == NULL)
entryInfo = NULL;
else {
entryInfo = new PFileInfo;
*entryInfo = *d.entryInfo;
}
directory = NULL;
entryBuffer = NULL;
}
void PDirectory::Close()
{
if (directory != NULL) {
PAssert(closedir(directory) == 0, POperatingSystemError);
directory = NULL;
}
if (entryBuffer != NULL) {
free(entryBuffer);
entryBuffer = NULL;
}
if (entryInfo != NULL) {
delete entryInfo;
entryInfo = NULL;
}
}
void PDirectory::Construct ()
{
directory = NULL;
entryBuffer = NULL;
entryInfo = NULL;
PString::AssignContents(CanonicaliseDirectory(*this));
}
PBoolean PDirectory::Open(int ScanMask)
{
if (directory != NULL)
Close();
scanMask = ScanMask;
if ((directory = opendir(theArray)) == NULL)
return PFalse;
entryBuffer = (struct dirent *)malloc(sizeof(struct dirent) + P_MAX_PATH);
entryInfo = new PFileInfo;
if (Next())
return PTrue;
Close();
return PFalse;
}
PBoolean PDirectory::Next()
{
if (directory == NULL)
return PFalse;
do {
do {
struct dirent * entryPtr;
entryBuffer->d_name[0] = '\0';
#if P_HAS_POSIX_READDIR_R == 3
if (::readdir_r(directory, entryBuffer, &entryPtr) != 0)
return PFalse;
if (entryPtr != entryBuffer)
return PFalse;
#elif P_HAS_POSIX_READDIR_R == 2
entryPtr = ::readdir_r(directory, entryBuffer);
if (entryPtr == NULL)
return PFalse;
#else
if ((entryPtr = ::readdir(directory)) == NULL)
return PFalse;
*entryBuffer = *entryPtr;
strcpy(entryBuffer->d_name, entryPtr->d_name);
#endif
} while (strcmp(entryBuffer->d_name, "." ) == 0 || strcmp(entryBuffer->d_name, "..") == 0);
/* Ignore this file if we can't get info about it */
if (PFile::GetInfo(*this+entryBuffer->d_name, *entryInfo) == 0)
continue;
if (scanMask == PFileInfo::AllPermissions)
return PTrue;
} while ((entryInfo->type & scanMask) == 0);
return PTrue;
}
PBoolean PDirectory::IsSubDir() const
{
if (entryInfo == NULL)
return PFalse;
return entryInfo->type == PFileInfo::SubDirectory;
}
PBoolean PDirectory::Restart(int newScanMask)
{
scanMask = newScanMask;
if (directory != NULL)
rewinddir(directory);
return PTrue;
}
PString PDirectory::GetEntryName() const
{
if (entryBuffer == NULL)
return PString();
return entryBuffer->d_name;
}
PBoolean PDirectory::GetInfo(PFileInfo & info) const
{
if (entryInfo == NULL)
return PFalse;
info = *entryInfo;
return PTrue;
}
PBoolean PDirectory::Exists(const PString & p)
{
struct stat sbuf;
if (stat((const char *)p, &sbuf) != 0)
return PFalse;
return S_ISDIR(sbuf.st_mode);
}
PBoolean PDirectory::Create(const PString & p, int perm)
{
PAssert(!p.IsEmpty(), "attempt to create dir with empty name");
PINDEX last = p.GetLength()-1;
PString str = p;
if (p[last] == '/')
str = p.Left(last);
#ifdef P_VXWORKS
return mkdir(str) == 0;
#else
return mkdir(str, perm) == 0;
#endif
}
PBoolean PDirectory::Remove(const PString & p)
{
PAssert(!p.IsEmpty(), "attempt to remove dir with empty name");
PString str = p.Left(p.GetLength()-1);
return rmdir(str) == 0;
}
PString PDirectory::GetVolume() const
{
PString volume;
#if defined(P_QNX)
int fd;
char mounton[257];
if ((fd = open(operator+("."), O_RDONLY)) != -1) {
mounton[256] = 0;
devctl(fd, DCMD_FSYS_MOUNTED_ON, mounton, 256, 0);
close(fd);
volume = strdup(mounton);
}
#else
struct stat status;
if (stat(operator+("."), &status) != -1) {
dev_t my_dev = status.st_dev;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -