Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/core/StarFile_unix.cpp
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-06-20 14:33:09 +1000
commit6352e8e3196f78388b6c771073f9e03eaa612673 (patch)
treee23772f79a7fbc41bc9108951e9e136857484bf4 /source/core/StarFile_unix.cpp
parent6741a057e5639280d85d0f88ba26f000baa58f61 (diff)
everything everywhere
all at once
Diffstat (limited to 'source/core/StarFile_unix.cpp')
-rw-r--r--source/core/StarFile_unix.cpp295
1 files changed, 295 insertions, 0 deletions
diff --git a/source/core/StarFile_unix.cpp b/source/core/StarFile_unix.cpp
new file mode 100644
index 0000000..aa22bc8
--- /dev/null
+++ b/source/core/StarFile_unix.cpp
@@ -0,0 +1,295 @@
+#include "StarFile.hpp"
+#include "StarFormat.hpp"
+#include "StarRandom.hpp"
+#include "StarEncode.hpp"
+
+#include <errno.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#ifdef STAR_SYSTEM_MACOSX
+#include <mach-o/dyld.h>
+#elif defined STAR_SYSTEM_FREEBSD
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#endif
+
+namespace Star {
+
+namespace {
+ int fdFromHandle(void* ptr) {
+ return (int)(intptr_t)ptr;
+ }
+
+ void* handleFromFd(int handle) {
+ return (void*)(intptr_t)handle;
+ }
+}
+
+String File::convertDirSeparators(String const& path) {
+ return path.replace("\\", "/");
+}
+
+String File::currentDirectory() {
+ char buffer[PATH_MAX];
+ if (::getcwd(buffer, PATH_MAX) == NULL)
+ throw IOException("getcwd failed");
+
+ return String(buffer);
+}
+
+void File::changeDirectory(const String& dirName) {
+ if (::chdir(dirName.utf8Ptr()) != 0)
+ throw IOException(strf("could not change directory to %s", dirName));
+}
+
+void File::makeDirectory(String const& dirName) {
+ if (::mkdir(dirName.utf8Ptr(), 0777) != 0)
+ throw IOException(strf("could not create directory '%s', %s", dirName, strerror(errno)));
+}
+
+List<pair<String, bool>> File::dirList(const String& dirName, bool skipDots) {
+ List<std::pair<String, bool>> fileList;
+ DIR* directory = ::opendir(dirName.utf8Ptr());
+ if (directory == NULL)
+ throw IOException::format("dirList failed on dir: '%s'", dirName);
+
+ for (dirent* entry = ::readdir(directory); entry != NULL; entry = ::readdir(directory)) {
+ String entryString = entry->d_name;
+ if (!skipDots || (entryString != "." && entryString != "..")) {
+ bool isDirectory = false;
+ if (entry->d_type == DT_DIR) {
+ isDirectory = true;
+ } else if (entry->d_type == DT_LNK || entry->d_type == DT_UNKNOWN) {
+ isDirectory = File::isDirectory(File::relativeTo(dirName, entryString));
+ }
+ fileList.append({entryString, isDirectory});
+ }
+ }
+ ::closedir(directory);
+
+ return fileList;
+}
+
+String File::baseName(const String& fileName) {
+ String ret;
+
+ std::string file = fileName.utf8();
+ char* fn = new char[file.size() + 1];
+ std::copy(file.begin(), file.end(), fn);
+ fn[file.size()] = 0;
+ ret = String(::basename(fn));
+ delete[] fn;
+
+ return ret;
+}
+
+String File::dirName(const String& fileName) {
+ String ret;
+
+ std::string file = fileName.utf8();
+ char* fn = new char[file.size() + 1];
+ std::copy(file.begin(), file.end(), fn);
+ fn[file.size()] = 0;
+ ret = String(::dirname(fn));
+ delete[] fn;
+
+ return ret;
+}
+
+String File::relativeTo(String const& relativeTo, String const& path) {
+ if (path.beginsWith("/"))
+ return path;
+ return relativeTo.trimEnd("/") + '/' + path;
+}
+
+String File::fullPath(const String& fileName) {
+ char buffer[PATH_MAX];
+
+ if (::realpath(fileName.utf8Ptr(), buffer) == NULL)
+ throw IOException::format("realpath failed on file: '%s' problem path was: '%s'", fileName, buffer);
+
+ return String(buffer);
+}
+
+String File::temporaryFileName() {
+ return relativeTo(P_tmpdir, strf("starbound.tmpfile.%s", hexEncode(Random::randBytes(16))));
+}
+
+FilePtr File::temporaryFile() {
+ return open(temporaryFileName(), IOMode::ReadWrite);
+}
+
+FilePtr File::ephemeralFile() {
+ auto file = make_shared<File>();
+ ByteArray path = ByteArray::fromCStringWithNull(relativeTo(P_tmpdir, "starbound.tmpfile.XXXXXXXX").utf8Ptr());
+ auto res = mkstemp(path.ptr());
+ if (res < 0)
+ throw IOException::format("tmpfile error: %s", strerror(errno));
+ if (::unlink(path.ptr()) < 0)
+ throw IOException::format("Could not remove mkstemp file when creating ephemeralFile: %s", strerror(errno));
+ file->m_file = handleFromFd(res);
+ file->setMode(IOMode::ReadWrite);
+ return file;
+}
+
+String File::temporaryDirectory() {
+ String dirname = relativeTo(P_tmpdir, strf("starbound.tmpdir.%s", hexEncode(Random::randBytes(16))));
+ makeDirectory(dirname);
+ return dirname;
+}
+
+bool File::exists(String const& path) {
+ struct stat st_buf;
+ int status = stat(path.utf8Ptr(), &st_buf);
+ return status == 0;
+}
+
+bool File::isFile(String const& path) {
+ struct stat st_buf;
+ int status = stat(path.utf8Ptr(), &st_buf);
+ if (status != 0)
+ return false;
+
+ return S_ISREG(st_buf.st_mode);
+}
+
+bool File::isDirectory(String const& path) {
+ struct stat st_buf;
+ int status = stat(path.utf8Ptr(), &st_buf);
+ if (status != 0)
+ return false;
+
+ return S_ISDIR(st_buf.st_mode);
+}
+
+void File::remove(String const& filename) {
+ if (::remove(filename.utf8Ptr()) < 0)
+ throw IOException::format("remove error: %s", strerror(errno));
+}
+
+void File::rename(String const& source, String const& target) {
+ if (::rename(source.utf8Ptr(), target.utf8Ptr()) < 0)
+ throw IOException::format("rename error: %s", strerror(errno));
+}
+
+void File::overwriteFileWithRename(char const* data, size_t len, String const& filename, String const& newSuffix) {
+ String newFile = filename + newSuffix;
+ writeFile(data, len, newFile);
+ File::rename(newFile, filename);
+}
+
+void* File::fopen(char const* filename, IOMode mode) {
+ int oflag = 0;
+
+ if (mode & IOMode::Read && mode & IOMode::Write)
+ oflag |= O_RDWR | O_CREAT;
+ else if (mode & IOMode::Read)
+ oflag |= O_RDONLY;
+ else if (mode & IOMode::Write)
+ oflag |= O_WRONLY | O_CREAT;
+
+ if (mode & IOMode::Truncate)
+ oflag |= O_TRUNC;
+
+ int fd = ::open(filename, oflag, 0666);
+ if (fd < 0)
+ throw IOException::format("Error opening file '%s', error: %s", filename, strerror(errno));
+
+ if (mode & IOMode::Append) {
+ if (lseek(fd, 0, SEEK_END) < 0)
+ throw IOException::format("Error opening file '%s', cannot seek: %s", filename, strerror(errno));
+ }
+
+ return handleFromFd(fd);
+}
+
+void File::fseek(void* f, StreamOffset offset, IOSeek seekMode) {
+ auto fd = fdFromHandle(f);
+ int retCode;
+ if (seekMode == IOSeek::Relative)
+ retCode = lseek(fd, offset, SEEK_CUR);
+ else if (seekMode == IOSeek::Absolute)
+ retCode = lseek(fd, offset, SEEK_SET);
+ else
+ retCode = lseek(fd, offset, SEEK_END);
+
+ if (retCode < 0)
+ throw IOException::format("Seek error: %s", strerror(errno));
+}
+
+StreamOffset File::ftell(void* f) {
+ return lseek(fdFromHandle(f), 0, SEEK_CUR);
+}
+
+size_t File::fread(void* file, char* data, size_t len) {
+ if (len == 0)
+ return 0;
+
+ auto fd = fdFromHandle(file);
+ auto ret = ::read(fd, data, len);
+ if (ret < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ return 0;
+ throw IOException::format("Read error: %s", strerror(errno));
+ } else {
+ return ret;
+ }
+}
+
+size_t File::fwrite(void* file, char const* data, size_t len) {
+ if (len == 0)
+ return 0;
+
+ auto fd = fdFromHandle(file);
+ auto ret = ::write(fd, data, len);
+ if (ret < 0) {
+ if (errno == EAGAIN || errno == EINTR)
+ return 0;
+ throw IOException::format("Write error: %s", strerror(errno));
+ } else {
+ return ret;
+ }
+}
+
+void File::fsync(void* file) {
+ auto fd = fdFromHandle(file);
+#ifdef STAR_SYSTEM_LINUX
+ ::fdatasync(fd);
+#else
+ ::fsync(fd);
+#endif
+}
+
+void File::fclose(void* file) {
+ if (::close(fdFromHandle(file)) < 0)
+ throw IOException::format("Close error: %s", strerror(errno));
+}
+
+StreamOffset File::fsize(void* file) {
+ StreamOffset pos = ftell(file);
+ StreamOffset size = lseek(fdFromHandle(file), 0, SEEK_END);
+ lseek(fdFromHandle(file), pos, SEEK_SET);
+ return size;
+}
+
+size_t File::pread(void* file, char* data, size_t len, StreamOffset position) {
+ return ::pread(fdFromHandle(file), data, len, position);
+}
+
+size_t File::pwrite(void* file, char const* data, size_t len, StreamOffset position) {
+ return ::pwrite(fdFromHandle(file), data, len, position);
+}
+
+void File::resize(void* f, StreamOffset size) {
+ if (::ftruncate(fdFromHandle(f), size) < 0)
+ throw IOException::format("resize error: %s", strerror(errno));
+}
+
+}