fuse parsing custom arguments in C - c

Using libfuse in my c-project, I 'm trying to add custom command-line arguments and handle them.
Here is an example on which I rely
https://github.com/libfuse/libfuse/wiki/Option-Parsing
First, I tried to do the argument for the mount point configuration -с <pathtoconfig>
I tried many ways to describe an option like -c --config conf= -o conf=, but ineffectually
Please, help me find the right path to solve the problem :(
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fuse.h>
#include "fuu_walk.h"
#include "jsmnload.h"
#define _JSMN_TOKEN_SIZE_ 256
#define _JSMN_BUFFER_SIZE_ 4096
#define MYFS_OPT(t, p, v) { t, offsetof(struct myfs_config, p), v }
struct myfs_config {
char *mystring;
} conf;
static struct fuse_opt myfs_opts[] = {
MYFS_OPT("-c %s", mystring, 1),
FUSE_OPT_END
};
jsmntok_t t[_JSMN_TOKEN_SIZE_];
char buf[_JSMN_BUFFER_SIZE_];
#if 0
= ""
"{\"root\": ["
"{\"path\":\"/\", \"mode\":\"drw-------\"},"
"{\"path\":\"/12ABC345DE67\", \"mode\":\"drw-------\"},"
"{\"path\":\"/12ABC345DE67/_XQ01\", \"mode\":\"-rw-------\"},"
"{\"path\":\"/12ABC345DE67/_XQ02\", \"mode\":\"-rw-------\"},"
"{\"path\":\"/12ABC345DE78\", \"mode\":\"drw-------\"},"
"{\"path\":\"/12ABC345DE89\", \"mode\":\"drw-------\"}"
"]}";
#endif
static int myfs_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs)
{
struct myfs_config *ptr = (struct myfs_config *)data;
FILE *conf;
int rc = 0;
//I wanna check the argument on the each iteration of fuse_opt_parse. It's just the debug printf
printf("arg = %s\t string %s\t key = %i\n", arg, ptr->mystring, key);
switch (key) {
case 1:
conf = fopen(ptr->mystring, "r");
rc = read(fileno(conf), buf, _JSMN_BUFFER_SIZE_);
if ( jsmnload(buf, t, _JSMN_TOKEN_SIZE_, fuu_mkfstree) < 0 ) {
printf("Error load configuration\n");
exit(-1);
}
}
return 1;
}
int main(int argc, char *argv[])
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
memset(&conf, 0, sizeof(conf));
fuse_opt_parse(&args, &conf, myfs_opts, myfs_opt_proc);
return fuu_main(args.argc, args.argv);
}
Launch example
./appendix/fuu /mnt/cdrom/ -c /mnt/fs.json
As a result, printf in myfs_opt_proc function works only once and outputs
arg = /mnt/cdrom/ string (null) key = -2
Why myfs_opt_proc does not work for option -c?

I cannot comment so as an answer... looking at the reference you provided it seems to me that there is no option starting with -c. So result seems correct because fuse cannot parse this. Look at this snippet from your link:
fuse_opt_add_arg(&args, "-omodules=subdir,subdir=/foo");
You may try to announce options to fuse using -o.
Edit: Youre example differs from the linked one, try to add to following line to the defined struct:
FUSE_OPT_KEY("-c", "KEY_CONFIG");
and some line before
emum {
KEY_CONFIG
};
and parse it like this in youre myfs_opt_proc function
switch (key) {
case KEY_CONFIG:
/* ... */
. Summed up you missed declaring the -c key.

Related

Hello world in C using SGX

I noticed some people able to write an SGX code in C code. I tried to do that, Assume I have the following code. Still I don't know how to write a Makefile that can compile these file As I didn't find much information online on how to compile it.
main.c
#define ENCLAVE_FILE "enclave.signed.dll"
#define MAX_BUF_LEN 100
#include "sgx_urts.h"
#include "enclave_u.h"
#include "stdio.h"
#include <string>
int main()
{
//Encalve starts
sgx_enclave_id_t eid;
sgx_status_t ret = SGX_SUCCESS;
sgx_launch_token_t token = { 0 };
int updated = 0;
char buffer[MAX_BUF_LEN] = "Hello world!";
ret = sgx_create_enclave(ENCLAVE_FILE, SGX_DEBUG_FLAG, &token, &updated, &eid, NULL);
if (ret != SGX_SUCCESS) {
printf("\nApp: error %#x, failed to create enclave. \n", ret);
}
//Encalve starts
// (ECALL will happen here).
printf("\nApp: Buffertesrs:\n");
printf("App: Buffer before ECALL: %s\n", buffer);
encalveChangebuffer(eid, buffer, MAX_BUF_LEN);
printf("App: Buffer before ECALL: %s\n", buffer);
}
encalve.c
#include "enclave_t.h"
#include "sgx_trts.h"
#include <stdio.h>
#include <string.h>
void encalveChangebuffer(char * buf, size_t len) {
const char * secret = "Hello from Enclave 2";
if (len > strlen(secret))
memcpy(buf, secret, strlen(secret) + 1);
else
memcpy(buf, "false", strlen("false") + 1);
}
encalve.edl
enclave {
trusted {
/* define ECALLs here. */
public void encalveChangebuffer([in,out,size=len] char * buf, size_t len);
};
untrusted {
/* define OCALLs here. */
};
};
I am looking for a Makefile that can compile sgx c code.
Check out this reference:
SGX Developer Reference.
It has a section about Edger8r Tool that explains how to run that tool to compile enclave.edl to a bunch of C files.
It also has a section about sgx_sign.exe that is needed to produce a signed DLL.
There's a section "Enclave Project Files" that lists all required files and build tool settings.
I don't have all the answers, but that should be a good starting point for building your make file.

creating multiple recursive directories in c

I am completing cs50x (the edX (free) version of the Harvard cs50) course and am trying to be a bit tricky/lazy/test myself.
I am trying to use a C program to create all the directories I will need for my psets.
I have looked online and found that <sys/stat.h> includes the mkdir() function and therefore tried creating some nested loops to create all the necessary folders by doing something similar to mkdir {pset1,pset1/{standard,hacker},pset2,pset2{standard... to give me a directory structure like this:
pset1/Standard
pset1/Hacker
pset2/Standard
etc...
I came up with this:
#include <cs50.h>
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, string argv[])
{
for(int i = 1; i <=8; i++)
{
string dir = argv[1];
sprintf(dir,"%s%i", argv[1], i);
mkdir(dir, 0777);
for(int j = 0; j<2; j++)
{
string subDir[] = {"Standard","Hacker"};
sprintf(dir,"%s%i/%s", argv[1], i, subDir[j]);
mkdir(dir, 0777);
}
}
}
However, the program only creates pset1 and completes, there are no subfolders, no pset2 etc.
Yes, you're being lazy since you seem to have very little knowledge of C, yet try to program in it. :)
C is not Python, there is no string interpolation/formatting operator. You have to call a function, specificially snprintf(). Read that manual page.
Also, you can't create a bunch of nested directories with a single call to mkdir(). Read the manual page.
To create nested directories, you're either going to have to build each's absolute path (i.e. each successive time you call mkdir() the path will be longer than the previous time), or actually enter each directory as you create it, and go from there.
To create a full path you can call mkdir() recursivly like this:
#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
int mkdirr(const char * path, const mode_t mode, const int fail_on_exist)
{
int result = 0;
char * dir = NULL;
do
{
if (NULL == path)
{
errno = EINVAL;
result = -1;
break;
}
if ((dir = strrchr(path, '/')))
{
*dir = '\0';
result = mkdirr(path, mode, fail_on_exist);
*dir = '/';
if (result)
{
break;
}
}
if (strlen(path))
{
if ((result = mkdir(path, mode)))
{
char s[PATH_MAX];
sprintf(s, "mkdir() failed for '%s'", path);
perror(s);
if ((EEXIST == result) && (0 == fail_on_exist))
{
result = 0;
}
else
{
break;
}
}
}
} while (0);
return result;
}
And then call mkdirr() like this;
int main(void)
{
char p[] = "test/1/2/3";
if (-1 == mkdirr(p, 0777, 0))
{
perror("mkdirr() failed()");
}
return 0;
}

The following code doesn't work .. why?

The following code isn't working as expected ..
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
struct dest
{
char filename[20], keyword[20];
bool opened;
FILE * stream;
};
void display_data(const struct dest p) {
printf("Keyword: %s, Filename: %s, Used: %s\n", p.keyword, p.filename, p.opened ? "Yes" : "No");
}
int main(int argc, char const *argv[])
{
// float lon, lat;
// char info[80];
if ((argc+1) % 2) {
fprintf(stderr, "Usage: %s file_to_read file_for_unknown type file type file ...\n", argv[0]);
return 2;
}
if (access(argv[1], F_OK) == -1) {
fprintf(stderr, "File can't be accessed: %s\n", argv[1]);
return 2;
}
const short pairs = (argc-3)/2;
struct dest data[pairs];
short times = 4;
for(short i = 4; i < argc; i += 2) {
struct dest data[i-times];
data[i-times].opened = false;
strcpy(data[i-times].keyword, argv[i-1]);
strcpy(data[i-times].filename, argv[i]);
// display_data(data[i-times]);
times += 1;
}
display_data(data[0]);
return 0;
}
That's what happens when I try to run it ..
./categorize spooky.csv other.csv UFO UFOS.csv
Keyword: ?, Filename: �#, Used: No
Which isn't that meaningful ..
I have been trying to work out the solution .. in vein ..
I don't understand where the problem is ..
Arguments are parsed as follows:
The first argument: the file the program is supposed to read from (ignored for now)
The second argument: the file the program is supposed to store at any unknown info found in the spooky.csv file (also, ignored in this implementation)
The other arguments: they are parsed as pairs, the first is the keyword, the second is the file ..
My Solution for this filtering problem was to create an array of structs, and within each struct I store the keyword, the filename and the file io stream (which i am ignoring, for now) ..
Any help would be highly appreciated ..
You have 2 struct dest data[] arrays. The inner one is masking the outer - get rid of it.
Your compiler is probably warning about this, if you have warnings turned on.

How to check if soft link exists or not

user: ls -lt
lrwxrwxrwx 1 user sw-team 9 Jun 18 19:01 new_link -> test/file
I have a soft link like mentioned above. I want to check whether new_link(not the linked file) exists or not. I tried all the below but all are checking only if the final destination file (test/file) exists or not.
access(filename,F_OK)
stat()
open()
fopen()
I want to find it in C language not in shell script.Please tell me how to find if new_link exists before checking the linked file?
Use lstat - get symbolic link status:
The lstat() function shall be equivalent to stat(), except when path refers to a symbolic link. In that case lstat() shall return information about the link, while stat() shall return information about the file the link references.
(Emphasis mine.)
lstat will return non-zero, and errno will be set to ENOENT if the link (or any other part of the path) does not exist.
Example:
#include <stdio.h>
#include <stdbool.h>
#include <sys/stat.h>
bool symlink_exists(const char* path)
{
struct stat buf;
int result;
result = lstat(path, &buf);
return (result == 0);
}
void test(const char* path)
{
bool exists = symlink_exists(path);
printf("%s does%s exist.\n", path, exists ? "" : " not");
}
int main(int argc, char** argv)
{
test("/bin/sh");
test("/etc/no_such_thing");
return 0;
}
Output:
/bin/sh does exist.
/etc/no_such_thing does not exist.
You need lstat to get link status and readlink to read the value of symlink.
I have modified Jonthon's code. Check this:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/stat.h>
bool symlink_exists(const char* path)
{
struct stat buf;
int ret = 0;
char *linkname;
if (lstat(path, &buf) == 0) {
// TODO: Add error handling
linkname = malloc(buf.st_size + 1);
readlink(path, linkname, buf.st_size + 1);
linkname[buf.st_size] = '\0';
printf("---> '%s' points to '%s'\n", path, linkname);
if (stat(linkname, &buf) == 0)
ret = 1;
}
return ret;
}
void test(const char* path)
{
bool exists = symlink_exists(path);
printf("%s does%s exist.\n", path, exists ? "" : " *not*");
}
int main(int argc, char** argv)
{
test("/bin/sh"); //Normal link using relative path - NOT WORKING
test("/etc/no_such_thing"); //Broken file
test("tmpp"); //Normal link using absolute path - WORKING
test("tmppp"); //Broken link
return 0;
}
Use absolute path to create your links. Otherwise you have to convert it to relative paths.
Short answer:
#include <sys/stat.h>
#include <string>
bool symlinkExists(const string &path)
{
struct stat info;
return lstat(path.c_str(), &info) == 0;
}

Unix c program to list directories recursively

I am working on a POSIX C learning exercise that involves recursively listing files/folders in a specified directory. The program takes in as arguments of one or more directories. I can list the contents of the initial directory fine but having a problem with the recursion. Is something wrong with the way I am passing in the argument for the recursive function call?
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <string.h>
void listdir(char *argv[])
{
DIR *mydirhandle;
struct dirent *mydirent;
struct stat statinfo;
int n = 1;
while(argv[n] != NULL)
{
if((mydirhandle = opendir(argv[n])) == NULL)
{
perror("opendir");
exit(1);
}
printf("%s/\n", argv[n]);
while((mydirent = readdir(mydirhandle)) != NULL)
{
if((strcmp(mydirent->d_name, ".") == 0) || (strcmp(mydirent->d_name, "..") == 0))
{
continue;
}
else
{
printf("\t%s\n", mydirent->d_name);
//check if next entry is a directory
if(mydirent->d_type == DT_DIR)
{
//is current directory being passed correctly here?
listdir(mydirent->d_name);
}
}
}
n++;
closedir(mydirhandle);
}
}
int main(int argc, char *argv[])
{
if(argc < 2)
{
printf("usage: %s <directory>\n", argv[0]);
return 0;
}
listdir(argv);
return 0;
}
The d_name member of struct dirent is the basename of the item in question. So, if you're going through a directory like this:
.
..
where-is/
pancakes/
.
..
house
Once you're in where-is, you'll try to listdir("pancakes") but that won't work because you need to listdir("where-is/pancakes").
You need to combine that with the name of the directory that you're looking before you have something that you can pass to the next listdir call.
You'll want to replace things like this:
listdir(mydirent->d_name);
with things like this:
char *next_dir = malloc(strlen(argv[n]) + strlen(mydirent->d_name) + 1 + 1);
sprintf(next_dir, "%s/%s", argv[n], mydirent->d_name);
listdir(next_dir);
free(next_dir);
Alternatively, you could chdir into the directories as you enter them and then chdir back up when you're done.
Turning on warnings will show that you're passing the wrong type when making the recursive function call. I would simply make listdir take a char * argument rather than char **, and then use a for loop in main to loop over multiple arguments if you need to.
You should use ftw for this, it calls a given callback on every item of the subtree. This way, you avoid using explicit recursion yourself, and your code will get much shorter.

Resources