This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-goldedplus/goldlib/gall/gfilutl1.cpp

530 lines
12 KiB
C++
Raw Normal View History

2000-02-25 10:15:17 +00:00
// This may look like C code, but it is really -*- C++ -*-
// ------------------------------------------------------------------
// The Goldware Library
// Copyright (C) 1990-1999 Odinn Sorensen
// Copyright (C) 1999-2000 Alexander S. Aganichev
// ------------------------------------------------------------------
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this program; if not, write to the Free
// Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
// MA 02111-1307, USA
// ------------------------------------------------------------------
// $Id$
// ------------------------------------------------------------------
// File utility functions
// ------------------------------------------------------------------
#include <gtimall.h>
#include <gstrall.h>
#include <gfilutil.h>
2006-04-24 16:38:44 +00:00
#include <gfile.h>
2009-04-19 20:49:49 +00:00
#include <stdlib.h>
2006-04-24 16:38:44 +00:00
2002-09-24 10:16:04 +00:00
#if defined(__MINGW32__) || defined(_MSC_VER)
#include <sys/utime.h>
#else
2000-02-25 10:15:17 +00:00
#include <utime.h>
#endif
2000-02-25 10:15:17 +00:00
#if defined(__OS2__)
#define INCL_BASE
#include <os2.h>
#endif
#if defined(__WIN32__)
#include <windows.h>
#endif
#if defined(__MSDOS__)
#include <dos.h>
#endif
#if defined(__UNIX__)
#include <pwd.h>
#include <sys/types.h>
#endif
2000-02-25 10:15:17 +00:00
// ------------------------------------------------------------------
2009-11-29 12:20:28 +00:00
// Adds the directory-delimiter character into end of string ('\\' in DOS-based, '/' in unix-based OS)
2000-02-25 10:15:17 +00:00
char* AddBackslash(char* p) {
2011-02-14 19:57:28 +00:00
if(p != NULL) {
if(*p) {
2000-02-25 10:15:17 +00:00
strchg(p, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR);
if(p[strlen(p)-1] != GOLD_SLASH_CHR)
strcat(p, GOLD_SLASH_STR);
2011-02-14 19:57:28 +00:00
}
else
2000-02-25 10:15:17 +00:00
strcpy(p, GOLD_SLASH_STR);
2011-02-14 19:57:28 +00:00
}
2000-02-25 10:15:17 +00:00
return p;
}
// ------------------------------------------------------------------
2009-11-29 12:20:28 +00:00
// Remove one trailing directory-delimiter character ('\\' in DOS-based, '/' in unix-based OS)
2000-02-25 10:15:17 +00:00
char* StripBackslash(char* p) {
2011-02-14 19:57:28 +00:00
if(p == NULL) return p;
2000-02-25 10:15:17 +00:00
int x = strlen(p) - 1;
if(*p and isslash(p[x]))
p[x] = NUL;
return p;
}
// ------------------------------------------------------------------
// Get size of file
long GetFilesize(const char* file) {
2011-02-14 19:57:28 +00:00
if(file == NULL) return 0;
2000-02-25 10:15:17 +00:00
struct stat info;
if(stat(file, &info) == 0)
return info.st_size;
return -1;
}
// ------------------------------------------------------------------
// Convert time returned with stat to FFTime
2006-04-24 16:38:44 +00:00
time32_t gfixstattime(time32_t st_time)
{
#if (defined(__MINGW32__) && !defined(__MSVCRT__)) || defined(__CYGWIN__)
struct tm f; ggmtime(&f, &st_time);
2000-02-25 10:15:17 +00:00
#else
struct tm f; glocaltime(&f, &st_time);
2000-02-25 10:15:17 +00:00
#endif
FFTime t;
t.ft_year = f.tm_year - 80;
t.ft_month = f.tm_mon + 1;
t.ft_day = f.tm_mday;
t.ft_hour = f.tm_hour;
t.ft_min = f.tm_min;
t.ft_tsec = f.tm_sec / 2;
#if (defined(__MINGW32__) && !defined(__MSVCRT__)) || defined(__CYGWIN__)
2000-02-25 10:15:17 +00:00
union {
DWORD t;
struct {
WORD wFatTime;
WORD wFatDate;
} d;
} ft;
ft.t = (DWORD)t.number();
FILETIME FileTime, LocalFileTime;
DosDateTimeToFileTime(ft.d.wFatDate, ft.d.wFatTime, &FileTime);
FileTimeToLocalFileTime(&FileTime, &LocalFileTime);
SYSTEMTIME SystemTime;
FileTimeToSystemTime(&LocalFileTime, &SystemTime);
t.ft_year = SystemTime.wYear - 1980;
t.ft_month = SystemTime.wMonth;
t.ft_day = SystemTime.wDay;
t.ft_hour = SystemTime.wHour;
t.ft_min = SystemTime.wMinute;
t.ft_tsec = SystemTime.wSecond / 2;
#endif
return t.number();
}
// ------------------------------------------------------------------
// Get timestamp of file
2006-04-24 16:38:44 +00:00
time32_t GetFiletime(const char* file) {
2000-02-25 10:15:17 +00:00
struct stat st;
2011-02-14 19:57:28 +00:00
if(file == NULL) return 0;
2000-02-25 10:15:17 +00:00
if(stat(file, &st) == 0) {
#if defined(__MINGW32__)
if(st.st_mode & S_IFDIR)
return 0;
#endif
return gfixstattime(st.st_mtime);
}
return 0;
}
// ------------------------------------------------------------------
// Get size of open file
long fsize(FILE* fp) {
2011-02-14 19:57:28 +00:00
if(fp == NULL) return 0;
2000-02-25 10:15:17 +00:00
return filelength(fileno(fp));
}
// ------------------------------------------------------------------
// Check if a pathname is a directory
bool is_dir(const TCHAR *path)
{
2011-02-14 19:57:28 +00:00
if(path == NULL) return false;
// Check if it's a root path (X:\ оr /)
2000-02-25 10:15:17 +00:00
#if defined(__HAVE_DRIVES__)
if(g_isalpha(path[0]) and (path[1] == ':') and isslash(path[2]) and (path[3] == NUL))
2000-02-25 10:15:17 +00:00
return true; // The root is a directory
# else
if( isslash(path[0]) and (path[1] == NUL))
return true; // The root is a directory
2000-02-25 10:15:17 +00:00
#endif
Path tmp;
strxcpy(tmp, path, sizeof(Path));
StripBackslash(tmp);
struct stat st;
if(stat(tmp, &st) == 0)
2005-10-25 06:11:09 +00:00
return make_bool(st.st_mode & S_IFDIR);
2000-02-25 10:15:17 +00:00
return false;
}
// ------------------------------------------------------------------
// Add path to filename if no path is present
static Path __addpath;
const char* AddPath(const char* path, const char* file) {
2011-02-14 19:57:28 +00:00
if( (path == NULL) or (file == NULL) ) return file;
2000-02-25 10:15:17 +00:00
if(strpbrk(file, "/\\")) {
// Don't add path if the filename already contains one
return file;
}
else if(*path and ((*file == '.') or isslash(path[strlen(path)-1]))) {
// Build path+filename if path ends with a slash or backslash
strxmerge(__addpath, sizeof(Path), path, file, NULL);
return __addpath;
}
else {
// Use filename in path or file
return *path ? path : file;
}
}
// ------------------------------------------------------------------
// Add path to filename, if no path is set
void MakePathname(char* pathname, const char* path, const char* name) {
Path tmpname;
2011-02-14 19:57:28 +00:00
if( (pathname == NULL) or (path == NULL) or (name == NULL) ) return;
strxcpy(tmpname, name, GMAXPATH);
2003-01-04 10:13:33 +00:00
strschg_environ(tmpname);
2000-02-25 10:15:17 +00:00
if(strblank(tmpname)) {
*pathname = NUL;
return;
}
2002-11-24 16:08:06 +00:00
bool have_path = false;
if(isslash(tmpname[0]))
have_path = true;
#if defined(__HAVE_DRIVES__)
// Check if it's a root path (X:\)
else if(g_isalpha(tmpname[0]) and (tmpname[1] == ':') and isslash(tmpname[2]))
2002-11-24 16:08:06 +00:00
have_path = true; // The root is a directory
#endif
2000-02-25 10:15:17 +00:00
strchg(tmpname, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR);
2002-11-24 16:08:06 +00:00
if(have_path) {
strxcpy(pathname, tmpname, sizeof(Path));
}
2000-02-25 10:15:17 +00:00
else {
Path tmppath;
strcpy(tmppath, path);
strbtrim(tmppath);
strchg(tmppath, GOLD_WRONG_SLASH_CHR, GOLD_SLASH_CHR);
if(*tmppath)
AddBackslash(tmppath);
strxmerge(pathname, sizeof(Path), tmppath, tmpname, NULL);
2000-02-25 10:15:17 +00:00
}
strschg_environ(pathname);
2000-02-25 10:15:17 +00:00
}
// ------------------------------------------------------------------
// Shareable fopen() for compilers that need it
FILE *fsopen(const char *path, const char *type, int shflag) {
FILE* fp=NULL;
int fh=-1, acc=0, mode=S_STDRD, c, n;
2011-02-14 19:57:28 +00:00
if( (path == NULL) or (type == NULL) ) return NULL;
2000-02-25 10:15:17 +00:00
switch(type[0]) {
case 'r':
acc |= O_RDONLY;
break;
case 'w':
acc |= (O_TRUNC|O_CREAT|O_WRONLY);
mode |= S_STDRW;
break;
case 'a':
acc |= (O_APPEND|O_CREAT|O_WRONLY);
mode |= S_STDRW;
break;
default:
return NULL;
}
n=0;
do {
c = type[++n];
switch(c) {
case '+':
acc &= (~O_RDONLY);
acc &= (~O_WRONLY);
acc |= O_RDWR;
break;
case 'b':
acc |= O_BINARY;
break;
case 't':
acc |= O_TEXT;
break;
default:
break;
}
2002-11-04 18:59:51 +00:00
} while((n < 3) and (c));
2000-02-25 10:15:17 +00:00
fh = sopen(path, acc, shflag, mode);
if(fh != -1)
fp = fdopen(fh, (char*)type);
return fp;
}
// ------------------------------------------------------------------
2009-11-29 12:20:28 +00:00
// Update time of modification for the file 'filename'
2000-02-25 10:15:17 +00:00
2006-04-24 16:38:44 +00:00
void TouchFile(const TCHAR *filename)
{
2011-02-14 19:57:28 +00:00
if(filename == NULL) return;
2006-04-24 16:38:44 +00:00
if (not fexist(filename))
{
gfile fh(filename, O_WRONLY|O_CREAT|O_TRUNC);
}
else
{
2000-02-25 10:15:17 +00:00
struct utimbuf ut;
ut.actime = ut.modtime = time(NULL);
utime(filename, &ut);
}
}
// ------------------------------------------------------------------
2009-11-29 12:20:28 +00:00
// Copy pathname with enviroment variables substitution and adds directory delimiter char.
// Copy not more sizeof(Path) characters (__dst should be type "Path" or equvalence, size is GMAXPATH)
2000-02-25 10:15:17 +00:00
char* PathCopy(char* __dst, const char* __src) {
2011-02-14 19:57:28 +00:00
if( (__dst == NULL) or (__src == NULL) ) return __dst;
2000-10-20 11:14:13 +00:00
strschg_environ(strxcpy(__dst, __src, sizeof(Path)));
return AddBackslash(__dst);
2000-02-25 10:15:17 +00:00
}
// ------------------------------------------------------------------
2009-11-29 12:20:28 +00:00
// Test filesystem for file locks feature
2000-02-25 10:15:17 +00:00
int TestLockPath(const char* __path) {
int _canlock = false;
Path _file;
2011-02-14 19:57:28 +00:00
if(__path == NULL) return NO;
2000-02-25 10:15:17 +00:00
strxmerge(_file, sizeof(Path), __path, "GDXXXXXX", NULL);
mktemp(_file);
int _fh = sopen(_file, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, SH_DENYNO, S_STDRW);
if(_fh != -1) {
if(lock(_fh, 0L, 1L) == -1)
_canlock = NO;
else {
_canlock = YES;
unlock(_fh, 0L, 1L);
}
close(_fh);
remove(_file);
}
return _canlock;
}
// ------------------------------------------------------------------
2009-11-29 12:20:28 +00:00
// Return filename without path. (Return pointer to filename part of filepath.)
2000-02-25 10:15:17 +00:00
const char* CleanFilename(const char* __file) {
static const char* invalidfilename = "<invalid>";
if((__file == NULL) or (__file == (char*)0xFFFFFFFFL) or (__file == (char*)0xEEEEEEEEL))
return invalidfilename;
const char *tmp, *tmp2;
tmp = tmp2 = __file;
while(*tmp)
if(isslash(*tmp++))
tmp2 = tmp;
return *tmp2 ? tmp2 : invalidfilename;
}
// ------------------------------------------------------------------
2009-11-29 12:20:28 +00:00
// Fill file with garbage (random byte values).
2000-02-25 10:15:17 +00:00
void WipeFile(const char* file, int options) {
uint n;
byte buf[512];
2002-09-24 10:16:04 +00:00
(void)options;
2011-02-14 19:57:28 +00:00
if(file == NULL) return;
2002-09-24 10:16:04 +00:00
for(n=0; n<512; n++)
buf[n] = (byte)(rand() % 256);
2000-02-25 10:15:17 +00:00
int fh = sopen(file, O_RDWR|O_BINARY, SH_DENYRW, S_STDRW);
if(fh != -1) {
uint blocks = (uint)(filelength(fh) / 512L) + 1;
for(n=0; n<blocks; n++)
write(fh, buf, 512);
chsize(fh, 0);
close(fh);
remove(file);
}
}
// ------------------------------------------------------------------
2009-11-29 12:20:28 +00:00
// DOS-style enviroment variables substitution in string.
2000-02-25 10:15:17 +00:00
int strschg_environ(char* s) {
2011-02-14 19:57:28 +00:00
if(s == NULL) return 0;
2000-02-25 10:15:17 +00:00
if(*s == NUL)
return 0;
std::string __s = s;
2009-11-29 12:20:28 +00:00
int rv = strschg_environ(__s); // Look in gfilutl2.cpp
2000-02-25 10:15:17 +00:00
if(rv)
strxcpy(s, __s.c_str(), sizeof(Path));
return rv;
}
// ------------------------------------------------------------------
2009-11-29 12:20:28 +00:00
// OS-independent change directory
2000-02-25 10:15:17 +00:00
int gchdir(const char* dir) {
2011-02-14 19:57:28 +00:00
if(dir == NULL) return 0;
2000-02-25 10:15:17 +00:00
#if defined(__WIN32__)
return not SetCurrentDirectory(dir);
#else
#if defined(__HAVE_DRIVES__)
if(dir[1] == ':') {
#if defined(__EMX__)
_chdrive(*dir);
#else
uint drives;
_dos_setdrive(g_toupper(*dir)-'@', &drives);
2000-02-25 10:15:17 +00:00
#endif
}
#endif
int e = chdir(dir);
if(e) {
Path p;
strcpy(p, dir);
StripBackslash(p);
e = chdir(p);
}
return e;
#endif
}
// ------------------------------------------------------------------
2009-11-29 12:20:28 +00:00
// Replace file suffix with specified in 'ext'
2000-02-25 10:15:17 +00:00
void replaceextension(char *destpath, const char *srcpath, const char *ext) {
const char *ptr;
char *ptr2, *slash, *dot;
2011-02-14 19:57:28 +00:00
if( (destpath == NULL) or (srcpath == NULL) or (ext == NULL) ) return;
2000-02-25 10:15:17 +00:00
ptr2 = slash = dot = destpath;
ptr = srcpath;
while(*ptr) {
if(isslash(*ptr))
slash = ptr2;
else if(*ptr == '.')
dot = ptr2;
*ptr2++ = *ptr++;
}
if(dot-slash > 0)
ptr2 = dot;
strcpy(ptr2, ext);
}
// ------------------------------------------------------------------
2009-11-29 12:20:28 +00:00
// Write to 'dir' dirname of the 'path'
2000-02-25 10:15:17 +00:00
void extractdirname(char *dir, const char *path) {
const char *p1 = path;
char *p2, *p3;
2011-02-14 19:57:28 +00:00
if( (dir == NULL) or (path == NULL) ) return;
2000-02-25 10:15:17 +00:00
p3 = p2 = dir;
2003-04-07 10:21:30 +00:00
*p3 = NUL;
2000-02-25 10:15:17 +00:00
while(*p1) {
if(isslash(*p1))
p2 = p3;
*p3++ = *p1++;
}
if(isslash(*p2))
++p2;
*p2 = NUL;
}
// ------------------------------------------------------------------