1
0
mirror of https://github.com/stefanocasazza/ULib.git synced 2025-09-28 19:05:55 +08:00
ULib/include/ulib/file.h
stefanocasazza 2d52d6d538 some fix
2015-11-10 19:41:51 +01:00

976 lines
26 KiB
C++

// ============================================================================
//
// = LIBRARY
// ULib - c++ library
//
// = FILENAME
// file.h
//
// = AUTHOR
// Stefano Casazza
//
// ============================================================================
#ifndef ULIB_FILE_H
#define ULIB_FILE_H
#include <ulib/string.h>
#include <errno.h>
// struct stat {
// dev_t st_dev; /* device */
// ino_t st_ino; /* inode */
// mode_t st_mode; /* protection */
// nlink_t st_nlink; /* number of hard links */
// uid_t st_uid; /* user ID of owner */
// gid_t st_gid; /* group ID of owner */
// dev_t st_rdev; /* device type (if inode device) */
// off_t st_size; /* total size, in bytes */
// blksize_t st_blksize; /* blocksize for filesystem I/O */
// blkcnt_t st_blocks; /* number of blocks allocated */
// time_t st_atime; /* time of last access */
// time_t st_mtime; /* time of last modification */
// time_t st_ctime; /* time of last change */
// };
#ifdef _MSWINDOWS_
#define st_ino u_inode
#endif
// File-permission-bit symbols
#define U_PERM__rw_r__r__ 0644
#define U_PERM__r________ 0400
#define U_PERM__r__r__r__ 0444
#define U_PERM__r_xr_xr_x 0555
#define PERM_FILE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) // rw_rw_r__
#define PERM_DIRECTORY S_IRWXU // rwx
// NB: the UString pathname maybe not writeable so path_relativ[path_relativ_len] maybe != '\0' (not null-terminate)...
#define U_FILE_TO_PARAM(file) (file).getPathRelativ(),(file).getPathRelativLen()
#define U_FILE_TO_TRACE(file) (file).getPathRelativLen(),(file).getPathRelativ()
#define U_FILE_TO_STRING(file) (file).getPath().substr((file).getPath().distance((file).getPathRelativ()),(file).getPathRelativLen())
class URDB;
class UHTTP;
class UDirWalk;
class UStringExt;
class UClientImage_Base;
template <class T> class URDBObjectHandler;
class U_EXPORT UFile : public stat {
public:
// NB: the object can be used as (struct stat) because UMemoryError is allocate after...
// Check for memory error
U_MEMORY_TEST
// Allocator e Deallocator
U_MEMORY_ALLOCATOR
U_MEMORY_DEALLOCATOR
// check for op chdir()
#ifdef DEBUG
static int num_file_object;
static void inc_num_file_object(UFile* pthis);
static void dec_num_file_object(int fd);
static void chk_num_file_object();
#else
# define inc_num_file_object(pthis)
# define dec_num_file_object(fd)
# define chk_num_file_object()
#endif
void reset()
{
U_TRACE_NO_PARAM(0, "UFile::reset()")
fd = -1;
map = (char*)MAP_FAILED;
st_size = 0;
map_size = 0;
}
// COSTRUTTORI
UFile()
{
U_TRACE_REGISTER_OBJECT(0, UFile, "", 0)
fd = -1;
map = (char*)MAP_FAILED;
path_relativ = 0;
path_relativ_len = map_size = 0;
inc_num_file_object(this);
}
UFile(const UString& path, const UString* environment = 0) : pathname(path)
{
U_TRACE_REGISTER_OBJECT(0, UFile, "%V,%p", path.rep, environment)
inc_num_file_object(this);
setPathRelativ(environment);
}
#ifdef U_COVERITY_FALSE_POSITIVE
virtual
#endif
~UFile()
{
U_TRACE_UNREGISTER_OBJECT(0, UFile)
dec_num_file_object(fd);
}
// PATH
void setRoot();
void setPath(const UString& path, const UString* environment = 0);
void setPath(const char* _pathname, const UString* environment = 0)
{
U_TRACE(0, "UFile::setPath(%S,%p)", _pathname, environment)
UString path(_pathname);
setPath(path, environment);
}
bool isRoot()
{
U_TRACE_NO_PARAM(0, "UFile::isRoot()")
U_INTERNAL_DUMP("u_cwd = %S", u_cwd)
U_INTERNAL_DUMP("path_relativ(%u) = %.*S", path_relativ_len, path_relativ_len, path_relativ)
if (path_relativ_len == 1 &&
path_relativ[0] == '/')
{
U_RETURN(true);
}
U_RETURN(false);
}
bool isPath()
{
U_TRACE_NO_PARAM(0, "UFile::isPath()")
U_CHECK_MEMORY
if (pathname) U_RETURN(true);
U_RETURN(false);
}
bool isPath(const char* _pathname, uint32_t len)
{
U_TRACE(0, "UFile::isPath(%.*S,%u)", len, _pathname, len)
U_INTERNAL_DUMP("u_cwd(%u) = %.*S", u_cwd_len, u_cwd_len, u_cwd)
U_INTERNAL_DUMP("path_relativ(%u) = %.*S", path_relativ_len, path_relativ_len, path_relativ)
if ((path_relativ_len == len) && (memcmp(path_relativ, _pathname, len) == 0)) U_RETURN(true);
U_RETURN(false);
}
// NB: the string can be not writable so path_relativ[path_relativ_len] can be != '\0'...
UString& getPath() { return pathname; }
UString getName() const;
UString getDirName() const;
UString getSuffix() const;
char* getPathRelativ() const { return (char*)path_relativ; }
int32_t getPathRelativLen() const { return path_relativ_len; }
bool isName(const UString& name) const { return name.equal(getName()); }
bool isNameDosMatch(const char* mask, uint32_t mask_len) const;
static uint32_t setPathFromFile(const UFile& file, char* buffer_path, const char* suffix, uint32_t len);
// OPEN - CLOSE
static int open(const char* _pathname, int flags, mode_t mode);
static int creat(const char* _pathname, int flags = O_TRUNC | O_RDWR, mode_t mode = PERM_FILE)
{
U_TRACE(0, "UFile::creat(%S,%d,%d)", _pathname, flags, mode)
return open(_pathname, O_CREAT | flags, mode);
}
static void close(int _fd)
{
U_TRACE(1, "UFile::close(%d)", _fd)
U_INTERNAL_ASSERT_DIFFERS(_fd, -1)
# ifdef U_COVERITY_FALSE_POSITIVE
if (_fd > 0)
# endif
(void) U_SYSCALL(close, "%d", _fd);
}
bool open( int flags = O_RDONLY);
bool open(const char* _pathname, int flags = O_RDONLY)
{
U_TRACE(0, "UFile::open(%S,%d)", _pathname, flags)
UString path(_pathname);
setPath(path);
return open(flags);
}
bool open(const UString& path, int flags = O_RDONLY)
{
U_TRACE(0, "UFile::open(%V,%d)", path.rep, flags)
setPath(path);
return open(flags);
}
bool creat( int flags = O_TRUNC | O_RDWR, mode_t mode = PERM_FILE);
bool creat(const UString& path, int flags = O_TRUNC | O_RDWR, mode_t mode = PERM_FILE);
void reopen(int flags)
{
U_TRACE(0, "UFile::reopen(%d)", flags)
U_CHECK_MEMORY
U_INTERNAL_ASSERT_POINTER(path_relativ)
U_INTERNAL_DUMP("path_relativ(%u) = %.*S", path_relativ_len, path_relativ_len, path_relativ)
close();
U_INTERNAL_ASSERT(pathname.isNullTerminated())
fd = open(pathname.data(), flags, PERM_FILE);
}
bool isOpen()
{
U_TRACE_NO_PARAM(0, "UFile::isOpen()")
U_CHECK_MEMORY
if (fd != -1) U_RETURN(true);
U_RETURN(false);
}
void close()
{
U_TRACE_NO_PARAM(0, "UFile::close()")
U_CHECK_MEMORY
UFile::close(fd);
fd = -1;
}
void setFd(int _fd)
{
U_TRACE(0, "UFile::setFd(%d)", _fd)
U_CHECK_MEMORY
fd = _fd;
}
int getFd() const
{
U_TRACE_NO_PARAM(0, "UFile::getFd()")
U_CHECK_MEMORY
U_RETURN(fd);
}
// ACCESS
bool access(int mode = R_OK | X_OK)
{
U_TRACE(1, "UFile::access(%d)", mode)
U_CHECK_MEMORY
U_INTERNAL_ASSERT_POINTER(path_relativ)
U_INTERNAL_DUMP("path_relativ(%u) = %.*S", path_relativ_len, path_relativ_len, path_relativ)
if (U_SYSCALL(access, "%S,%d", U_PATH_CONV(path_relativ), mode) == 0) U_RETURN(true);
U_RETURN(false);
}
bool stat();
bool slink() const
{
U_TRACE_NO_PARAM(0, "UFile::slink()")
U_CHECK_MEMORY
# ifndef _MSWINDOWS_
if (S_ISLNK(st_mode)) U_RETURN(true);
# endif
U_RETURN(false);
}
#ifndef _MSWINDOWS_
bool lstat()
{
U_TRACE_NO_PARAM(1, "UFile::lstat()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_POINTER(path_relativ)
U_INTERNAL_DUMP("path_relativ(%u) = %.*S", path_relativ_len, path_relativ_len, path_relativ)
if (U_SYSCALL(lstat, "%S,%p", U_PATH_CONV(path_relativ), (struct stat*)this) == 0) U_RETURN(true);
U_RETURN(false);
}
#endif
void fstat()
{
U_TRACE_NO_PARAM(1, "UFile::fstat()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_DIFFERS(fd, -1)
U_INTERNAL_ASSERT_POINTER(path_relativ)
U_INTERNAL_DUMP("path_relativ(%u) = %.*S", path_relativ_len, path_relativ_len, path_relativ)
# ifdef U_COVERITY_FALSE_POSITIVE
if (fd > 0)
# endif
(void) U_SYSCALL(fstat, "%d,%p", fd, (struct stat*)this);
}
off_t lseek(uint32_t offset, int whence)
{
U_TRACE(1, "UFile::lseek(%u,%d)", offset, whence)
U_CHECK_MEMORY
U_INTERNAL_ASSERT_DIFFERS(fd, -1)
# ifdef U_COVERITY_FALSE_POSITIVE
if (fd <= 0) U_RETURN(0);
# endif
off_t result = U_SYSCALL(lseek, "%d,%u,%d", fd, offset, whence);
U_RETURN(result);
}
void readSize()
{
U_TRACE_NO_PARAM(1, "UFile::readSize()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_DIFFERS(fd, -1)
U_INTERNAL_ASSERT_POINTER(path_relativ)
U_INTERNAL_DUMP("path_relativ(%u) = %.*S", path_relativ_len, path_relativ_len, path_relativ)
st_size = lseek(U_SEEK_BEGIN, SEEK_END);
U_INTERNAL_ASSERT(st_size >= U_SEEK_BEGIN)
}
off_t size(bool bstat = false);
off_t getSize() const
{
U_TRACE_NO_PARAM(0, "UFile::getSize()")
U_CHECK_MEMORY
U_RETURN(st_size);
}
static off_t getSize(int _fd)
{
U_TRACE(1, "UFile::getSize(%d)", _fd)
U_INTERNAL_ASSERT_DIFFERS(_fd, -1)
off_t result = U_SYSCALL(lseek, "%d,%u,%d", _fd, U_SEEK_BEGIN, SEEK_END);
U_RETURN(result);
}
static off_t getSize(const char* _pathname)
{
U_TRACE(1, "UFile::getSize(%S)", _pathname)
struct stat st;
if (U_SYSCALL(stat, "%S,%p", U_PATH_CONV(_pathname), &st) == 0) U_RETURN(st.st_size);
U_RETURN(0);
}
bool empty() const
{
U_TRACE_NO_PARAM(0, "UFile::empty()")
U_CHECK_MEMORY
if (st_size == 0) U_RETURN(true);
U_RETURN(false);
}
bool regular() const
{
U_TRACE_NO_PARAM(0, "UFile::regular()")
U_CHECK_MEMORY
if (S_ISREG(st_mode)) U_RETURN(true);
U_RETURN(false);
}
bool dir() const
{
U_TRACE_NO_PARAM(0, "UFile::dir()")
U_CHECK_MEMORY
if (S_ISDIR(st_mode)) U_RETURN(true);
U_RETURN(false);
}
bool socket() const
{
U_TRACE_NO_PARAM(0, "UFile::socket()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_DIFFERS(fd, -1)
if (S_ISSOCK(st_mode)) U_RETURN(true);
U_RETURN(false);
}
// Etag (HTTP/1.1)
UString etag() const
{
U_TRACE_NO_PARAM(0, "UFile::etag()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_MAJOR(st_size, 0)
U_INTERNAL_ASSERT_DIFFERS(st_ino, 0)
UString _etag(100U);
// NB: The only format constraints are that the string be quoted...
_etag.snprintf("\"%x-%x-%x\"", st_ino, st_size, st_mtime);
U_RETURN_STRING(_etag);
}
uint64_t inode()
{
U_TRACE_NO_PARAM(0, "UFile::inode()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_MAJOR(st_size, 0)
U_INTERNAL_ASSERT_DIFFERS(st_ino, 0)
U_RETURN(st_ino);
}
/**
* Mount Point
*
* Either the system root directory or a directory for which the st_dev field of structure stat differs from that of its parent directory
*/
bool isMountPoint(dev_t parent_id)
{
U_TRACE(0, "UFile::isMountPoint(%ld)", parent_id)
fstat();
U_RETURN(st_dev != parent_id);
}
// MODIFIER
bool modified()
{
U_TRACE_NO_PARAM(0, "UFile::modified()")
time_t mtime = st_mtime;
fstat();
U_INTERNAL_DUMP("mtime = %ld, st_mtime = %ld", (long)mtime, (long)st_mtime)
if (mtime != st_mtime) U_RETURN(true);
U_RETURN(false);
}
static bool isBlocking(int _fd, int& flags) // actual state is blocking...?
{
U_TRACE(1, "UFile::isBlocking(%d,%d)", _fd, flags)
U_INTERNAL_ASSERT_DIFFERS(_fd, -1)
if (flags == -1) flags = U_SYSCALL(fcntl, "%d,%d,%d", _fd, F_GETFL, 0);
U_INTERNAL_DUMP("O_NONBLOCK = %B, flags = %B", O_NONBLOCK, flags)
bool blocking = ((flags & O_NONBLOCK) != O_NONBLOCK);
U_RETURN(blocking);
}
static int setBlocking(int fd, int flags, bool block);
// mkdir
static bool _mkdir(const char* path, mode_t mode = PERM_DIRECTORY)
{
U_TRACE(1, "UFile::_mkdir(%S,%d)", path, mode)
if (U_SYSCALL(mkdir, "%S,%d", U_PATH_CONV(path), mode) != -1 || errno == EEXIST) U_RETURN(true);
U_RETURN(false);
}
// unlink
static bool _unlink(const char* _pathname)
{
U_TRACE(1, "UFile::_unlink(%S)", _pathname)
if (U_SYSCALL(unlink, "%S", U_PATH_CONV(_pathname)) == 0) U_RETURN(true);
U_RETURN(false);
}
bool _unlink()
{
U_TRACE_NO_PARAM(0, "UFile::_unlink()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_POINTER(path_relativ)
U_INTERNAL_DUMP("path_relativ(%u) = %.*S", path_relativ_len, path_relativ_len, path_relativ)
if (UFile::_unlink(path_relativ)) U_RETURN(true);
U_RETURN(false);
}
// rename
bool _rename( const char* newpath);
static bool _rename(const char* oldpath, const char* newpath)
{
U_TRACE(1, "UFile::_rename(%S,%S)", oldpath, newpath)
if (U_SYSCALL(rename, "%S,%S", oldpath, newpath) != -1) U_RETURN(true);
U_RETURN(false);
}
void fsync()
{
U_TRACE_NO_PARAM(1, "UFile::fsync()")
U_CHECK_MEMORY
U_INTERNAL_ASSERT_DIFFERS(fd, -1)
U_INTERNAL_ASSERT_POINTER(path_relativ)
U_INTERNAL_DUMP("path_relativ(%u) = %.*S", path_relativ_len, path_relativ_len, path_relativ)
# ifdef U_COVERITY_FALSE_POSITIVE
if (fd > 0)
# endif
(void) U_SYSCALL(fsync, "%d", fd);
}
bool fallocate(uint32_t n);
bool ftruncate(uint32_t n);
static bool chdir(const char* path, bool flag_save = false);
// LOCKING
bool lock(short l_type = F_WRLCK, uint32_t start = 0, uint32_t len = 0) const; /* set the lock, waiting if necessary */
bool unlock(uint32_t start = 0, uint32_t len = 0) const { return lock(F_UNLCK, start, len); }
// MEMORY MAPPED I/O (Basically, you can tell the OS that some file is the backing store for a certain portion of the process memory)
bool isMapped() const
{
U_TRACE_NO_PARAM(0, "UFile::isMapped()")
U_CHECK_MEMORY
U_RETURN(map != MAP_FAILED);
}
char* getMap() const { return map; }
void munmap();
static void munmap(void* _map, uint32_t length)
{
U_TRACE(1, "UFile::munmap(%p,%u)", _map, length)
U_INTERNAL_ASSERT_DIFFERS(_map, MAP_FAILED)
(void) U_SYSCALL(munmap, "%p,%u", _map, length);
}
static void msync(char* ptr, char* page, int flags = MS_ASYNC | MS_INVALIDATE); // flushes changes made to memory mapped file back to disk
// mremap() expands (or shrinks) an existing memory mapping, potentially moving it at the same time
// (controlled by the flags argument and the available virtual address space)
static char* mremap(void* old_address, uint32_t old_size, uint32_t new_size, int flags = 0) // MREMAP_MAYMOVE == 1
{
U_TRACE(1, "UFile::mremap(%p,%u,%u,%d)", old_address, old_size, new_size, flags)
void* result =
# if defined(__NetBSD__) || defined(__UNIKERNEL__)
U_SYSCALL(mremap, "%p,%u,%p,%u,%d", old_address, old_size, 0, new_size, 0);
# else
U_SYSCALL(mremap, "%p,%u,%u,%d", old_address, old_size, new_size, flags);
# endif
U_RETURN((char*)result);
}
bool memmap(int prot = PROT_READ, UString* str = 0, uint32_t offset = 0, uint32_t length = 0);
UString getContent( bool brdonly = true, bool bstat = false, bool bmap = false);
UString _getContent(bool bsize = true, bool brdonly = false, bool bmap = false);
static UString contentOf(const UString& _pathname, int flags = O_RDONLY, bool bstat = false);
static UString contentOf(const char* _pathname, int flags = O_RDONLY, bool bstat = false, const UString* environment = 0);
static char* mmap(uint32_t* plength, int _fd = -1, int prot = PROT_READ | PROT_WRITE, int flags = MAP_SHARED | MAP_ANONYMOUS, uint32_t offset = 0);
static char* shm_open( const char* name, uint32_t length); // create/open POSIX shared memory object
static void shm_unlink(const char *name); // unlink POSIX shared memory object
// MIME TYPE
const char* getMimeType(const char* suffix = 0, int* pmime_index = 0);
// PREAD - PWRITE
static bool pread(int _fd, void* buf, uint32_t count, uint32_t offset)
{
U_TRACE(1, "UFile::pread(%d,%p,%u,%u)", _fd, buf, count, offset)
if (U_SYSCALL(pread, "%d,%p,%u,%u", _fd, buf, count, offset) == (ssize_t)count) U_RETURN(true);
U_RETURN(false);
}
static bool pwrite(int _fd, const void* buf, uint32_t count, uint32_t offset)
{
U_TRACE(1, "UFile::pwrite(%d,%p,%u,%u)", _fd, buf, count, offset)
if (U_SYSCALL(pwrite, "%d,%p,%u,%u", _fd, buf, count, offset) == (ssize_t)count) U_RETURN(true);
U_RETURN(false);
}
bool pread( void* buf, uint32_t count, uint32_t offset);
bool pwrite(const void* buf, uint32_t count, uint32_t offset);
// SERVICES
static bool access(const char* path, int mode = R_OK | X_OK)
{
U_TRACE(1, "UFile::access(%S,%d)", path, mode)
if (U_SYSCALL(access, "%S,%d", U_PATH_CONV(path), mode) == 0) U_RETURN(true);
U_RETURN(false);
}
static bool stat(const char* path, struct stat* st)
{
U_TRACE(1, "UFile::stat(%S,%p)", path, st)
if (U_SYSCALL(stat, "%S,%p", U_PATH_CONV(path), st) == 0) U_RETURN(true);
U_RETURN(false);
}
static bool write(int _fd, const void* buf, uint32_t count)
{
U_TRACE(1, "UFile::write(%d,%p,%u)", _fd, buf, count)
if (U_SYSCALL(write, "%d,%p,%u", _fd, buf, count) == (ssize_t)count) U_RETURN(true);
U_RETURN(false);
}
static int writev(int _fd, const struct iovec* iov, int n)
{
U_TRACE(1, "UFile::writev(%d,%p,%d)", _fd, iov, n) // problem with sanitize address
int result = U_SYSCALL(writev, "%d,%p,%d", _fd, iov, n);
U_RETURN(result);
}
int writev(const struct iovec* iov, int n) const
{
U_TRACE(0, "UFile::writev(%p,%d)", iov, n)
U_CHECK_MEMORY
U_INTERNAL_ASSERT_DIFFERS(fd, -1)
U_INTERNAL_ASSERT_POINTER(path_relativ)
U_INTERNAL_DUMP("path_relativ(%u) = %.*S", path_relativ_len, path_relativ_len, path_relativ)
# ifdef U_COVERITY_FALSE_POSITIVE
if (fd <= 0) U_RETURN(0);
# endif
int result = UFile::writev(fd, iov, n);
U_RETURN(result);
}
bool write(const char* data, uint32_t sz, bool append = false, bool bmkdirs = false);
bool write(const struct iovec* iov, int n, bool append = false, bool bmkdirs = false);
bool write(const UString& data, bool append = false, bool bmkdirs = false)
{ return write(U_STRING_TO_PARAM(data), append, bmkdirs); }
static int setSysParam( const char* name, int value, bool force = false);
static int getSysParam( const char* name);
static UString getSysContent(const char* name);
static bool writeToTmp(const char* data, uint32_t sz, bool append, const char* fmt, ...);
static bool writeToTmp(const struct iovec* iov, int n, bool append, const char* fmt, ...);
static bool writeTo(const UString& path, const char* data, uint32_t sz, bool append = false, bool bmkdirs = false);
static bool writeTo(const UString& path, const struct iovec* iov, int n, bool append = false, bool bmkdirs = false);
static bool writeTo(const UString& path, const UString& data, bool append = false, bool bmkdirs = false)
{ return writeTo(path, U_STRING_TO_PARAM(data), append, bmkdirs); }
// symlink creates a symbolic link named newpath which contains the string oldpath (make one pathname be an alias for another)
static bool symlink(const char* oldpath, const char* newpath)
{
U_TRACE(1, "UFile::symlink(%S,%S)", oldpath, newpath)
# ifndef _MSWINDOWS_
if (U_SYSCALL(symlink, "%S,%S", oldpath, newpath) != -1) U_RETURN(true);
# endif
U_RETURN(false);
}
bool symlink(const char* newpath)
{
U_TRACE(0, "UFile::symlink(%S)", newpath)
U_CHECK_MEMORY
U_INTERNAL_ASSERT(pathname.isNullTerminated())
# ifndef _MSWINDOWS_
if (symlink(pathname.data(), newpath)) U_RETURN(true);
# endif
U_RETURN(false);
}
// make a FIFO special file (a named pipe)
static bool mkfifo(const char* _pathname, mode_t mode = S_IRUSR | S_IWUSR)
{
U_TRACE(1, "UFile::mkfifo(%S,%d)", _pathname, mode)
# ifndef _MSWINDOWS_
if (U_SYSCALL(mkfifo, "%S,%d", _pathname, mode) == 0) U_RETURN(true);
# endif
U_RETURN(false);
}
// Expands all symbolic links and resolves references to '/./', '/../' and extra '/' characters in the null
// terminated string named by path and stores the canonicalized absolute pathname in the return string.
// The resulting string will have no symbolic link, '/./' or '/../' components
static UString getRealPath(const char* path, bool brelativ = false);
// TEMP OP
// ----------------------------------------------------------------------------------------------------------------------
// create a unique temporary file
// ----------------------------------------------------------------------------------------------------------------------
// char pathname[] = "/tmp/dataXXXXXX"
// The last six characters of template must be XXXXXX and these are replaced with a string that makes the filename unique
// ----------------------------------------------------------------------------------------------------------------------
bool mkTemp(char* _template);
// --------------------------------------------------------------------------------------------------------------
// mkdtemp - create a unique temporary directory
// --------------------------------------------------------------------------------------------------------------
// The mkdtemp() function generates a uniquely-named temporary directory from template. The last six characters
// of template must be XXXXXX and these are replaced with a string that makes the directory name unique.
// The directory is then created with permissions 0700.
// Since it will be modified, template must not be a string constant, but should be declared as a character array
// --------------------------------------------------------------------------------------------------------------
static bool mkdtemp(UString& _template);
// DIR OP
static bool rmdir(const UString& dir, bool remove_all = false);
// If path includes more than one pathname component, remove it, then strip the last component
// and remove the resulting directory, etc., until all components have been removed.
// The pathname component must be empty...
static bool rmdirs(const UString& dir, bool remove_all = false);
// Creates all directories in this path. This method returns true if all directories in this path are created
static bool mkdirs(const char* path, mode_t mode = PERM_DIRECTORY);
// MEMORY POOL
static bool isAllocableFromPool(uint32_t sz)
{
U_TRACE(0, "UFile::isAllocableFromPool(%u)", sz)
# if defined(ENABLE_MEMPOOL)
U_INTERNAL_DUMP("nfree = %u pfree = %p", nfree, pfree)
if (sz > U_CAPACITY &&
nfree > (sz + rlimit_memfree))
{
U_RETURN(true);
}
# endif
U_RETURN(false);
}
static bool isLastAllocation(void* ptr, size_t sz)
{
U_TRACE(0, "UFile::isLastAllocation(%p,%lu)", ptr, sz)
# if defined(ENABLE_MEMPOOL)
U_INTERNAL_ASSERT_EQUALS(sz & U_PAGEMASK, 0)
U_INTERNAL_ASSERT(sz >= U_MAX_SIZE_PREALLOCATE)
U_INTERNAL_DUMP("nfree = %u pfree = %p", nfree, pfree)
if (pfree)
{
U_INTERNAL_ASSERT_MAJOR(nfree, rlimit_memfree)
if ((pfree - sz) == ptr) U_RETURN(true);
}
# endif
U_RETURN(false);
}
// DEBUG
#if defined(U_STDCPP_ENABLE) && defined(DEBUG)
const char* dump(bool reset) const;
#endif
protected:
uint32_t path_relativ_len, map_size; // size to mmap(), may be larger than the size of the file...
UString pathname;
char* map;
const char* path_relativ; // the string can be not writeable...
int fd;
static char* cwd_save;
static uint32_t cwd_save_len;
static char* pfree;
static uint32_t nfree, rlimit_memfree, rlimit_memalloc;
void substitute(UFile& file);
bool creatForWrite(bool append, bool bmkdirs);
void setPathRelativ(const UString* environment = 0);
void setPath(const UFile& file, char* buffer_path, const char* suffix, uint32_t len);
static void ftw_tree_up();
static void ftw_tree_push();
static void ftw_vector_push();
private:
#ifdef _MSWINDOWS_
uint64_t u_inode;
#endif
#ifdef U_COMPILER_DELETE_MEMBERS
UFile& operator=(const UFile&) = delete;
#else
UFile& operator=(const UFile&) { return *this; }
#endif
friend void ULib_init();
friend class URDB;
friend class UHTTP;
friend class UString;
friend class UDirWalk;
friend class UStringRep;
friend class UStringExt;
friend class UMemoryPool;
friend class UClientImage_Base;
template <class T> friend class URDBObjectHandler;
};
#endif