Skip to content

Commit

Permalink
Merge pull request #45 from yhoogstrate/new_args_and_mount_with_fstab
Browse files Browse the repository at this point in the history
New args and mount with fstab
  • Loading branch information
yhoogstrate authored Sep 6, 2019
2 parents e80c1df + 6e94593 commit 04eaa80
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 52 deletions.
19 changes: 17 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ project(fastafs)
# Do this once in a while - find different bugs
#set(CMAKE_CXX_COMPILER "clang++")

set(PROJECT_VERSION "1.6.1")
set(PROJECT_VERSION "1.6.2")
set(PACKAGE_URL "https://github.com/yhoogstrate/fastafs")
set(PACKAGE_BUGREPORT "${PACKAGE_URL}/issues")

Expand Down Expand Up @@ -110,9 +110,23 @@ add_executable(fastafs
src/fuse.cpp
src/lsfastafs.cpp
)

set_target_properties(fastafs PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BUILD_DIR}")

# mount-only binary, without all the other stuff 'mount.fastafs' [for fstab]
add_executable(mount.fastafs
src/main_mount.cpp
src/fasta_to_fastafs.cpp
src/ucsc2bit_to_fastafs.cpp
src/fastafs.cpp
src/ucsc2bit.cpp
src/twobit_byte.cpp
src/database.cpp
src/utils.cpp
src/fuse.cpp
src/lsfastafs.cpp
)
set_target_properties(mount.fastafs PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${BUILD_DIR}")

add_library(libfastafs SHARED
src/fasta_to_fastafs.cpp
src/ucsc2bit_to_fastafs.cpp
Expand Down Expand Up @@ -166,6 +180,7 @@ add_test(test_utils "${BUILD_TEST_DIR}/test_utils")

# The compiled binary, usually to: /usr/local/bin/fastafs
install(TARGETS fastafs DESTINATION "bin")
install(TARGETS mount.fastafs DESTINATION "bin")
install(TARGETS libfastafs LIBRARY DESTINATION "lib" PUBLIC_HEADER DESTINATION "include/libfastafs")

# ----------------------------------------------------------------------
7 changes: 7 additions & 0 deletions Changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
2019-09-06 Youri Hoogstrate

* v1.6.2
* Rewritten argument parsing of fuse/mounting
* Added binary `mount.fastafs` only for mounting, wihtout the toolkit
* `fastafs --version` will now also output whether the binary was compiled as debug or release.

2019-08-21 Youri Hoogstrate

* v1.6.1
Expand Down
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Here we propose a solution; a mixture of 2bit compression and random on FASTA ve
FASTAFS is compatible with 2bit files but 2bit has some limitations and does for instance not allow mounting DICT files needed for CRAM and Picard tools. The 2bit files can be convert to FASTAFS and, more importantly, a mounted FASTAFS mountpoint will not only virtualize the FASTA but also the 2bit file. Is FASTAFS this famous 15th standard (<https://xkcd.com/927/>)?
Partially, but it is not designed to replace FASTA nor 2bit as those mountpoints should be used as flat files did before and the virtualization of dict files is not possible when we mount 2bit files.

## installation and compilation
## Installation and compilation

Currently the package uses cmake for compilation
Required dependencies are:
Expand Down Expand Up @@ -165,6 +165,30 @@ aaaa
c
```

### Find all running `fastafs mount` / `mount.fastafs` instances

The output format of `fastafs ps` is: `<pid>\t<source>\t<destination>\n`

```
$ fastafs ps
16383 /home/youri/.local/share/fastafs/test.fastafs /mnt/tmp
```

### Mounting via fstab (for instance on linux boot)

You can add the following line(s) to /etc/fstab to make fastafs mount during boot:

```
mount.fastafs#/home/youri/.local/share/fastafs/hg19.fastafs /mnt/fastafs/hg19 fuse auto,allow_other 0 0
```

Here `mount.fastafs` refers to the binary that only does mounting, without the rest of the toolkit.
This is followed by a hash-tag and the path of the desired fastafs file. The next value is the mount point followed by the argument indicating it runs fuse.
The `auto,allow_other` refers to the `-o` argument.
Here `auto` ensures it is mounted automatically after boot.
Given that a system mounts as root user, the default permission of the mount point will be only for root.
By setting `allow_other`, file system users get permissions to the mountpoint.

## Contributing
Feel free to start a discussion or to contribute to the GPL licensed code.

Expand Down
133 changes: 85 additions & 48 deletions src/fuse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,9 @@ static int do_getxattr(const char* path, const char* name, char* value, size_t s
sprintf(mypid, "%d", getpid());
size_t pid_size = (size_t) strlen(mypid);


if(size > pid_size) {
strncpy(value, mypid, pid_size);
strcpy(value, mypid);// if statement makes strncpy unneeded
value[pid_size] = '\0';

return (int) pid_size + 1;
Expand Down Expand Up @@ -328,9 +329,11 @@ fuse_operations operations = {




void print_fuse_help()
{
std::cout << "usage: fasfafs <mount: fastafs UID> <mountpoint> [options]\n";
std::cout << "usage: fasfafs mount <mount: fastafs UID> <mountpoint> [options]\n";
std::cout << "usage: mount.fastafs <mount: fastafs UID> <mountpoint> [options]\n";
std::cout << "\n";
std::cout << "general options:\n";
std::cout << " -2 --2bit virtualise a 2bit file rather than FASTAFS UID\n";
Expand Down Expand Up @@ -410,59 +413,96 @@ fuse_instance *parse_args(int argc, char **argv, char **argv_fuse)

fuse_instance *fi = new fuse_instance({nullptr, nullptr, true, nullptr, 60, 0});

//printf("argc=%i",argc);
//fuse option variable to send to fuse
argv_fuse[fi->argc_fuse++] = (char *) "fastafs"; // becomes fuse.fastafs

//fi->argv_fuse[0] = argv[0];
//fi->argv_fuse[1] = argv[1];
int i = 2;
while(i < argc) {
printf("processing argv[%i] = '%s';\n", i, argv[i]);
if(i < argc - 3) { // all arguments that take 2 arguments "--p", "50"
if(strcmp(argv[i], "-p") == 0 or strcmp(argv[i], "--padding") == 0) {
try {
sscanf(argv[++i], "%u", &fi->padding);
} catch(std::exception const & e) {
std::cerr << "ERROR: invalid padding value, must be integer value ranging from 0 to max-int size\n";
exit(1);
std::vector<char*> fuse_options = {}; // those that need to be appended later

char current_argument = '\0';// could be o for '-o', etc.

std::vector<int> full_args = {};
for(unsigned int i = 0; i < argc; ++i) {
printf("processing argv[%i] = '%s' [current argument=%i]\n", i, argv[i], (int) current_argument);

if(current_argument != '\0') { // parse the arguments' value
switch(current_argument) {
case 'p': // scanning padding value
if(!sscanf(argv[i], "%u", &fi->padding)) {
throw std::invalid_argument("Invalid argument (padding value): " + std::string(argv[i]));
}
} else { // arguments that need to be send to fuse
//argv_test[fi->argc_fuse] = argv[i];
argv_fuse[fi->argc_fuse++] = argv[i];
break;
default:
//throw std::invalid_argument("Invalid argument: " + std::string(argv[i]));
fuse_options.push_back(argv[i]); // could be values that correspond to fuse arguments, such as: -o, -f, etc.
break;
}

current_argument = '\0';// reset
} else if(argv[i][0] == '-') {
if(strlen(argv[i]) == 1) {
throw std::invalid_argument("Invalid argument: " + std::string(argv[i]));
}
} else if(i < argc - 2) { // all arguments that one argument "--lowercase" switches etc
if(strcmp(argv[i], "-2") == 0 or strcmp(argv[i], "--2bit") == 0) {

switch(argv[i][1]) {
case '2': // a fastafs specific flag
fi->from_fastafs = false;
} else { // arguments that need to be send to fuse
//argv_test[fi->argc_fuse] = argv[i];
argv_fuse[fi->argc_fuse++] = argv[i];
break;

case 'f': // fuse specific flags
case 's':
case 'd':
fuse_options.push_back(argv[i]);
break;

case 'o': // argument, fuse specific
current_argument = argv[i][1];
fuse_options.push_back(argv[i]); // fuse specific
break;

default: // argument, fastafs spcific (such as '-p' followed by '50')
current_argument = argv[i][1];
break;
}
} else if(i == argc - 2) { // this refers to the fastafs object
if(fi->from_fastafs) {
database d = database();
std::string fname = d.get(argv[i]);

if(fname.size() == 0) { // invalid mount argument, don't bind fastafs object
print_fuse_help();
exit(1);
} else { // valid fastafs and bind fastafs object
fi->f = new fastafs(std::string(argv[i]));
fi->f->load(fname);

fi->cache = fi->f->init_ffs2f(fi->padding, true);// allow mixed case
}
} else {
std::string basename = std::filesystem::path(std::string(argv[i])).filename();
} else {
full_args.push_back(i); // args such as 'sudo', 'fastafs' 'fastafs-uid' and '/mount/point' of which only the last 2 are needed
}
}

fi->u2b = new ucsc2bit(basename);// useses basename as prefix for filenames to mount: hg19.2bit -> hg19.2bit.fa
fi->u2b->load(std::string(argv[i]));
if(full_args.size() >= 2) {
int mount_target_arg = full_args[full_args.size() - 2 ]; // last two arguments are <fastafs file> and <mount point>, location to last 2 args not starting with --/- are in this vector

if(fi->from_fastafs) {
database d = database();
std::string fname = d.get(argv[mount_target_arg]);

std::string name; // prefix name of mounted fasta dict 2bit and fai files
if(fname.size() == 0) { // invalid mount argument, don't bind fastafs object
fname = std::string(argv[mount_target_arg]);
name = std::filesystem::path(fname).filename();

// remove .fastafs suffix
size_t lastindex = name.find_last_of(".");
name = name.substr(0, lastindex);

} else {
name = std::string(argv[mount_target_arg]);
}
} else { // mountpoint
//argv_test[fi->argc_fuse] = argv[i];
argv_fuse[fi->argc_fuse++] = argv[i];

fi->f = new fastafs(name);
fi->f->load(fname);
fi->cache = fi->f->init_ffs2f(fi->padding, true);// allow mixed case
} else {
std::string basename = std::filesystem::path(std::string(argv[mount_target_arg])).filename();

fi->u2b = new ucsc2bit(basename);// useses basename as prefix for filenames to mount: hg19.2bit -> hg19.2bit.fa
fi->u2b->load(std::string(argv[mount_target_arg]));
}

i++;
//argv_fuse[fi->argc_fuse++] = argv[mount_target_arg];
argv_fuse[fi->argc_fuse++] = argv[mount_target_arg + 1];
for(size_t j = 0; j < fuse_options.size(); j++) {
argv_fuse[fi->argc_fuse++] = fuse_options[j];
}
}

return fi;
Expand Down Expand Up @@ -504,6 +544,3 @@ void fuse(int argc, char *argv[])
//http://www.maastaar.net/fuse/linux/filesystem/c/2016/05/21/writing-a-simple-filesystem-using-fuse/
}




7 changes: 6 additions & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,12 @@ int main(int argc, char *argv[])
if(strcmp(argv[1], "--help") == 0 or strcmp(argv[1], "-h") == 0) {
usage();
} else if(strcmp(argv[1], "--version") == 0) {
std::cout << PACKAGE << " v" << PACKAGE_VERSION << GIT_SHA1_STRING << "\n\n";
#if DEBUG
std::cout << PACKAGE << " v" << PACKAGE_VERSION << GIT_SHA1_STRING << "-debug\n\n";
#else
std::cout << PACKAGE << " v" << PACKAGE_VERSION << GIT_SHA1_STRING << "-release\n\n";
#endif //DEBUG

std::cout << "Copyright (C) 2017 Youri Hoogstrate." << "\n";
std::cout << "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n";
std::cout << "This is free software: you are free to change and redistribute it.\n";
Expand Down
13 changes: 13 additions & 0 deletions src/main_mount.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

#include <iostream>

#include "config.hpp"
#include "fuse.hpp"

int main(int argc, char *argv[])
{
fuse(argc, argv);

return 0;
}

0 comments on commit 04eaa80

Please sign in to comment.