mirror of https://gitee.com/bigwinds/arangodb
438 lines
10 KiB
C
438 lines
10 KiB
C
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief file functions
|
|
///
|
|
/// @file
|
|
///
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2010-2011 triagens GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
///
|
|
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// @author Dr. Frank Celler
|
|
/// @author Copyright 2011, triagens GmbH, Cologne, Germany
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "files.h"
|
|
|
|
#ifdef TRI_HAVE_DIRENT_H
|
|
#include <dirent.h>
|
|
#endif
|
|
|
|
#ifdef TRI_HAVE_DIRECT_H
|
|
#include <direct.h>
|
|
#endif
|
|
|
|
#include <Basics/logging.h>
|
|
#include <Basics/strings.h>
|
|
#include <Basics/string-buffer.h>
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// --SECTION-- public functions
|
|
// -----------------------------------------------------------------------------
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @addtogroup Files
|
|
/// @{
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief checks if path is a directory
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool TRI_IsDirectory (char const* path) {
|
|
struct stat stbuf;
|
|
int res;
|
|
|
|
res = stat(path, &stbuf);
|
|
|
|
return (res == 0) && ((stbuf.st_mode & S_IFMT) == S_IFDIR);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief checks if file exists
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool TRI_ExistsFile (char const* path) {
|
|
struct stat stbuf;
|
|
int res;
|
|
|
|
res = stat(path, &stbuf);
|
|
|
|
return res == 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a directory
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool TRI_CreateDirectory (char const* path) {
|
|
int res;
|
|
|
|
res = TRI_MKDIR(path, 0777);
|
|
|
|
if (res != 0) {
|
|
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief extracts the dirname
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char* TRI_Dirname (char const* path) {
|
|
size_t n;
|
|
size_t m;
|
|
char const* p;
|
|
|
|
n = strlen(path);
|
|
m = 0;
|
|
|
|
if (1 < n) {
|
|
if (path[n - 1] == '/') {
|
|
m = 1;
|
|
}
|
|
}
|
|
|
|
if (n == 0) {
|
|
return TRI_DuplicateString(".");
|
|
}
|
|
else if (n == 1 && *path == '/') {
|
|
return TRI_DuplicateString("/");
|
|
}
|
|
else if (n - m == 1 && *path == '.') {
|
|
return TRI_DuplicateString(".");
|
|
}
|
|
else if (n - m == 2 && path[0] == '.' && path[1] == '.') {
|
|
return TRI_DuplicateString("..");
|
|
}
|
|
|
|
for (p = path + (n - m - 1); path < p; --p) {
|
|
if (*p == '/') {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (path == p) {
|
|
if (*p == '/') {
|
|
return TRI_DuplicateString("/");
|
|
}
|
|
else {
|
|
return TRI_DuplicateString(".");
|
|
}
|
|
}
|
|
|
|
n = p - path;
|
|
|
|
return TRI_DuplicateString2(path, n);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief extracts the basename
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char* TRI_Basename (char const* path) {
|
|
size_t n;
|
|
size_t m;
|
|
char const* p;
|
|
|
|
n = strlen(path);
|
|
m = 0;
|
|
|
|
if (1 < n) {
|
|
if (path[n - 1] == '/') {
|
|
m = 1;
|
|
}
|
|
}
|
|
|
|
if (n == 0) {
|
|
return TRI_DuplicateString("");
|
|
}
|
|
else if (n == 1 && *path == '/') {
|
|
return TRI_DuplicateString("");
|
|
}
|
|
else if (n - m == 1 && *path == '.') {
|
|
return TRI_DuplicateString("");
|
|
}
|
|
else if (n - m == 2 && path[0] == '.' && path[1] == '.') {
|
|
return TRI_DuplicateString("");
|
|
}
|
|
|
|
for (p = path + (n - m - 1); path < p; --p) {
|
|
if (*p == '/') {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (path == p) {
|
|
if (*p == '/') {
|
|
return TRI_DuplicateString2(path + 1, n - m);
|
|
}
|
|
}
|
|
|
|
n -= p - path;
|
|
|
|
return TRI_DuplicateString2(p + 1, n - 1);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a filename
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char* TRI_Concatenate2File (char const* path, char const* name) {
|
|
return TRI_Concatenate3String(path, "/", name);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief creates a filename
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char* TRI_Concatenate3File (char const* path1, char const* path2, char const* name) {
|
|
return TRI_Concatenate5String(path1, "/", path2, "/", name);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief returns a list of files in path
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
TRI_vector_string_t TRI_FilesDirectory (char const* path) {
|
|
TRI_vector_string_t result;
|
|
|
|
#ifdef TRI_HAVE_WIN32_LIST_FILES
|
|
|
|
struct _finddata_t fd;
|
|
intptr_t handle;
|
|
string filter;
|
|
|
|
TRI_InitVectorString(&result);
|
|
|
|
filter = directory + "\\*";
|
|
handle = _findfirst(filter.c_str(), &fd);
|
|
|
|
if (handle == -1) {
|
|
return result;
|
|
}
|
|
|
|
do {
|
|
if (strcmp(fd.name, ".") != 0 && strcmp(fd.name, "..") != 0) {
|
|
result.push_back(fd.name);
|
|
}
|
|
} while(_findnext(handle, &fd) != -1);
|
|
|
|
_findclose(handle);
|
|
|
|
#else
|
|
|
|
DIR * d;
|
|
struct dirent * de;
|
|
|
|
TRI_InitVectorString(&result);
|
|
|
|
d = opendir(path);
|
|
|
|
if (d == 0) {
|
|
return result;
|
|
}
|
|
|
|
de = readdir(d);
|
|
|
|
while (de != 0) {
|
|
if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) {
|
|
|
|
TRI_PushBackVectorString(&result, TRI_DuplicateString(de->d_name));
|
|
}
|
|
|
|
de = readdir(d);
|
|
}
|
|
|
|
closedir(d);
|
|
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief renames a file
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool TRI_RenameFile (char const* old, char const* filename) {
|
|
int res;
|
|
|
|
res = rename(old, filename);
|
|
|
|
if (res != 0) {
|
|
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
|
LOG_TRACE("cannot rename file from '%s' to '%s': %s", old, filename, TRI_LAST_ERROR_STR);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief unlinks a file
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool TRI_UnlinkFile (char const* filename) {
|
|
int res;
|
|
|
|
res = unlink(filename);
|
|
|
|
if (res != 0) {
|
|
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
|
LOG_TRACE("cannot unlink file '%s': %s", filename, TRI_LAST_ERROR_STR);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief reads into a buffer from a file
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool TRI_ReadPointer (int fd, void* buffer, size_t length) {
|
|
char* ptr;
|
|
|
|
ptr = buffer;
|
|
|
|
while (0 < length) {
|
|
ssize_t n = read(fd, ptr, length);
|
|
|
|
if (n < 0) {
|
|
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
|
LOG_ERROR("cannot read: %s", TRI_LAST_ERROR_STR);
|
|
return false;
|
|
}
|
|
else if (n == 0) {
|
|
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
|
LOG_ERROR("cannot read, end-of-file");
|
|
return false;
|
|
}
|
|
|
|
ptr += n;
|
|
length -= n;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief writes buffer to a file
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool TRI_WritePointer (int fd, void const* buffer, size_t length) {
|
|
char const* ptr;
|
|
|
|
ptr = buffer;
|
|
|
|
while (0 < length) {
|
|
ssize_t n = write(fd, ptr, length);
|
|
|
|
if (n < 0) {
|
|
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
|
LOG_ERROR("cannot write: %s", TRI_LAST_ERROR_STR);
|
|
return false;
|
|
}
|
|
|
|
ptr += n;
|
|
length -= n;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief fsyncs a file
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool TRI_fsync (int fd) {
|
|
int res = fsync(fd);
|
|
|
|
#ifdef __APPLE__
|
|
|
|
if (res == 0) {
|
|
res = fcntl(fd, F_FULLFSYNC, 0);
|
|
}
|
|
|
|
#endif
|
|
|
|
if (res == 0) {
|
|
return true;
|
|
}
|
|
else {
|
|
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @brief slurps in a file
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char* TRI_SlurpFile (char const* filename) {
|
|
TRI_string_buffer_t result;
|
|
char buffer[10240];
|
|
int fd;
|
|
|
|
fd = TRI_OPEN(filename, O_RDONLY);
|
|
|
|
if (fd == -1) {
|
|
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
|
return NULL;
|
|
}
|
|
|
|
TRI_InitStringBuffer(&result);
|
|
|
|
while (true) {
|
|
ssize_t n;
|
|
|
|
n = TRI_READ(fd, buffer, sizeof(buffer));
|
|
|
|
if (n == 0) {
|
|
break;
|
|
}
|
|
|
|
if (n < 0) {
|
|
TRI_CLOSE(fd);
|
|
|
|
TRI_DestroyStringBuffer(&result);
|
|
|
|
TRI_set_errno(TRI_ERROR_SYS_ERROR);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
TRI_AppendString2StringBuffer(&result, buffer, n);
|
|
}
|
|
|
|
TRI_CLOSE(fd);
|
|
|
|
return result._buffer;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/// @}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Local Variables:
|
|
// mode: outline-minor
|
|
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\)"
|
|
// End:
|