Initial commit

This commit is contained in:
2022-12-04 22:47:05 +08:00
commit 682ba1f45c
17 changed files with 1639 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
project(PyNFS)
set(SRC_FILES
"pynfs.h"
"pynfs.cpp"
"NFS.h"
"NFS.cpp"
"NFSFH.h"
"NFSFH.cpp"
"wildcards.hpp"
"fileutils.hpp")
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
find_package(Python2 COMPONENTS Interpreter Development REQUIRED)
message(STATUS "Project : ${PROJECT_NAME}")
message(STATUS "Python Site : ${Python2_SITELIB}")
message(STATUS "Python Include Dirs : ${Python2_INCLUDE_DIRS}")
message(STATUS "Python Library Dirs : ${Python2_LIBRARY_DIRS}")
message(STATUS "Python Library : ${Python2_LIBRARIES}")
include_directories(
${Python2_INCLUDE_DIRS}
"${CMAKE_SOURCE_DIR}/vendor/libnfs/include"
"${CMAKE_SOURCE_DIR}/vendor/pybind11/include"
"${CMAKE_SOURCE_DIR}/vendor/pystring/include"
)
link_directories(
${Python2_LIBRARY_DIRS}
"${CMAKE_SOURCE_DIR}/vendor/libnfs/lib"
"${CMAKE_SOURCE_DIR}/vendor/pystring/lib"
)
add_library(${PROJECT_NAME} SHARED ${SRC_FILES})
add_custom_command(TARGET ${PROJECT_NAME}
POST_BUILD COMMAND "copy" ARGS "$(TargetDir)$(TargetFileName)" "${Python2_SITELIB}\\${PROJECT_NAME}" "/Y/B")
target_link_libraries(${PROJECT_NAME} nfs pystring ${Python2_LIBRARIES})
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "_${PROJECT_NAME}")
set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".pyd")
install(TARGETS ${PROJECT_NAME}
RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}")
install(FILES "${CMAKE_SOURCE_DIR}/python/${PROJECT_NAME}/__init__.py"
DESTINATION ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME})
+761
View File
@@ -0,0 +1,761 @@
#include "NFS.h"
#include "NFSFH.h"
#include "fileutils.hpp"
#include "wildcards.hpp"
namespace pynfs
{
NFS::NFS() : _nfs(NULL), _url(NULL)
{
#ifdef WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("Failed to start Winsock2\n");
return;
}
#endif
_nfs = nfs_init_context();
if (_nfs == NULL)
{
printf("failed to init context\n");
return;
}
};
NFS::NFS(std::string path) : _nfs(NULL), _url(NULL)
{
#ifdef WIN32
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("Failed to start Winsock2\n");
return;
}
#endif
_nfs = nfs_init_context();
if (_nfs == NULL)
{
printf("Failed to init context\n");
return;
}
if (openurl(path) != 0)
{
printf("Failed to openurl(\"%s\")", path.c_str());
return;
}
}
NFS::~NFS()
{
free_context();
}
int NFS::openurl(std::string path)
{
_url = nfs_parse_url_dir(_nfs, path.c_str());
if (_url == NULL)
{
fprintf(stderr, "%s\n", nfs_get_error(_nfs));
return 1;
}
if (nfs_mount(_nfs, _url->server, _url->path) != 0)
{
fprintf(stderr, "Failed to mount nfs share : %s\n", nfs_get_error(_nfs));
return 1;
}
return 0;
}
std::vector<std::string> NFS::listdir(std::string path, bool recursive = false,
bool with_file = true, bool with_dir = true, std::string pattern = "*")
{
int ret;
struct nfsdirent *nfsdirent;
struct nfsdir *nfsdir;
std::vector<std::string> result;
if ((ret = nfs_opendir(_nfs, path.c_str(), &nfsdir)) != 0)
{
char error[1024];
sprintf(error, "Failed to opendir(\"%s\"): %s\n", path.c_str(),
nfs_get_error(_nfs));
free_context();
throw PyNFSError(error);
}
std::vector<std::string> patterns;
pystring::split(pattern, patterns, ",");
while ((nfsdirent = nfs_readdir(_nfs, nfsdir)) != NULL)
{
if (!strcmp(nfsdirent->name, ".") || !strcmp(nfsdirent->name, ".."))
{
continue;
}
std::string fpath = pystring::os::path::join_posix(path, nfsdirent->name);
if (recursive && (nfsdirent->mode & S_IFMT) == S_IFDIR)
{
std::vector<std::string> fpathes = listdir(fpath, recursive, with_file, with_dir, pattern);
for (auto p : fpathes)
{
for (auto ptn : patterns)
{
if (match(ptn.c_str(), p.c_str()))
{
result.push_back(p);
}
}
}
if (with_dir)
{
for (auto ptn : patterns)
{
if (match(ptn.c_str(), fpath.c_str()))
{
result.push_back(fpath);
}
}
}
}
else
{
if (with_file)
{
for (auto ptn : patterns)
{
if (match(ptn.c_str(), fpath.c_str()))
{
result.push_back(fpath);
}
}
}
}
}
nfs_closedir(_nfs, nfsdir);
return result;
}
int NFS::mkdir(std::string path)
{
// https://github.com/sahlberg/libnfs/issues/181
// Get mkdir permission with uid, nfs://address/nfs_share/?uid=0
int ret;
if ((ret = nfs_mkdir(_nfs, path.c_str())) != 0)
{
// fprintf(stderr, "Failed to mkdir: %s\n", nfs_get_error(nfs));
char error[1024];
sprintf(error, "Failed to mkdir(\"%s\"): %s\n", path.c_str(),
nfs_get_error(_nfs));
free_context();
throw PyNFSError(error);
}
return ret;
}
void NFS::rmtree(std::string path)
{
for (auto p : listdir(path))
{
std::string fpath = pystring::os::path::join_posix(path, p);
if (isdir(fpath))
{
rmtree(fpath);
}
else
{
remove(fpath);
}
}
rmdir(path);
}
int NFS::rmdir(std::string path)
{
int ret;
if ((ret = nfs_rmdir(_nfs, path.c_str())) != 0)
{
char error[1024];
sprintf(error, "Failed to rmdir(\"%s\"): %s\n", path.c_str(),
nfs_get_error(_nfs));
free_context();
throw PyNFSError(error);
}
return ret;
}
int NFS::remove(std::string path)
{
int ret;
if ((ret = nfs_unlink(_nfs, path.c_str())) != 0)
{
char error[1024];
sprintf(error, "Failed to unlink(\"%s\"): %s\n", path.c_str(),
nfs_get_error(_nfs));
free_context();
throw PyNFSError(error);
}
return ret;
}
int NFS::chdir(std::string path)
{
int ret;
if ((ret = nfs_chdir(_nfs, path.c_str())) != 0)
{
char error[1024];
sprintf(error, "Failed to chdir(\"%s\"): %s\n", path.c_str(),
nfs_get_error(_nfs));
free_context();
throw PyNFSError(error);
}
return 0;
}
void NFS::makedirs(std::string path)
{
std::vector<std::string> result;
pystring::split(pystring::replace(path, "\\", "/"), result, "/");
std::string npath = "/";
for (auto p : result)
{
npath = pystring::os::path::join_posix(npath, p);
if (exists(npath))
continue;
mkdir(npath);
}
}
struct nfs_stat_64 NFS::fstat(std::string path)
{
struct nfs_stat_64 stat;
if (nfs_stat64(_nfs, path.c_str(), &stat) != 0)
{
// fprintf(stderr, "Failed to stat file : %s\n", nfs_get_error(nfs));
char error[1024];
sprintf(error, "Failed to stat file: %s\n",
nfs_get_error(_nfs));
free_context();
throw PyNFSError(error);
}
return stat;
}
int NFS::chmod(std::string path, int mode)
{
int ret;
if ((ret = nfs_chmod(_nfs, path.c_str(), mode)) != 0)
{
//fprintf(stderr, "Failed to chmod(): %s\n", nfs_get_error(nfs));
char error[1024];
sprintf(error, "Failed to chmod(): %s\n",
nfs_get_error(_nfs));
free_context();
throw PyNFSError(error);
}
return ret;
}
int NFS::chown(std::string path, int uid, int gid)
{
int ret;
if ((ret = nfs_chown(_nfs, path.c_str(), uid, gid)) != 0)
{
char error[1024];
sprintf(error, "Failed to chown(): %s\n",
nfs_get_error(_nfs));
free_context();
throw PyNFSError(error);
}
return ret;
}
bool NFS::exists(std::string path)
{
struct nfs_stat_64 stat;
if (nfs_stat64(_nfs, path.c_str(), &stat) != 0)
{
return false;
}
return true;
}
bool NFS::isfile(std::string path)
{
struct nfs_stat_64 st = fstat(path);
py::object isreg = py::module_::import("stat").attr("S_ISREG")(st.nfs_mode);
return isreg.cast<bool>();
}
bool NFS::isdir(std::string path)
{
struct nfs_stat_64 st = fstat(path);
py::object isdir = py::module_::import("stat").attr("S_ISDIR")(st.nfs_mode);
return isdir.cast<bool>();
}
time_t NFS::getmtime(std::string path)
{
struct nfs_stat_64 st = fstat(path);
return st.nfs_mtime;
}
time_t NFS::getatime(std::string path)
{
struct nfs_stat_64 st = fstat(path);
return st.nfs_atime;
}
time_t NFS::getctime(std::string path)
{
struct nfs_stat_64 st = fstat(path);
return st.nfs_ctime;
}
std::vector<std::string> NFS::glob(std::string path, bool recursive)
{
return std::vector<std::string>();
}
void NFS::set_uid(int uid)
{
nfs_set_uid(_nfs, uid);
}
void NFS::set_gid(int gid)
{
nfs_set_gid(_nfs, gid);
}
std::string NFS::getcwd()
{
const char *cwd[1024];
nfs_getcwd(_nfs, cwd);
return std::string(*cwd);
}
void NFS::free_context()
{
if (_url != NULL)
{
nfs_destroy_url(_url);
_url = NULL;
}
if (_nfs != NULL)
{
nfs_destroy_context(_nfs);
_nfs = NULL;
}
}
int NFS::rename(std::string old_path, std::string new_path)
{
int ret;
if ((ret = nfs_rename(_nfs, old_path.c_str(), new_path.c_str())) != 0)
{
//fprintf(stderr, "Failed to rename(): %s\n", nfs_get_error(nfs));
char error[1024];
sprintf(error, "Failed to rename(\"%s\", \"%s\"): %s\n",
old_path.c_str(), new_path.c_str(),
nfs_get_error(_nfs));
throw PyNFSError(error);
}
return ret;
}
int NFS::symlink(std::string target, std::string linkname)
{
int ret;
if ((ret = nfs_symlink(_nfs, target.c_str(), linkname.c_str())) != 0)
{
char error[1024];
sprintf(error, "Failed to symlink(\"%s\", \"%s\"): %s\n",
target.c_str(), linkname.c_str(),
nfs_get_error(_nfs));
throw PyNFSError(error);
}
return ret;
}
std::shared_ptr<NFSFH> NFS::fopen(std::string path, std::string mode)
{
/*std::cout << getcwd() << std::endl;
if (!pystring::startswith(path, "nfs://")) {
char _path[1024];
sprintf(_path, "nfs://%s%s/%s",
_url->server, _url->path, path.c_str());
return NFSFH(_nfs, _path, mode);
}
else {
return NFSFH(_nfs, path, mode);
}*/
struct file_context *ctx = new file_context;
if (ctx == NULL)
{
fprintf(stderr, "Failed to malloc file_context\n");
return NULL;
}
ctx->nfs = _nfs;
ctx->url = _url;
return std::make_shared<NFSFH>(ctx, path, mode);
}
int NFS::put(std::string nfs_dst, std::string src, bool recursive = true, std::string pattern = "*")
{
std::cout << "put() : " << src << std::endl;
struct stat info;
std::string cwd = getcwd();
std::string dst_path = pystring::os::path::join_posix(cwd, nfs_dst);
// Destination must be directory
if (!pystring::endswith(dst_path, "/"))
{
dst_path = dst_path + "/";
}
if (!exists(dst_path))
{
makedirs(dst_path);
}
if (!fu::exists(src))
{
fprintf(stderr, "src path \"%s\" not exists.", src.c_str());
return 1;
}
if (fu::isdir(src))
{
putdir(nfs_dst, src, recursive, pattern);
}
else
{
std::string src_file_path = src;
std::string src_file = pystring::os::path::basename(src_file_path);
std::string dst_file_path = pystring::os::path::join_posix(dst_path, src_file);
putfile(dst_file_path, src_file_path);
}
return 0;
}
int NFS::putdir(std::string nfs_dst, std::string src, bool recursive, std::string pattern = "*")
{
// dst : ./dst
// src : C:/xx/Python27
// C:/xx/Python27/a/a.pyd --> ./dst/Python27/a/a.pyd
// dst : ./dst
// src : C:/xx/Python27/
// C:/xx/Python27/a/a.pyd --> ./dst/a/a.pyd
std::cout << "putdir() : " << src << std::endl;
std::vector<std::string> src_pathes = fu::listdir(src, recursive, true, true, pattern);
for (auto src_path : src_pathes)
{
//std::string src_path_rel = pystring::replace(src_path, src, "");
std::string src_path_rel = pystring::slice(src_path, src.length());
if (!pystring::endswith(src, "/"))
{
std::string src_dirname = pystring::os::path::dirname(src);
src_path_rel = pystring::slice(src_path, src_dirname.length());
//src_path_rel = pystring::replace(src_path, src_dirname, "");
}
if (pystring::startswith(src_path_rel, "/"))
{
src_path_rel = pystring::slice(src_path_rel, 1);
}
std::string dst_path = pystring::os::path::join_posix(nfs_dst, src_path_rel);
if (!fu::exists(src_path))
{
fprintf(stderr, "Failed to stat source file : %s", src_path.c_str());
continue;
}
if (fu::isdir(src_path))
{
makedirs(dst_path);
}
else
{
putfile(dst_path, src_path);
}
}
return 0;
}
int NFS::putfile(std::string nfs_dst, std::string src)
{
struct stat st;
off_t off;
ssize_t count;
std::string src_file_path = src;
//int fd = fu::open(src_file_path, O_RDONLY | O_BINARY);
int fd = fu::open(src_file_path, "rb");
if (fd < 0)
{
fprintf(stderr, "Failed to open file for reading : \"%s\"\n", src_file_path.c_str());
return 1;
}
nfs_dst = pystring::replace(nfs_dst, "\\", "/");
std::string dst_file_path = nfs_dst;
std::string dst_dir = pystring::os::path::dirname(dst_file_path);
// Destination is directory
if (!exists(dst_dir))
{
makedirs(dst_dir);
}
auto nfsfh = fopen(dst_file_path, "wb+");
if (nfsfh == NULL)
{
fprintf(stderr, "Failed to open nfs file for write : \"%s\"\n", dst_file_path.c_str());
fu::close(fd);
return 10;
}
if (stat(src_file_path.c_str(), &st) != 0)
{
fprintf(stderr, "Failed to stat source file \"%s\"\n", src_file_path.c_str());
fu::close(fd);
return 10;
}
char* buf;
buf = (char*)malloc(BUFSIZE);
off = 0;
while (off < st.st_size)
{
count = (size_t)(st.st_size - off);
if (count > BUFSIZE)
{
count = BUFSIZE;
}
count = fu::pread(fd, buf, count, off);
if (count < 0)
{
fprintf(stderr, "Failed to read from source file\n");
fu::close(fd);
nfsfh->free_context();
return 10;
}
count = nfsfh->pwrite(buf, count, off);
if (count < 0)
{
fprintf(stderr, "Failed to write to nfs target file\n");
fu::close(fd);
nfsfh->fclose();
return 10;
}
off += count;
}
if (buf != NULL)
{
free(buf);
}
printf("Copied %d bytes : %s\n", (int)off, dst_file_path.c_str());
fu::close(fd);
nfsfh->fclose();
return 0;
}
int NFS::getdir(std::string nfs_src, std::string dst, bool recursive=true, std::string pattern="*")
{
std::vector<std::string> src_pathes = listdir(nfs_src, recursive, true, true, pattern);
dst = pystring::os::path::normpath(dst);
for (auto src_path : src_pathes)
{
//std::cout << src_path << std::endl;
//continue;
std::string src_path_rel = pystring::slice(src_path, nfs_src.length());
if (!pystring::endswith(nfs_src, "/"))
{
std::string src_dirname = pystring::os::path::dirname(nfs_src);
std::cout << "getdir : src_dirname :" << src_dirname << std::endl;
src_path_rel = pystring::slice(src_path, src_dirname.length());
}
if (pystring::startswith(src_path_rel, "/"))
{
src_path_rel = pystring::slice(src_path_rel, 1);
}
/*std::cout << "getdir : dst :" << dst << std::endl;
std::cout << "getdir : src :" << src << std::endl;
std::cout << "getdir : src_path :" << src_path << std::endl;
std::cout << "getdir : src_path_rel : " << src_path_rel << std::endl;*/
std::string dst_path = pystring::os::path::normpath(pystring::os::path::join(dst, src_path_rel));
if (!exists(src_path))
{
fprintf(stderr, "Failed to stat nfs source file : %s", src_path.c_str());
continue;
}
if (isdir(src_path))
{
makedirs(dst_path);
}
else
{
getfile(src_path, dst_path);
}
//std::cout << "----" << std::endl;
}
return 0;
}
int NFS::getfile(std::string nfs_src, std::string dst)
{
/*std::cout << "getfile : src : " << nfs_src << std::endl;
std::cout << "getfile : dst : " << dst << std::endl;*/
//return 0;
off_t off;
ssize_t count;
std::string src_file_path = nfs_src;
std::string src_dir = pystring::os::path::dirname(src_file_path);
auto nfsfh = fopen(src_file_path, "rb");
if (nfsfh == NULL)
{
fprintf(stderr, "Failed to open nfs file for read : \"%s\"\n", src_file_path.c_str());
return 10;
}
dst = pystring::replace(dst, "\\", "/");
std::string dst_file_path = dst;
std::string dst_dir = pystring::os::path::dirname(dst_file_path);
if (!fu::exists(dst_dir))
{
fu::makedirs(dst_dir);
}
int fd = fu::open(dst_file_path, "wb+");
char* buf;
buf = (char*)malloc(BUFSIZE);
off = 0;
auto st = nfsfh->fstat();
while (off < st.nfs_size)
{
count = (size_t)(st.nfs_size - off);
if (count > BUFSIZE)
{
count = BUFSIZE;
}
count = nfsfh->pread(buf, count, off);
if (count < 0)
{
fprintf(stderr, "Failed to read from source nfs file\n");
fu::close(fd);
nfsfh->free_context();
return 10;
}
count = fu::pwrite(fd, buf, count, off);
if (count < 0)
{
fprintf(stderr, "Failed to write to target file\n");
fu::close(fd);
nfsfh->fclose();
return 10;
}
off += count;
}
if (buf != NULL)
{
free(buf);
}
printf("Copied %d bytes : %s\n", (int)off, dst_file_path.c_str());
fu::close(fd);
nfsfh->fclose();
return 0;
}
int NFS::get(std::string nfs_src, std::string dst, bool recursive=true, std::string pattern="*")
{
std::cout << "get() : " << nfs_src << std::endl;
std::string dst_path = dst;
if (!pystring::endswith(dst_path, "/"))
{
dst_path = dst_path + "/";
}
if (!fu::exists(dst_path))
{
fu::makedirs(dst_path);
}
if (!exists(nfs_src))
{
fprintf(stderr, "nfs src path \"%s\" not exists.\n", nfs_src.c_str());
return 1;
}
if (isdir(nfs_src))
{
getdir(nfs_src, dst, recursive, pattern);
}
else
{
std::string src_file_path = nfs_src;
std::string src_file = pystring::os::path::basename(src_file_path);
std::string dst_file_path = pystring::os::path::join_posix(dst_path, src_file);
getfile(src_file_path, dst_file_path);
}
return 0;
}
void NFS::test()
{
set_uid(0);
set_gid(0);
if (!exists("./a"))
mkdir("./a");
makedirs("./a/b/c");
auto fn = fopen("./a/b/c/test.txt", "w+");
for (int i = 0; i <= 1000; i++)
{
char buf[1024];
sprintf(buf, "This is a test %d\n", i);
fn->fwrite(buf);
}
fn->fclose();
for (auto p : listdir("./a", true, true, "*"))
{
std::cout << p << std::endl;
}
//put("./", "C:/Python27");
chmod("./a/b/c/test.txt", 0777);
chown("./a/b/c/test.txt", 1000, 1000);
get("./Python27/", "C:/test");
//putfile("./ttt/", "C:/Python27/NEWS.txt");
//putfile("./ttt/addColorSwitch.png", "C:/CGCG/projects/COOKIES/maya/2018/x64/icons/addColorSwitch.png");
}
}
+72
View File
@@ -0,0 +1,72 @@
#pragma once
#include "pynfs.h"
namespace pynfs
{
class NFSFH;
class NFS
{
public:
NFS();
NFS(std::string path);
~NFS();
int openurl(std::string path);
std::vector<std::string> listdir(std::string path, bool recursive, bool with_file, bool with_dir, std::string pattern);
int mkdir(std::string path);
void rmtree(std::string path);
int rmdir(std::string path);
int remove(std::string path);
int chdir(std::string path);
void makedirs(std::string path);
int chmod(std::string path, int mode);
int chown(std::string path, int uid, int gid);
int rename(std::string old_path, std::string new_path);
int symlink(std::string target, std::string linkname);
struct nfs_stat_64 fstat(std::string path);
bool exists(std::string path);
bool isfile(std::string path);
bool isdir(std::string path);
time_t getmtime(std::string path);
time_t getatime(std::string path);
time_t getctime(std::string path);
std::vector<std::string> glob(std::string path, bool recursive);
std::shared_ptr<NFSFH> fopen(std::string path, std::string mode);
int putdir(std::string dst, std::string src, bool recursive, std::string pattern);
int putfile(std::string dst, std::string src);
int put(std::string nfs_dst, std::string src, bool recursive, std::string pattern);
int getdir(std::string src, std::string dst, bool resursive, std::string pattern);
int getfile(std::string src, std::string dst);
int get(std::string nfs_src, std::string dst, bool recursive, std::string pattern);
void test();
// void syncdir(std::string src_path, std::string dst_path);
void set_uid(int uid);
void set_gid(int gid);
std::string server() { return _url->server; };
std::string path() { return _url->path; };
std::string file() { return _url->file; };
std::string getcwd();
nfs_context *nfs() { return _nfs; };
struct nfs_url *url() { return _url; };
void free_context();
private:
nfs_context *_nfs;
nfs_url *_url;
};
}
+255
View File
@@ -0,0 +1,255 @@
#include "NFS.h"
#include "NFSFH.h"
#include "pystring.h"
#include <nfsc/libnfs.h>
namespace pynfs
{
NFSFH::NFSFH(void* ctx, std::string path, std::string mode)
{
_nfs = NULL;
_nfsfh = NULL;
_url = NULL;
_ctx = static_cast<struct file_context*> (ctx);
if (_ctx == NULL) {
char error[1024];
sprintf(error, "Failed to init file_context\n");
throw PyNFSError(error);
}
else {
_nfs = _ctx->nfs;
_url = _ctx->url;
}
if (_ctx->nfs == NULL) {
if (!pystring::startswith(path, "nfs://")) {
char error[1024];
sprintf(error, "Failed to init context from path: %s\n", path.c_str());
throw PyNFSError(error);
}
auto nfs_ctx = NFS::NFS(path);
_nfs = nfs_ctx.nfs();
_url = nfs_ctx.url();
if (_nfs == NULL) {
char error[1024];
sprintf(error, "Failed to init context");
throw PyNFSError(error);
}
}
/*if (_url == NULL)
{
if (!pystring::startswith(path, "nfs://")) {
char error[1024];
sprintf(error, "Failed to init url from path: %s\n", path.c_str());
throw PyNFSError(error);
}
else {
_url = nfs_parse_url_full(_nfs, path.c_str());
if (_url == NULL) {
char error[1024];
sprintf(error, "%s\n", nfs_get_error(_nfs));
free_context();
throw PyNFSError(error);
}
}
}*/
_binary = pystring::count(mode, "b") ? true : false;
_plus = pystring::endswith(mode, "+");
_flag = 0;
if (pystring::startswith(mode, "r")) {
_flag = _plus ? O_RDWR : O_RDONLY;
if (pystring::startswith(mode, "rb")) {
_flag |= O_BINARY;
}
}
if (pystring::startswith(mode, "w")) {
_flag = _plus ? O_RDWR : O_WRONLY;
_flag |= O_CREAT | O_TRUNC;
if(pystring::startswith(mode, "wb")) {
_flag |= O_BINARY;
}
}
if (pystring::startswith(mode, "a")) {
_flag = _plus ? O_RDWR : O_WRONLY;
_flag |= O_CREAT | O_APPEND;
}
if (nfs_open(_nfs, path.c_str(), _flag, &_nfsfh) != 0) {
if (_flag & O_CREAT) {
if (nfs_create(_nfs, path.c_str(), _flag, 0664, &_nfsfh) != 0) {
char error[1024];
sprintf(error, "Failed to create file %s: %s\n",
_url->file,
nfs_get_error(_nfs));
throw PyNFSError(error);
free_context();
}
}
else {
char error[1024];
sprintf(error, "Failed to open file %s: %s\n",
_url->file,
nfs_get_error(_nfs));
free_context();
throw PyNFSError(error);
}
}
_closed = false;
_need_flush = false;
_writing = _flag & (O_RDWR | O_WRONLY) ? true : false;
}
NFSFH::NFSFH(std::string path, std::string mode)
{
if (!pystring::startswith(path, "nfs://")) {
char error[1024];
sprintf(error, "Failed to init context from path: %s\n", path.c_str());
throw PyNFSError(error);
}
}
void NFSFH::fclose()
{
if (_need_flush) {
flush();
}
nfs_close(_nfs, _nfsfh);
_closed = true;
}
std::string NFSFH::fread(int size = -1)
{
if (size < 0) {
uint64_t pos = tell();
struct nfs_stat_64 st;
nfs_fstat64(_nfs, _nfsfh, &st);
size = (int)(st.nfs_size - pos);
}
char buf[BUFSIZE];
int count;
count = nfs_read(_nfs, _nfsfh, sizeof(buf), buf);
if (count < 0) {
char error[1024];
sprintf(error, "Failed to read(): %s\n",
nfs_get_error(_nfs));
}
return std::string(buf).substr(0, count);
}
int NFSFH::fwrite(char* data)
{
int ret = 0;
int count = nfs_write(_nfs, _nfsfh, strlen(data), data);
if (count < 0) {
char error[1024];
sprintf(error, "Failed to write(): %s\n",
nfs_get_error(_nfs));
ret = 1;
}
_need_flush = true;
return ret;
}
void NFSFH::fseek(int64_t offset, int whence = SEEK_CUR)
{
uint64_t current_offset;
nfs_lseek(_nfs, _nfsfh, offset, whence, &current_offset);
}
uint64_t NFSFH::fileno()
{
struct nfs_stat_64 st;
nfs_fstat64(_nfs, _nfsfh, &st);
return st.nfs_ino;
}
nfs_stat_64 NFSFH::fstat()
{
struct nfs_stat_64 stat;
if (nfs_fstat64(_nfs, _nfsfh, &stat) != 0) {
char error[1024];
sprintf(error, "Failed to stat file: %s\n",
nfs_get_error(_nfs));
free_context();
throw PyNFSError(error);
}
return stat;
}
uint64_t NFSFH::tell()
{
uint64_t pos;
nfs_lseek(_nfs, _nfsfh, 0, SEEK_CUR, &pos);
return pos;
}
void NFSFH::truncate(uint64_t offset = -1)
{
if (offset < 0) {
offset = tell();
}
nfs_ftruncate(_nfs, _nfsfh, offset);
}
void NFSFH::flush()
{
if (_closed) {
throw PyNFSError("I/O operation on closed file");
return;
}
nfs_fsync(_nfs, _nfsfh);
_need_flush = false;
}
const size_t NFSFH::pread(char* buf, size_t count, off_t off)
{
return nfs_pread(_nfs, _nfsfh, off, count, buf);;
}
const size_t NFSFH::pwrite(char* buf, size_t count, off_t off)
{
return nfs_pwrite(_nfs, _nfsfh, off, count, buf);
}
std::string NFSFH::getcwd()
{
const char* cwd[1024];
nfs_getcwd(_nfs, cwd);
return std::string(*cwd);
}
void NFSFH::error()
{
}
void NFSFH::enter()
{
}
void NFSFH::exit()
{
}
const void NFSFH::free_context()
{
/*if (_fd != -1) {
close(_fd);
}*/
if (_nfsfh != NULL) {
nfs_close(_nfs, _nfsfh);
}
if (_nfs != NULL) {
nfs_destroy_context(_nfs);
}
nfs_destroy_url(_url);
}
}
+53
View File
@@ -0,0 +1,53 @@
#pragma once
#include "pynfs.h"
namespace pynfs
{
class NFS;
class NFSFH
{
public:
NFSFH(void* ctx, std::string path, std::string mode);
NFSFH(std::string path, std::string mode);
void fclose();
int fwrite(char* data);
std::string fread(int size);
//char* fread();
void fseek(int64_t offset, int whence);
uint64_t fileno();
struct nfs_stat_64 fstat();
uint64_t tell();
void truncate(uint64_t offset);
void flush();
const size_t pread(char* buf, size_t count, off_t off);
const size_t pwrite(char* buf, size_t count, off_t off);
nfs_context* nfs() { return _nfs; };
struct nfs_url* url() { return _url; };
struct nfsfh* nfsfh() { return _nfsfh; };
std::string getcwd();
void error();
void enter();
void exit();
const void free_context();
private:
struct file_context* _ctx;
nfs_context* _nfs;
struct nfsfh* _nfsfh;
struct nfs_url* _url;
int _flag;
bool _plus;
bool _binary;
bool _closed;
bool _need_flush;
bool _writing;
};
}
+200
View File
@@ -0,0 +1,200 @@
#define _FILE_OFFSET_BITS 64
#include <string>
#include <vector>
#include <iostream>
#include <Windows.h>
#include <direct.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include "pystring.h"
#undef open
#undef close
namespace fu
{
bool exists(std::string path)
{
struct stat st;
if (stat(path.c_str(), &st) != 0) {
return false;
}
return true;
}
void makedirs(std::string path)
{
std::vector<std::string> result;
pystring::split(pystring::replace(path, "\\", "/"), result, "/");
std::string npath = result[0];
for (auto p : result)
{
if (p == result[0])
continue;
npath = pystring::os::path::join_posix(npath, p);
if (exists(npath))
continue;
mkdir(npath.c_str());
}
}
bool isdir(std::string path)
{
struct stat st;
if (stat(path.c_str(), &st) != 0) {
return false;
}
if (st.st_mode & S_IFDIR)
return true;
return false;
}
bool isfile(std::string path)
{
struct stat st;
if (stat(path.c_str(), &st) != 0) {
return false;
}
if (st.st_mode & S_IFREG)
return true;
return false;
}
time_t getmtime(std::string path)
{
struct stat st;
if (stat(path.c_str(), &st) != 0) {
return 0;
}
return st.st_mtime;
}
time_t getatime(std::string path)
{
struct stat st;
if (stat(path.c_str(), &st) != 0) {
return 0;
}
return st.st_atime;
}
time_t getctime(std::string path)
{
struct stat st;
if (stat(path.c_str(), &st) != 0) {
return 0;
}
return st.st_ctime;
}
struct stat fstat(std::string path) {
struct stat st;
stat(path.c_str(), &st);
return st;
}
std::vector<std::string> listdir(std::string path, bool recursive=false, bool with_file=true, bool with_dir=true, std::string pattern="*")
{
std::vector<std::string> result;
if (!isdir(path)) {
fprintf(stderr, "Path is not directory : %s", path.c_str());
return result;
}
WIN32_FIND_DATA data;
std::string rpath = pystring::os::path::join(path, pattern);
HANDLE hFind = FindFirstFile(rpath.c_str(), &data);
if (hFind != INVALID_HANDLE_VALUE)
{
do {
if (pystring::startswith(data.cFileName, ".") || pystring::startswith(data.cFileName, ".."))
continue;
std::string fpath = pystring::os::path::join(path, data.cFileName);
if (recursive && isdir(fpath)) {
std::vector<std::string> fpaths = listdir(fpath, recursive, with_file, with_dir, pattern);
for (auto p : fpaths) {
result.push_back(p);
}
if (with_dir){
result.push_back(fpath);
}
}
else {
if (with_file) {
result.push_back(fpath);
}
}
} while (FindNextFile(hFind, &data));
FindClose(hFind);
}
return result;
}
int open(std::string path, int flags) {
int fd = _open(path.c_str(), flags, 0660);
if (fd == -1){
fprintf(stderr, "Fail to open %s\n", path.c_str());
return fd;
}
return fd;
}
int open(std::string path, std::string mode)
{
bool _binary = pystring::count(mode, "b") ? true : false;
bool _plus = pystring::endswith(mode, "+") ? true : false;
int _flags = 0;
if (pystring::startswith(mode, "r")) {
_flags = _plus ? O_RDWR : O_RDONLY;
if (pystring::startswith(mode, "rb")) {
_flags |= O_BINARY;
}
}
if (pystring::startswith(mode, "w")) {
_flags = _plus ? O_RDWR : O_WRONLY;
_flags |= O_CREAT | O_TRUNC;
if (pystring::startswith(mode, "wb")) {
_flags |= O_BINARY;
}
}
if (pystring::startswith(mode, "a")) {
_flags = _plus ? O_RDWR : O_WRONLY;
_flags |= O_CREAT | O_APPEND;
}
int fd = _open(path.c_str(), _flags, 0660);
if (fd == -1) {
fprintf(stderr, "Fail to open %s\n", path.c_str());
return fd;
}
return fd;
}
int close(int fd)
{
if (fd != -1){
return _close(fd);
}
return 0;
}
static ssize_t pread(int fd, char* buf, size_t count, off_t off)
{
lseek(fd, off, SEEK_SET);
return read(fd, buf, count);
}
static ssize_t pwrite(int fd, char* buf, size_t count, off_t off)
{
lseek(fd, off, SEEK_SET);
return write(fd, buf, count);
}
}
+73
View File
@@ -0,0 +1,73 @@
#include "NFS.h"
#include "NFSFH.h"
PYBIND11_MODULE(_pynfs, m)
{
m.doc() = "libnfs python binding";
using namespace pybind11::literals;
py::class_<pynfs::NFS>(m, "NFS")
.def(py::init<>())
.def(py::init<std::string>(), py::arg("path"))
.def("openurl", &pynfs::NFS::openurl, "Open a NFS url (nfs://server/path)")
.def("listdir", &pynfs::NFS::listdir, "List directory contents.",
py::arg("path") = ".",
py::arg("recursive") = false,
py::arg("with_file") = true,
py::arg("with_dir") = true,
py::arg("pattern") = "*")
.def("mkdir", &pynfs::NFS::mkdir, "Make new directory.")
.def("makedirs", &pynfs::NFS::makedirs, "Make new directories recursively.")
.def("remove", &pynfs::NFS::remove, "Remove a file or directory.")
.def("rmtree", &pynfs::NFS::rmtree, "Remove a directory tree.")
.def("rmdir", &pynfs::NFS::rmdir, "Remove a directory.")
.def("chmod", &pynfs::NFS::chmod, "Change permission")
.def("chown", &pynfs::NFS::chown, "Change owner")
.def("exists", &pynfs::NFS::exists, "Determine file or directory exists.")
.def("isdir", &pynfs::NFS::isdir, "Determine path is directory")
.def("isfile", &pynfs::NFS::isfile, "Determine path is file")
.def("chdir", &pynfs::NFS::chdir, "Change current working directory (cwd)")
.def("getcwd", &pynfs::NFS::getcwd, "Get current working directory")
.def("open", &pynfs::NFS::fopen, "Open a nfs file handle")
.def("getatime", &pynfs::NFS::getatime, "Get access time")
.def("getmtime", &pynfs::NFS::getmtime, "Get modify time")
.def("getctime", &pynfs::NFS::getctime, "Get create time")
.def("set_uid", &pynfs::NFS::set_uid, "Set uid")
.def("set_gid", &pynfs::NFS::set_gid, "Set gid")
.def("put", &pynfs::NFS::put, "Put file or directory to nfs path",
py::arg("nfs_dst"), py::arg("src"),
py::arg("recursive") = false,
py::arg("pattern") = "*")
.def("get", &pynfs::NFS::get, "Get file or directory from nfs path",
py::arg("nfs_src"), py::arg("dst"),
py::arg("recursive") = false, py::arg("pattern") = "*")
.def("test", &pynfs::NFS::test);
py::class_<pynfs::NFSFH>(m, "NFSFH")
.def(py::init<void *, std::string, std::string>())
.def(py::init<std::string, std::string>())
.def("read", &pynfs::NFSFH::fread,
py::arg("size") = -1)
.def("write", &pynfs::NFSFH::fwrite)
.def("seek", &pynfs::NFSFH::fseek,
py::arg("offset"), py::arg("whence") = SEEK_CUR)
.def("turncate", &pynfs::NFSFH::truncate,
py::arg("offset") = -1)
.def("tell", &pynfs::NFSFH::tell)
.def("fileno", &pynfs::NFSFH::fileno)
.def("flush", &pynfs::NFSFH::flush)
.def("stat", &pynfs::NFSFH::fstat)
.def("close", &pynfs::NFSFH::fclose)
.def("__enter__", &pynfs::NFSFH::enter)
.def("__exit__", &pynfs::NFSFH::exit);
static py::exception<pynfs::PyNFSError> ex(m, "PyNFSError");
py::register_exception_translator([](std::exception_ptr p)
{
try {
if (p) std::rethrow_exception(p);
}
catch (const pynfs::PyNFSError&e) {
// Set MyException as the active python error
ex(e.what());
} });
}
+40
View File
@@ -0,0 +1,40 @@
#pragma once
#include <pybind11/stl.h>
#include <pybind11/functional.h>
#include <pybind11/complex.h>
#include <pybind11/pybind11.h>
#ifdef WIN32
#include <win32/win32_compat.h>
#pragma comment(lib, "ws2_32.lib")
#endif
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <fcntl.h>
#include <stdio.h>
#include <nfsc/libnfs.h>
#define BUFSIZE 1024*1024
namespace py = pybind11;
namespace pynfs
{
struct file_context {
nfs_context* nfs;
nfs_url* url;
};
class PyNFSError : public std::exception
{
public:
explicit PyNFSError(const char* m) : message{ m } {}
const char* what() const noexcept override { return message.c_str(); }
private:
std::string message = "";
};
}
+28
View File
@@ -0,0 +1,28 @@
#include <string.h>
#include <iostream>
bool match(char const* needle, char const* haystack) {
for (; *needle != '\0'; ++needle) {
switch (*needle) {
case '?':
if (*haystack == '\0')
return false;
++haystack;
break;
case '*': {
if (needle[1] == '\0')
return true;
size_t max = strlen(haystack);
for (size_t i = 0; i < max; i++)
if (match(needle + 1, haystack + i))
return true;
return false;
}
default:
if (*haystack != *needle)
return false;
++haystack;
}
}
return *haystack == '\0';
}