📄 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): ______________________________________. * * $Log: osutil.cxx,v $ * Revision 1.55 2000/06/21 01:01:22 robertj * AIX port, thanks Wolfgang Platzer (wolfgang.platzer@infonova.at). * * Revision 1.54 2000/04/19 00:13:53 robertj * BeOS port changes. * * Revision 1.53 2000/04/09 18:19:23 rogerh * Add my changes for NetBSD support. * * Revision 1.52 2000/04/06 12:11:32 rogerh * MacOS X support submitted by Kevin Packard * * Revision 1.51 2000/04/05 02:55:11 robertj * Added microseconds to PTime class. * * Revision 1.50 2000/03/08 12:17:09 rogerh * Add OpenBSD support * * Revision 1.49 2000/02/24 11:03:49 robertj * Fixed warning on Linux systems about _REENTRANT * * Revision 1.48 1999/08/17 07:37:36 robertj * Fixed inlines so are inlined for optimised version * * Revision 1.47 1999/06/28 09:28:02 robertj * Portability issues, especially n BeOS (thanks Yuri!) * * Revision 1.46 1999/06/26 08:21:12 robertj * Fixed bug in PFilePath::SetType finding dots outside of file name in path. * * Revision 1.45 1999/06/14 08:39:57 robertj * Added PConsoleChannel class for access to stdin/stdout/stderr * * Revision 1.44 1999/06/09 04:08:46 robertj * Added support for opening stdin/stdout/stderr as PFile objects. * * Revision 1.43 1999/02/22 13:26:53 robertj * BeOS port changes. * * Revision 1.42 1998/12/12 01:06:24 robertj * Fixed off by one error in month on FreeBSD platform * * Revision 1.41 1998/11/30 21:51:43 robertj * New directory structure. * * Revision 1.40 1998/11/26 11:54:16 robertj * Fixed error return on PFile::GetInfo * * Revision 1.39 1998/11/24 09:39:09 robertj * FreeBSD port. * * Revision 1.38 1998/11/10 13:00:52 robertj * Fixed strange problems with readdir_r usage. * * Revision 1.37 1998/11/06 04:44:46 robertj * Solaris compatibility * * Revision 1.36 1998/11/05 12:03:13 robertj * Fixed solaris compatibility and Linux warning on readdir_r function. * * Revision 1.35 1998/11/05 09:05:55 craigs * Changed directory routines to use reenttrant functions, and added PDirectory::GetParent * * Revision 1.34 1998/09/24 07:39:49 robertj * Removed file that only had #pragma implmentation for PTextFile and nothing else. * * Revision 1.33 1998/09/24 04:12:12 robertj * Added open software license. * */#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>#include <time.h>#include <sys/time.h>#include <ctype.h>#if defined(P_LINUX)#include <mntent.h>#include <sys/vfs.h>#define P_HAS_READDIR_R#if (__GNUC_MINOR__ < 7)#include <localeinfo.h>#else#define P_USE_LANGINFO#endif#elif defined(P_FREEBSD) || defined(P_OPENBSD) || defined(P_NETBSD) || defined(P_MACOSX)#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_HAS_READDIR_R#define P_USE_LANGINFO#include <sys/timeb.h>#include <sys/statvfs.h>#include <sys/mnttab.h>#elif defined(P_SUN4)#include <sys/timeb.h>#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)#if !P_USE_INLINES#include <ptlib/osutil.inl>#include <ptlib/ptlib.inl>#endif#ifdef P_SUN4extern "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 PNEWstatic PString CanonicaliseDirectory (const PString & path){ PString canonical_path; PString slash("/"); // if the path does not start with a slash, then the current directory // must be prepended if (path.IsEmpty() || path[0] != '/') { 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 += slash; 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 += slash; } ptr = end; } return canonical_path;}static PString CanonicaliseFilename(const PString & 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) return strtoll(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) return strtoull(theArray, &dummy, base);#else return strtouq(theArray, &dummy, base);#endif}/////////////////////////////////////////////////////////////////////////////////// timerPTimeInterval PTimer::Tick(){ struct timeval tv; ::gettimeofday (&tv, NULL); return (PInt64)(tv.tv_sec) * 1000 + tv.tv_usec/1000L;}/////////////////////////////////////////////////////////////////////////////////// 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::operator =(CanonicaliseDirectory(*this));}BOOL PDirectory::Open(int ScanMask){ if (directory != NULL) Close(); scanMask = ScanMask; if ((directory = opendir(theArray)) == NULL) return FALSE; entryBuffer = (struct dirent *)malloc(sizeof(struct dirent) + P_MAX_PATH); entryInfo = new PFileInfo; if (Next()) return TRUE; Close(); return FALSE;}BOOL PDirectory::Next(){ if (directory == NULL) return FALSE; do { do { struct dirent * entryPtr; entryBuffer->d_name[0] = '\0';#ifdef P_HAS_READDIR_R if (::readdir_r(directory, entryBuffer, &entryPtr) != 0) return FALSE; if (entryPtr != entryBuffer) return FALSE;#else if ((entryPtr = readdir(directory)) == NULL) return FALSE; *entryBuffer = *entryPtr; strcpy(entryBuffer->d_name, entryPtr->d_name);#endif } while (strcmp(entryBuffer->d_name, "." ) == 0 || strcmp(entryBuffer->d_name, "..") == 0); PAssert(PFile::GetInfo(*this+entryBuffer->d_name, *entryInfo), POperatingSystemError); if (scanMask == PFileInfo::AllPermissions) return TRUE; } while ((entryInfo->type & scanMask) == 0); return TRUE;}BOOL PDirectory::IsSubDir() const{ if (entryInfo == NULL) return FALSE; return entryInfo->type == PFileInfo::SubDirectory;}BOOL PDirectory::Restart(int newScanMask){ scanMask = newScanMask; if (directory != NULL) rewinddir(directory); return TRUE;}PString PDirectory::GetEntryName() const{ if (entryBuffer == NULL) return PString(); return entryBuffer->d_name;}BOOL PDirectory::GetInfo(PFileInfo & info) const{ info = *entryInfo; return TRUE;}BOOL PDirectory::Create(const PString & p, int perm){ PAssert(!p.IsEmpty(), "attempt to create dir with empty name"); PString str = p.Left(p.GetLength()-1); return mkdir(str, perm) == 0;}BOOL 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; struct stat status; if (stat(operator+("."), &status) != -1) { dev_t my_dev = status.st_dev;#if defined(P_LINUX) FILE * fp = setmntent(MOUNTED, "r"); if (fp != NULL) { struct mntent * mnt; while ((mnt = getmntent(fp)) != NULL) { if (stat(mnt->mnt_dir, &status) != -1 && status.st_dev == my_dev) { volume = mnt->mnt_fsname; break; } } } endmntent(fp);#elif defined(P_SOLARIS) FILE * fp = fopen("/etc/mnttab", "r"); if (fp != NULL) { struct mnttab mnt; while (getmntent(fp, &mnt) == 0) { if (stat(mnt.mnt_mountp, &status) != -1 && status.st_dev == my_dev) { volume = mnt.mnt_special; break; } } } fclose(fp);#elif defined(P_FREEBSD) || defined(P_OPENBSD) || defined(P_NETBSD) || defined(P_MACOSX) struct statfs * mnt; int count = getmntinfo(&mnt, MNT_NOWAIT); for (int i = 0; i < count; i++) { if (stat(mnt[i].f_mntonname, &status) != -1 && status.st_dev == my_dev) { volume = mnt[i].f_mntfromname; break; } }#elif defined (P_AIX) struct fstab * fs; setfsent(); while ((fs = getfsent()) != NULL) { if (stat(fs->fs_file, &status) != -1 && status.st_dev == my_dev) { volume = fs->fs_spec; break; } } endfsent();#else#warning Platform requires implemetation of GetVolume()#endif } return volume;}BOOL PDirectory::GetVolumeSpace(PInt64 & total, PInt64 & free, DWORD & clusterSize) const{#if defined(P_LINUX) || defined(P_FREEBSD) || defined(P_OPENBSD) || defined(P_NETBSD) || defined(P_MACOSX) struct statfs fs; if (statfs(operator+("."), &fs) == -1) return FALSE; clusterSize = fs.f_bsize; total = fs.f_blocks*(PInt64)fs.f_bsize; free = fs.f_bavail*(PInt64)fs.f_bsize; return TRUE;#elif defined(P_AIX) struct statfs fs; if (statfs((char *) ((const char *)operator+(".") ), &fs) == -1) return FALSE; clusterSize = fs.f_bsize; total = fs.f_blocks*(PInt64)fs.f_bsize; free = fs.f_bavail*(PInt64)fs.f_bsize; return TRUE;#elif defined(P_SOLARIS) struct statvfs buf; if (statvfs(operator+("."), &buf) != 0) return FALSE; clusterSize = buf.f_frsize; total = buf.f_blocks * buf.f_frsize; free = buf.f_bfree * buf.f_frsize; return TRUE;#else#warning Platform requires implemetation of GetVolumeSpace() return FALSE;#endif}PDirectory PDirectory::GetParent() const{ if (IsRoot()) return *this; return *this + "..";}/////////////////////////////////////////////////////////////////////////////////// PFile//void PFile::SetFilePath(const PString & newName){ PINDEX p; if ((p = newName.FindLast('/')) == P_MAX_INDEX) path = CanonicaliseDirectory("") + newName; else path = CanonicaliseDirectory(newName(0,p)) + newName(p+1, P_MAX_INDEX);}BOOL PFile::Open(OpenMode mode, int opt){ Close(); clear(); if (path.IsEmpty()) { char * tmp = tempnam(NULL, "PWL"); PAssert(tmp != NULL, POperatingSystemError); path = PString(tmp); runtime_free(tmp); } int oflags = 0; switch (mode) { case ReadOnly : oflags |= O_RDONLY; if (opt == ModeDefault) opt = MustExist; break; case WriteOnly : oflags |= O_WRONLY; if (opt == ModeDefault) opt = Create|Truncate; break; case ReadWrite : oflags |= O_RDWR; if (opt == ModeDefault) opt = Create; break; default : PAssertAlways(PInvalidParameter); } if ((opt&Create) != 0) oflags |= O_CREAT; if ((opt&Exclusive) != 0) oflags |= O_EXCL; if ((opt&Truncate) != 0) oflags |= O_TRUNC; removeOnClose = opt & Temporary; if (!ConvertOSError(os_handle = ::open(path, oflags, DEFAULT_FILE_MODE))) return FALSE; return ConvertOSError(::fcntl(os_handle, F_SETFD, 1));}BOOL PFile::SetLength(off_t len){ return ConvertOSError(ftruncate(GetHandle(), len));}BOOL PFile::Rename(const PFilePath & oldname, const PString & newname, BOOL force){ if (newname.Find('/') != P_MAX_INDEX) { errno = EINVAL; return FALSE; } if (rename(oldname, oldname.GetPath() + newname) == 0) return TRUE; if (!force || errno == ENOENT || !Exists(newname)) return FALSE; if (!Remove(newname, TRUE)) return FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -