nim_duilib/base/file/file_util_posix.cpp
jiajia_deng 4933d1f2bc Remove dependency on shared
Signed-off-by: jiajia_deng <2894220@gmail.com>
2019-09-20 16:27:58 +08:00

237 lines
4.8 KiB
C++

// Copyright (c) 2011, NetEase Inc. All rights reserved.
//
// Author: rl
// Date: 2011/6/12
//
// Modified by wrt(guangguang)
// Date: 2013/9/5
//
// Utilities for file and filepath operation
#include "file_util.h"
#include "base/util/string_util.h"
#if defined(OS_POSIX)
#include <string>
#include <vector>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/errno.h>
#include <sys/stat.h>
namespace nbase
{
typedef struct stat stat_wrapper_t;
static int CallStat(const char *path, stat_wrapper_t *sb)
{
return stat(path, sb);
}
static int CallLstat(const char *path, stat_wrapper_t *sb)
{
return lstat(path, sb);
}
bool FilePathCurrentDirectory(std::string &directory_out)
{
char directory[512] = "";
if (!getcwd(directory, sizeof(directory)))
{
return false;
}
directory_out = directory;
directory_out.append(1, kFilePathSeparators[0]);
return true;
}
bool FilePathIsExist(const char *filepath_in, bool is_directory)
{
if (!is_directory)
return access(filepath_in, F_OK) == 0;
else
{
DIR *directory = opendir(filepath_in);
if (directory != NULL)
{
closedir(directory);
return true;
}
}
return false;
}
bool CreateDirectory(const std::string& full_path)
{
return CreateDirectory(full_path.c_str());
}
bool CreateDirectory(const char* full_path)
{
if (full_path == NULL)
return false;
std::list<std::string> subpaths;
ParsePathComponents(full_path, subpaths);
if (subpaths.empty())
return false;
// Collect a list of all parent directories.
auto curr = subpaths.begin();
for (auto prev = curr++; curr != subpaths.end(); curr++) {
*curr = *prev + *curr;
prev = curr;
}
// Iterate through the parents and create the missing ones.
for (auto i = subpaths.begin(); i != subpaths.end(); ++i) {
if (FilePathIsExist(i->c_str(), true))
continue;
if (mkdir(i->c_str(), 0700) == 0)
continue;
// Mkdir failed, but it might have failed with EEXIST, or some other
// error due to the the directory appearing out of thin air. This can
// occur if two processes are trying to create the same file system tree
// at the same time. Check to see if it exists and make sure it is a
// directory.
if (!FilePathIsExist(i->c_str(), true))
return false;
}
return true;
}
FILE* OpenFile(const char *filepath, const char *mode)
{
FILE* file = NULL;
do
{
file = fopen(filepath, mode);
} while (!file && errno == EINTR);
return file;
}
int ReadFile(const char *filepath, void *data_out, size_t size)
{
int fd = open(filepath, O_RDONLY);
if (fd < 0)
return -1;
ssize_t bytes_read = read(fd, data_out, size);
if (int ret = close(fd) < 0)
return ret;
return bytes_read;
}
int WriteFile(const char *filepath, const void *data, size_t size)
{
int fd = creat(filepath, 0666);
if (fd < 0)
return -1;
ssize_t bytes_written_total = 0;
for (ssize_t bytes_written_partial = 0; bytes_written_total < size;
bytes_written_total += bytes_written_partial)
{
bytes_written_partial =
write(fd, data + bytes_written_total,
size - bytes_written_total);
if (bytes_written_partial < 0)
return -1;
}
if (int ret = close(fd) < 0)
return ret;
return bytes_written_total;
}
bool CopyFile(const std::string &from_path, const std::string &to_path)
{
int infile = open(from_path.c_str(), O_RDONLY);
if (infile < 0)
return false;
int outfile = creat(to_path.c_str(), 0666);
if (outfile < 0)
{
close(infile);
return false;
}
const size_t kBufferSize = 32768;
std::vector<char> buffer(kBufferSize);
bool result = true;
while (result)
{
ssize_t bytes_read = read(infile, &buffer[0], buffer.size());
if (bytes_read < 0)
{
result = false;
break;
}
if (bytes_read == 0)
break;
// Allow for partial writes
ssize_t bytes_written_per_read = 0;
do
{
ssize_t bytes_written_partial = write(
outfile,
&buffer[bytes_written_per_read],
bytes_read - bytes_written_per_read);
if (bytes_written_partial < 0)
{
result = false;
break;
}
bytes_written_per_read += bytes_written_partial;
} while (bytes_written_per_read < bytes_read);
}
if (close(infile) < 0)
result = false;
if (close(outfile) < 0)
result = false;
return result;
}
bool DeleteFile(const std::string &filepath)
{
const char* path_str = filepath.c_str();
stat_wrapper_t file_info;
int test = CallStat(path_str, &file_info);
if (test != 0)
{
// The Windows version defines this condition as success.
bool ret = (errno == ENOENT || errno == ENOTDIR);
return ret;
}
if (!S_ISDIR(file_info.st_mode))
return (unlink(path_str) == 0);
return true;
}
int64_t GetFileSize(const std::string &filepath)
{
const char* path_str = filepath.c_str();
stat_wrapper_t file_info;
int test = CallStat(path_str, &file_info);
if (test != 0)
return -1;
if (!S_ISDIR(file_info.st_mode))
return file_info.st_size;
return -1;
}
} // namespace nbase
#endif // OS_POSIX