Domanda

I'm developing a custom file system with fuse. What I want to do is to read contents of a directory from remote server and list them in mount point. My rpc program run solely well. but when I try to combine it with rpc it got some build error. I'm using rpcgen to create my rpc program but I don't know how exactly I should build them together.

this is my cfs_client.c :

/*
  FUSE: Filesystem in Userspace
  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>

  This program can be distributed under the terms of the GNU GPL.
  See the file COPYING.

  gcc -Wall cfs.c `pkg-config fuse --cflags --libs` -o cfs
 */

#define FUSE_USE_VERSION 26

#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "cfs.h"

static const char *cfs_str = "Hello World!\n";
static const char *cfs_path = "/cfs";

static int cfs_getattr(const char *path, struct stat *stbuf) {
    int res = 0;

    memset(stbuf, 0, sizeof (struct stat));
    if (strcmp(path, "/") == 0) {
        stbuf->st_mode = S_IFDIR | 0755;
        stbuf->st_nlink = 2;
    } else if (strcmp(path, cfs_path) == 0) {
        stbuf->st_mode = S_IFREG | 0444;
        stbuf->st_nlink = 1;
        stbuf->st_size = strlen(cfs_str);
    } else
        res = -ENOENT;

    return res;
}

static int cfs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
        off_t offset, struct fuse_file_info *fi) {
    (void) offset;
    (void) fi;
    char *host = "localhost";
    char *dirname = "/home/hamed/test";
    CLIENT *clnt;
    readdir_res *result_1;

    if (strcmp(path, "/") != 0)
        return -ENOENT;

#ifndef DEBUG
    clnt = clnt_create(host, CFSPROG, CFSVERS, "udp");
    if (clnt == NULL) {
        clnt_pcreateerror(host);
        exit(1);
    }
#endif  /* DEBUG */
    result_1 = readdir_1(&dirname, clnt);
    if (result_1 == (readdir_res *) NULL) {
        clnt_perror(clnt, "call failed");
    }
    namelist nl;
    nl = result_1->readdir_res_u.list;
    while (nl) {
        printf("dirname = %s\n", nl->name);
        filler(buf, nl->name, NULL, 0);
        nl = nl->next;
    }

#ifndef DEBUG
    clnt_destroy(clnt);
#endif   /* DEBUG */

    return 0;
}

static int cfs_open(const char *path, struct fuse_file_info *fi) {
    if (strcmp(path, cfs_path) != 0)
        return -ENOENT;

    if ((fi->flags & 3) != O_RDONLY)
        return -EACCES;

    return 0;
}

static int cfs_read(const char *path, char *buf, size_t size, off_t offset,
        struct fuse_file_info *fi) {
    size_t len;
    (void) fi;
    if (strcmp(path, cfs_path) != 0)
        return -ENOENT;

    len = strlen(cfs_str);
    if (offset < len) {
        if (offset + size > len)
            size = len - offset;
        memcpy(buf, cfs_str + offset, size);
    } else
        size = 0;

    return size;
}

static struct fuse_operations cfs_oper = {
    .getattr = cfs_getattr,
    .readdir = cfs_readdir,
    .open = cfs_open,
    .read = cfs_read,
};

int main(int argc, char *argv[]) {
    return fuse_main(argc, argv, &cfs_oper, NULL);
}

here is my cfs_server.c :

/*
 * This is sample code generated by rpcgen.
 * These are only templates and you can use them
 * as a guideline for developing your own functions.
 */

#include "cfs.h"
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <rpc/pmap_clnt.h>

readdir_res * readdir_1_svc(nametype *dirname, struct svc_req *rqstp) {
    DIR *dp;
    struct dirent *directory;
    static readdir_res result;
    int inode;
    namelist nl;
    namelist *nlp;

    dp = opendir(*dirname);
    if (dp != NULL) {
        nlp = &result.readdir_res_u.list;
        while (directory = readdir(dp)) {
            nl = *nlp = (namenode *) malloc(sizeof (namenode));
            nl->name = directory->d_name;
            nlp = &nl->next; 
        }
    }
        *nlp = NULL;
       result.errnum = 0;
        closedir(dp);

    return &result;
}

and this is make file that I useed :

# This is a template Makefile generated by rpcgen

# Parameters

CLIENT = cfs_client
SERVER = cfs_server

SOURCES_CLNT.c = 
SOURCES_CLNT.h = 
SOURCES_SVC.c = 
SOURCES_SVC.h = 
SOURCES.x = cfs.x

TARGETS_SVC.c = cfs_svc.c cfs_server.c cfs_xdr.c 
TARGETS_CLNT.c = cfs_clnt.c cfs_client.c cfs_xdr.c 
TARGETS = cfs.h cfs_xdr.c cfs_clnt.c cfs_svc.c cfs_client.c cfs_server.c

OBJECTS_CLNT = $(SOURCES_CLNT.c:%.c=%.o) $(TARGETS_CLNT.c:%.c=%.o)
OBJECTS_SVC = $(SOURCES_SVC.c:%.c=%.o) $(TARGETS_SVC.c:%.c=%.o)
# Compiler flags 

CFLAGS += -g -Wall -DRPC_SVC_FG $(shell pkg-config fuse --cflags --libs)
LDLIBS += -lnsl
RPCGENFLAGS = -g

# Targets 

all : $(CLIENT) $(SERVER)

$(TARGETS) : $(SOURCES.x) 
    rpcgen $(RPCGENFLAGS) $(SOURCES.x)

$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) $(TARGETS_CLNT.c) 

$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) $(TARGETS_SVC.c) 

$(CLIENT) : $(OBJECTS_CLNT) 
    $(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) $(LDLIBS) 

$(SERVER) : $(OBJECTS_SVC) 
    $(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)

 clean:
     $(RM) core $(TARGETS) $(OBJECTS_CLNT) $(OBJECTS_SVC) $(CLIENT) $(SERVER)

edit : error is :

root@debian:/programs/c/rpc/custom file system# make -f Makefile.cfs
rpcgen -g cfs.x
usage: rpcgen infile
    rpcgen [-abkCLNTM][-Dname[=value]] [-i size] [-I [-K seconds]] [-Y path] infile
    rpcgen [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm] [-o outfile] [infile]
    rpcgen [-s nettype]* [-o outfile] [infile]
    rpcgen [-n netid]* [-o outfile] [infile]
options:
-a      generate all files, including samples
-b      backward compatibility mode (generates code for SunOS 4.1)
-c      generate XDR routines
-C      ANSI C mode
-Dname[=value]  define a symbol (same as #define)
-h      generate header file
-i size     size at which to start generating inline code
-I      generate code for inetd support in server (for SunOS 4.1)
-K seconds  server exits after K seconds of inactivity
-l      generate client side stubs
-L      server errors will be printed to syslog
-m      generate server side stubs
-M      generate MT-safe code
-n netid    generate server code that supports named netid
-N      supports multiple arguments and call-by-value
-o outfile  name of the output file
-s nettype  generate server code that supports named nettype
-Sc     generate sample client code that uses remote procedures
-Ss     generate sample server code that defines remote procedures
-Sm         generate makefile template 
-t      generate RPC dispatch table
-T      generate code to support RPC dispatch tables
-Y path     directory name to find C preprocessor (cpp)

For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
make: *** [cfs_clnt.c] Error 1
È stato utile?

Soluzione

I've solved my problem by using a bash file. This is my script for those who may have same problem as mine :

cc -g    -c -o cfs_clnt.o cfs_clnt.c
cc -g    -D_FILE_OFFSET_BITS=64 -c -o cfs_client.o cfs_client.c 
cc -g    -c -o cfs_xdr.o cfs_xdr.c
cc -g     -o cfs_client  cfs_clnt.o cfs_client.o cfs_xdr.o -lnsl -Wall `pkg-config fuse --cflags --libs`
cc -g    -c -o cfs_svc.o cfs_svc.c
cc -g    -c -o cfs_server.o cfs_server.c
cc -g     -o cfs_server  cfs_svc.o cfs_server.o cfs_xdr.o -lnsl
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top