Initial commit
This commit is contained in:
15
Makefile
Normal file
15
Makefile
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
CFLAGS += -Wall -ggdb -I/usr/include/tirpc
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: fs454-client fs454-server
|
||||||
|
$(CC) -Wall $^ -lfuse3 -lpthread -o $@
|
||||||
|
|
||||||
|
fs454-client: src/fs454_fuse.o src/fs454_clnt.o src/fs454_xdr.o
|
||||||
|
$(CC) -ggdb -Wall $^ -ltirpc -lfuse3 -lpthread -o $@
|
||||||
|
|
||||||
|
fs454-server: src/fs454_server.o src/fs454_svc.o src/fs454_xdr.o src/file_tree.o src/inode_tree.o src/fsio.o
|
||||||
|
$(CC) -Wall $^ -ltirpc -o $@
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -f src/*.o fs454-client fs454-server
|
||||||
178
src/file_tree.c
Normal file
178
src/file_tree.c
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "file_tree.h"
|
||||||
|
|
||||||
|
directory_list *file_tree_new() {
|
||||||
|
directory_list *list = malloc(sizeof(directory_list));
|
||||||
|
if(list != NULL) {
|
||||||
|
list->first = NULL;
|
||||||
|
list->last = NULL;
|
||||||
|
list->count = 0;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
directory_entry *file_tree_lookup(directory_list *list, long parent, const char *name) {
|
||||||
|
directory_list_node *node = file_tree_list_dir(list, parent);
|
||||||
|
if(node == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
dirent_list_node *dirent_node = node->directory.first;
|
||||||
|
while(dirent_node != NULL) {
|
||||||
|
if(strcmp(dirent_node->entry.name, name) == 0) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
dirent_node = dirent_node->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(dirent_node != NULL) {
|
||||||
|
return &dirent_node->entry;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
directory_list_node *file_tree_list_dir(directory_list *list, long directory) {
|
||||||
|
directory_list_node *node = list->first;
|
||||||
|
while(node != NULL) {
|
||||||
|
if(node->self.inode == directory) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_tree_insert_root(directory_list *list) {
|
||||||
|
directory_list_node *newnode = malloc(sizeof(directory_list_node));
|
||||||
|
newnode->next = NULL;
|
||||||
|
newnode->directory.count = 0;
|
||||||
|
newnode->directory.first = NULL;
|
||||||
|
newnode->directory.last = NULL;
|
||||||
|
newnode->self.inode = 1;
|
||||||
|
newnode->self.parent = 0;
|
||||||
|
newnode->self.name = malloc(strlen("") + 1);
|
||||||
|
newnode->self.name[0] = (char) 0;
|
||||||
|
list->first = newnode;
|
||||||
|
list->last = newnode;
|
||||||
|
list->count = 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_tree_insert(directory_list *list, long parent, const char *name, long inode) {
|
||||||
|
directory_list_node *node = file_tree_list_dir(list, parent);
|
||||||
|
if(node == NULL) {
|
||||||
|
/* Parent directory not found */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dirent_list_node *newnode = malloc(sizeof(dirent_list_node));
|
||||||
|
newnode->next = NULL;
|
||||||
|
unsigned int namelen = strlen(name) + 1;
|
||||||
|
newnode->entry.name = malloc(namelen);
|
||||||
|
strcpy(newnode->entry.name, name);
|
||||||
|
newnode->entry.inode = inode;
|
||||||
|
newnode->entry.parent = parent;
|
||||||
|
if(node->directory.last != NULL) {
|
||||||
|
node->directory.last->next = newnode;
|
||||||
|
node->directory.last = newnode;
|
||||||
|
} else {
|
||||||
|
node->directory.first = newnode;
|
||||||
|
node->directory.last = newnode;
|
||||||
|
}
|
||||||
|
node->directory.count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_tree_insert_dir(directory_list *list, long parent, const char *name, long inode) {
|
||||||
|
if(file_tree_list_dir(list, inode) != NULL) {
|
||||||
|
/* We can't have several hardlinks to the same directory */
|
||||||
|
return -1;
|
||||||
|
} else if(file_tree_insert(list, parent, name, inode) != 0) {
|
||||||
|
/* Parent directory not found */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
directory_list_node *newnode = malloc(sizeof(directory_list_node));
|
||||||
|
newnode->next = NULL;
|
||||||
|
newnode->self.inode = inode;
|
||||||
|
unsigned int namelen = strlen(name) + 1;
|
||||||
|
newnode->self.name = malloc(namelen);
|
||||||
|
strcpy(newnode->self.name, name);
|
||||||
|
newnode->self.parent = parent;
|
||||||
|
newnode->directory.first = NULL;
|
||||||
|
newnode->directory.last = NULL;
|
||||||
|
newnode->directory.count = 0;
|
||||||
|
list->last->next = newnode;
|
||||||
|
list->last = newnode;
|
||||||
|
list->count++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int file_tree_remove(directory_list *list, long parent, const char *name) {
|
||||||
|
directory_entry *entry = file_tree_lookup(list, parent, name);
|
||||||
|
if(entry == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
directory_list_node *dir_list = file_tree_list_dir(list, entry->inode);
|
||||||
|
if(dir_list != NULL && dir_list->directory.count > 0) {
|
||||||
|
return -1;
|
||||||
|
} else if(dir_list != NULL && dir_list->directory.count == 0) {
|
||||||
|
directory_list_node *prev = NULL;
|
||||||
|
directory_list_node *curr = list->first;
|
||||||
|
while(curr != NULL) {
|
||||||
|
if(curr->self.inode == entry->inode) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
prev = curr;
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(curr != NULL) {
|
||||||
|
if(prev != NULL) {
|
||||||
|
prev->next = curr->next;
|
||||||
|
if(prev->next == NULL) {
|
||||||
|
list->last = prev;
|
||||||
|
}
|
||||||
|
} else if(list->first == list->last) {
|
||||||
|
list->first = list->last = NULL;
|
||||||
|
} else {
|
||||||
|
list->first = curr->next;
|
||||||
|
}
|
||||||
|
free(curr->self.name);
|
||||||
|
free(curr);
|
||||||
|
list->count--;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
directory_list_node *parent_list = file_tree_list_dir(list, parent);
|
||||||
|
dirent_list_node *prev = NULL;
|
||||||
|
dirent_list_node *curr = parent_list->directory.first;
|
||||||
|
while (curr != NULL) {
|
||||||
|
if (curr->entry.inode == entry->inode){
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
prev = curr;
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (curr != NULL) {
|
||||||
|
if (prev != NULL) {
|
||||||
|
prev->next = curr->next;
|
||||||
|
if (prev->next == NULL) {
|
||||||
|
parent_list->directory.last = prev;
|
||||||
|
}
|
||||||
|
} else if (parent_list->directory.first == parent_list->directory.last) {
|
||||||
|
parent_list->directory.first = parent_list->directory.last = NULL;
|
||||||
|
} else {
|
||||||
|
parent_list->directory.first = curr->next;
|
||||||
|
}
|
||||||
|
free(curr->entry.name);
|
||||||
|
free(curr);
|
||||||
|
parent_list->directory.count--;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
45
src/file_tree.h
Normal file
45
src/file_tree.h
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#ifndef FS454_FILE_TREE
|
||||||
|
#define FS454_FILE_TREE
|
||||||
|
|
||||||
|
typedef struct directory_entry_t {
|
||||||
|
long inode;
|
||||||
|
long parent;
|
||||||
|
char *name;
|
||||||
|
} directory_entry;
|
||||||
|
|
||||||
|
typedef struct dirent_list_node_t {
|
||||||
|
struct dirent_list_node_t *next;
|
||||||
|
directory_entry entry;
|
||||||
|
} dirent_list_node;
|
||||||
|
|
||||||
|
typedef struct dirent_list_t {
|
||||||
|
dirent_list_node *first, *last;
|
||||||
|
long count;
|
||||||
|
} dirent_list;
|
||||||
|
|
||||||
|
typedef struct directory_list_node_t {
|
||||||
|
struct directory_list_node_t *next;
|
||||||
|
directory_entry self;
|
||||||
|
dirent_list directory;
|
||||||
|
} directory_list_node;
|
||||||
|
|
||||||
|
typedef struct directory_list_t {
|
||||||
|
directory_list_node *first, *last;
|
||||||
|
long count;
|
||||||
|
} directory_list;
|
||||||
|
|
||||||
|
directory_list *file_tree_new();
|
||||||
|
|
||||||
|
directory_entry *file_tree_lookup(directory_list *list, long parent, const char *name);
|
||||||
|
|
||||||
|
directory_list_node *file_tree_list_dir(directory_list *list, long directory);
|
||||||
|
|
||||||
|
int file_tree_insert_root(directory_list *list);
|
||||||
|
|
||||||
|
int file_tree_insert(directory_list *list, long parent, const char *name, long inode);
|
||||||
|
|
||||||
|
int file_tree_insert_dir(directory_list *list, long parent, const char *name, long inode);
|
||||||
|
|
||||||
|
int file_tree_remove(directory_list *list, long parent, const char *name);
|
||||||
|
|
||||||
|
#endif
|
||||||
315
src/fs454.h
Normal file
315
src/fs454.h
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
/*
|
||||||
|
* Please do not edit this file.
|
||||||
|
* It was generated using rpcgen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FS454_H_RPCGEN
|
||||||
|
#define _FS454_H_RPCGEN
|
||||||
|
|
||||||
|
#include <rpc/rpc.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct file_attributes {
|
||||||
|
long id;
|
||||||
|
long link_count;
|
||||||
|
long filesize;
|
||||||
|
long owner;
|
||||||
|
long mode;
|
||||||
|
long last_access;
|
||||||
|
long last_modify;
|
||||||
|
long last_change;
|
||||||
|
};
|
||||||
|
typedef struct file_attributes file_attributes;
|
||||||
|
|
||||||
|
struct dir_entry {
|
||||||
|
struct {
|
||||||
|
u_int name_len;
|
||||||
|
char *name_val;
|
||||||
|
} name;
|
||||||
|
struct file_attributes attributes;
|
||||||
|
struct dir_entry *next;
|
||||||
|
};
|
||||||
|
typedef struct dir_entry dir_entry;
|
||||||
|
|
||||||
|
enum error_code {
|
||||||
|
FS454_ENONE = 0,
|
||||||
|
FS454_ENOINODE = 0 + 1,
|
||||||
|
FS454_EINVAL = 0 + 2,
|
||||||
|
FS454_EIO = 0 + 3,
|
||||||
|
FS454_EBADF = 0 + 4,
|
||||||
|
FS454_EACCESS = 0 + 5,
|
||||||
|
FS454_ENOTDIR = 0 + 6,
|
||||||
|
FS454_ENOTEMPTY = 0 + 7,
|
||||||
|
};
|
||||||
|
typedef enum error_code error_code;
|
||||||
|
|
||||||
|
typedef dir_entry *entry_list;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_int byte_buffer_len;
|
||||||
|
u_char *byte_buffer_val;
|
||||||
|
} byte_buffer;
|
||||||
|
|
||||||
|
|
||||||
|
struct attribute_res {
|
||||||
|
error_code err;
|
||||||
|
union {
|
||||||
|
file_attributes attributes;
|
||||||
|
} attribute_res_u;
|
||||||
|
};
|
||||||
|
typedef struct attribute_res attribute_res;
|
||||||
|
|
||||||
|
struct string_res {
|
||||||
|
error_code err;
|
||||||
|
union {
|
||||||
|
char *str;
|
||||||
|
} string_res_u;
|
||||||
|
};
|
||||||
|
typedef struct string_res string_res;
|
||||||
|
|
||||||
|
struct readdir_res {
|
||||||
|
error_code err;
|
||||||
|
union {
|
||||||
|
entry_list entries;
|
||||||
|
} readdir_res_u;
|
||||||
|
};
|
||||||
|
typedef struct readdir_res readdir_res;
|
||||||
|
|
||||||
|
struct buffer_res {
|
||||||
|
error_code err;
|
||||||
|
union {
|
||||||
|
byte_buffer buffer;
|
||||||
|
} buffer_res_u;
|
||||||
|
};
|
||||||
|
typedef struct buffer_res buffer_res;
|
||||||
|
|
||||||
|
struct allocate_1_argument {
|
||||||
|
long arg1;
|
||||||
|
long arg2;
|
||||||
|
};
|
||||||
|
typedef struct allocate_1_argument allocate_1_argument;
|
||||||
|
|
||||||
|
struct link_1_argument {
|
||||||
|
long arg1;
|
||||||
|
char *arg2;
|
||||||
|
long arg3;
|
||||||
|
};
|
||||||
|
typedef struct link_1_argument link_1_argument;
|
||||||
|
|
||||||
|
struct lookup_1_argument {
|
||||||
|
char *arg1;
|
||||||
|
long arg2;
|
||||||
|
};
|
||||||
|
typedef struct lookup_1_argument lookup_1_argument;
|
||||||
|
|
||||||
|
struct mkdir_1_argument {
|
||||||
|
char *arg1;
|
||||||
|
long arg2;
|
||||||
|
long arg3;
|
||||||
|
};
|
||||||
|
typedef struct mkdir_1_argument mkdir_1_argument;
|
||||||
|
|
||||||
|
struct mknod_1_argument {
|
||||||
|
char *arg1;
|
||||||
|
long arg2;
|
||||||
|
long arg3;
|
||||||
|
};
|
||||||
|
typedef struct mknod_1_argument mknod_1_argument;
|
||||||
|
|
||||||
|
struct read_1_argument {
|
||||||
|
long arg1;
|
||||||
|
long arg2;
|
||||||
|
long arg3;
|
||||||
|
};
|
||||||
|
typedef struct read_1_argument read_1_argument;
|
||||||
|
|
||||||
|
struct setattr_1_argument {
|
||||||
|
long arg1;
|
||||||
|
long arg2;
|
||||||
|
struct file_attributes arg3;
|
||||||
|
};
|
||||||
|
typedef struct setattr_1_argument setattr_1_argument;
|
||||||
|
|
||||||
|
struct symlink_1_argument {
|
||||||
|
char *arg1;
|
||||||
|
long arg2;
|
||||||
|
char *arg3;
|
||||||
|
};
|
||||||
|
typedef struct symlink_1_argument symlink_1_argument;
|
||||||
|
|
||||||
|
struct unlink_1_argument {
|
||||||
|
long arg1;
|
||||||
|
char *arg2;
|
||||||
|
};
|
||||||
|
typedef struct unlink_1_argument unlink_1_argument;
|
||||||
|
|
||||||
|
struct write_1_argument {
|
||||||
|
long arg1;
|
||||||
|
byte_buffer arg2;
|
||||||
|
long arg3;
|
||||||
|
long arg4;
|
||||||
|
};
|
||||||
|
typedef struct write_1_argument write_1_argument;
|
||||||
|
|
||||||
|
struct copy_1_argument {
|
||||||
|
long arg1;
|
||||||
|
long arg2;
|
||||||
|
long arg3;
|
||||||
|
long arg4;
|
||||||
|
long arg5;
|
||||||
|
};
|
||||||
|
typedef struct copy_1_argument copy_1_argument;
|
||||||
|
|
||||||
|
#define FS454 0x33764824
|
||||||
|
#define MESSAGEVERS 1
|
||||||
|
|
||||||
|
#if defined(__STDC__) || defined(__cplusplus)
|
||||||
|
#define ALLOCATE 1
|
||||||
|
extern error_code * allocate_1(long , long , CLIENT *);
|
||||||
|
extern error_code * allocate_1_svc(long , long , struct svc_req *);
|
||||||
|
#define GETATTR 2
|
||||||
|
extern attribute_res * getattr_1(long , CLIENT *);
|
||||||
|
extern attribute_res * getattr_1_svc(long , struct svc_req *);
|
||||||
|
#define LINK 3
|
||||||
|
extern attribute_res * link_1(long , char *, long , CLIENT *);
|
||||||
|
extern attribute_res * link_1_svc(long , char *, long , struct svc_req *);
|
||||||
|
#define LOOKUP 4
|
||||||
|
extern attribute_res * lookup_1(char *, long , CLIENT *);
|
||||||
|
extern attribute_res * lookup_1_svc(char *, long , struct svc_req *);
|
||||||
|
#define MKDIR 5
|
||||||
|
extern attribute_res * mkdir_1(char *, long , long , CLIENT *);
|
||||||
|
extern attribute_res * mkdir_1_svc(char *, long , long , struct svc_req *);
|
||||||
|
#define MKNOD 6
|
||||||
|
extern attribute_res * mknod_1(char *, long , long , CLIENT *);
|
||||||
|
extern attribute_res * mknod_1_svc(char *, long , long , struct svc_req *);
|
||||||
|
#define READ 7
|
||||||
|
extern buffer_res * read_1(long , long , long , CLIENT *);
|
||||||
|
extern buffer_res * read_1_svc(long , long , long , struct svc_req *);
|
||||||
|
#define READDIR 8
|
||||||
|
extern readdir_res * readdir_1(long , CLIENT *);
|
||||||
|
extern readdir_res * readdir_1_svc(long , struct svc_req *);
|
||||||
|
#define READLINK 9
|
||||||
|
extern string_res * readlink_1(long , CLIENT *);
|
||||||
|
extern string_res * readlink_1_svc(long , struct svc_req *);
|
||||||
|
#define SETATTR 10
|
||||||
|
extern attribute_res * setattr_1(long , long , struct file_attributes , CLIENT *);
|
||||||
|
extern attribute_res * setattr_1_svc(long , long , struct file_attributes , struct svc_req *);
|
||||||
|
#define SYMLINK 11
|
||||||
|
extern attribute_res * symlink_1(char *, long , char *, CLIENT *);
|
||||||
|
extern attribute_res * symlink_1_svc(char *, long , char *, struct svc_req *);
|
||||||
|
#define UNLINK 12
|
||||||
|
extern error_code * unlink_1(long , char *, CLIENT *);
|
||||||
|
extern error_code * unlink_1_svc(long , char *, struct svc_req *);
|
||||||
|
#define WRITE 13
|
||||||
|
extern error_code * write_1(long , byte_buffer , long , long , CLIENT *);
|
||||||
|
extern error_code * write_1_svc(long , byte_buffer , long , long , struct svc_req *);
|
||||||
|
#define COPY 14
|
||||||
|
extern error_code * copy_1(long , long , long , long , long , CLIENT *);
|
||||||
|
extern error_code * copy_1_svc(long , long , long , long , long , struct svc_req *);
|
||||||
|
extern int fs454_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t);
|
||||||
|
|
||||||
|
#else /* K&R C */
|
||||||
|
#define ALLOCATE 1
|
||||||
|
extern error_code * allocate_1();
|
||||||
|
extern error_code * allocate_1_svc();
|
||||||
|
#define GETATTR 2
|
||||||
|
extern attribute_res * getattr_1();
|
||||||
|
extern attribute_res * getattr_1_svc();
|
||||||
|
#define LINK 3
|
||||||
|
extern attribute_res * link_1();
|
||||||
|
extern attribute_res * link_1_svc();
|
||||||
|
#define LOOKUP 4
|
||||||
|
extern attribute_res * lookup_1();
|
||||||
|
extern attribute_res * lookup_1_svc();
|
||||||
|
#define MKDIR 5
|
||||||
|
extern attribute_res * mkdir_1();
|
||||||
|
extern attribute_res * mkdir_1_svc();
|
||||||
|
#define MKNOD 6
|
||||||
|
extern attribute_res * mknod_1();
|
||||||
|
extern attribute_res * mknod_1_svc();
|
||||||
|
#define READ 7
|
||||||
|
extern buffer_res * read_1();
|
||||||
|
extern buffer_res * read_1_svc();
|
||||||
|
#define READDIR 8
|
||||||
|
extern readdir_res * readdir_1();
|
||||||
|
extern readdir_res * readdir_1_svc();
|
||||||
|
#define READLINK 9
|
||||||
|
extern string_res * readlink_1();
|
||||||
|
extern string_res * readlink_1_svc();
|
||||||
|
#define SETATTR 10
|
||||||
|
extern attribute_res * setattr_1();
|
||||||
|
extern attribute_res * setattr_1_svc();
|
||||||
|
#define SYMLINK 11
|
||||||
|
extern attribute_res * symlink_1();
|
||||||
|
extern attribute_res * symlink_1_svc();
|
||||||
|
#define UNLINK 12
|
||||||
|
extern error_code * unlink_1();
|
||||||
|
extern error_code * unlink_1_svc();
|
||||||
|
#define WRITE 13
|
||||||
|
extern error_code * write_1();
|
||||||
|
extern error_code * write_1_svc();
|
||||||
|
#define COPY 14
|
||||||
|
extern error_code * copy_1();
|
||||||
|
extern error_code * copy_1_svc();
|
||||||
|
extern int fs454_1_freeresult ();
|
||||||
|
#endif /* K&R C */
|
||||||
|
|
||||||
|
/* the xdr functions */
|
||||||
|
|
||||||
|
#if defined(__STDC__) || defined(__cplusplus)
|
||||||
|
extern bool_t xdr_file_attributes (XDR *, file_attributes*);
|
||||||
|
extern bool_t xdr_dir_entry (XDR *, dir_entry*);
|
||||||
|
extern bool_t xdr_error_code (XDR *, error_code*);
|
||||||
|
extern bool_t xdr_entry_list (XDR *, entry_list*);
|
||||||
|
extern bool_t xdr_byte_buffer (XDR *, byte_buffer*);
|
||||||
|
extern bool_t xdr_file_attributes (XDR *, file_attributes*);
|
||||||
|
extern bool_t xdr_attribute_res (XDR *, attribute_res*);
|
||||||
|
extern bool_t xdr_string_res (XDR *, string_res*);
|
||||||
|
extern bool_t xdr_readdir_res (XDR *, readdir_res*);
|
||||||
|
extern bool_t xdr_buffer_res (XDR *, buffer_res*);
|
||||||
|
extern bool_t xdr_allocate_1_argument (XDR *, allocate_1_argument*);
|
||||||
|
extern bool_t xdr_link_1_argument (XDR *, link_1_argument*);
|
||||||
|
extern bool_t xdr_lookup_1_argument (XDR *, lookup_1_argument*);
|
||||||
|
extern bool_t xdr_mkdir_1_argument (XDR *, mkdir_1_argument*);
|
||||||
|
extern bool_t xdr_mknod_1_argument (XDR *, mknod_1_argument*);
|
||||||
|
extern bool_t xdr_read_1_argument (XDR *, read_1_argument*);
|
||||||
|
extern bool_t xdr_setattr_1_argument (XDR *, setattr_1_argument*);
|
||||||
|
extern bool_t xdr_symlink_1_argument (XDR *, symlink_1_argument*);
|
||||||
|
extern bool_t xdr_unlink_1_argument (XDR *, unlink_1_argument*);
|
||||||
|
extern bool_t xdr_write_1_argument (XDR *, write_1_argument*);
|
||||||
|
extern bool_t xdr_copy_1_argument (XDR *, copy_1_argument*);
|
||||||
|
|
||||||
|
#else /* K&R C */
|
||||||
|
extern bool_t xdr_file_attributes ();
|
||||||
|
extern bool_t xdr_dir_entry ();
|
||||||
|
extern bool_t xdr_error_code ();
|
||||||
|
extern bool_t xdr_entry_list ();
|
||||||
|
extern bool_t xdr_byte_buffer ();
|
||||||
|
extern bool_t xdr_file_attributes ();
|
||||||
|
extern bool_t xdr_attribute_res ();
|
||||||
|
extern bool_t xdr_string_res ();
|
||||||
|
extern bool_t xdr_readdir_res ();
|
||||||
|
extern bool_t xdr_buffer_res ();
|
||||||
|
extern bool_t xdr_allocate_1_argument ();
|
||||||
|
extern bool_t xdr_link_1_argument ();
|
||||||
|
extern bool_t xdr_lookup_1_argument ();
|
||||||
|
extern bool_t xdr_mkdir_1_argument ();
|
||||||
|
extern bool_t xdr_mknod_1_argument ();
|
||||||
|
extern bool_t xdr_read_1_argument ();
|
||||||
|
extern bool_t xdr_setattr_1_argument ();
|
||||||
|
extern bool_t xdr_symlink_1_argument ();
|
||||||
|
extern bool_t xdr_unlink_1_argument ();
|
||||||
|
extern bool_t xdr_write_1_argument ();
|
||||||
|
extern bool_t xdr_copy_1_argument ();
|
||||||
|
|
||||||
|
#endif /* K&R C */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !_FS454_H_RPCGEN */
|
||||||
80
src/fs454.x
Normal file
80
src/fs454.x
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
struct file_attributes {
|
||||||
|
long id;
|
||||||
|
long link_count;
|
||||||
|
long filesize;
|
||||||
|
long owner;
|
||||||
|
long mode;
|
||||||
|
long last_access;
|
||||||
|
long last_modify;
|
||||||
|
long last_change;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dir_entry {
|
||||||
|
char name<>;
|
||||||
|
struct file_attributes attributes;
|
||||||
|
struct dir_entry *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum error_code {
|
||||||
|
FS454_ENONE = 0,
|
||||||
|
FS454_ENOINODE,
|
||||||
|
FS454_EINVAL,
|
||||||
|
FS454_EIO,
|
||||||
|
FS454_EBADF,
|
||||||
|
FS454_EACCESS,
|
||||||
|
FS454_ENOTDIR,
|
||||||
|
FS454_ENOTEMPTY
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct dir_entry *entry_list;
|
||||||
|
|
||||||
|
typedef unsigned char byte_buffer<>;
|
||||||
|
|
||||||
|
typedef struct file_attributes file_attributes;
|
||||||
|
|
||||||
|
union attribute_res switch(error_code err) {
|
||||||
|
case FS454_ENONE:
|
||||||
|
file_attributes attributes;
|
||||||
|
default:
|
||||||
|
void;
|
||||||
|
};
|
||||||
|
|
||||||
|
union string_res switch(error_code err) {
|
||||||
|
case FS454_ENONE:
|
||||||
|
string str<>;
|
||||||
|
default:
|
||||||
|
void;
|
||||||
|
};
|
||||||
|
|
||||||
|
union readdir_res switch(error_code err) {
|
||||||
|
case FS454_ENONE:
|
||||||
|
entry_list entries;
|
||||||
|
default:
|
||||||
|
void;
|
||||||
|
};
|
||||||
|
|
||||||
|
union buffer_res switch(error_code err) {
|
||||||
|
case FS454_ENONE:
|
||||||
|
byte_buffer buffer;
|
||||||
|
default:
|
||||||
|
void;
|
||||||
|
};
|
||||||
|
|
||||||
|
program FS454 {
|
||||||
|
version MESSAGEVERS {
|
||||||
|
error_code ALLOCATE(long, long) = 1;
|
||||||
|
attribute_res GETATTR(long) = 2;
|
||||||
|
attribute_res LINK(long, string, long) = 3;
|
||||||
|
attribute_res LOOKUP(string, long) = 4;
|
||||||
|
attribute_res MKDIR(string, long, long) = 5;
|
||||||
|
attribute_res MKNOD(string, long, long) = 6;
|
||||||
|
buffer_res READ(long, long, long) = 7;
|
||||||
|
readdir_res READDIR(long) = 8;
|
||||||
|
string_res READLINK(long) = 9;
|
||||||
|
attribute_res SETATTR(long, long, struct file_attributes) = 10;
|
||||||
|
attribute_res SYMLINK(string, long, string) = 11;
|
||||||
|
error_code UNLINK(long, string) = 12;
|
||||||
|
error_code WRITE(long, byte_buffer, long, long) = 13;
|
||||||
|
error_code COPY(long, long, long, long, long) = 14;
|
||||||
|
} = 1;
|
||||||
|
} = 0x33764824;
|
||||||
253
src/fs454_clnt.c
Normal file
253
src/fs454_clnt.c
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
/*
|
||||||
|
* Please do not edit this file.
|
||||||
|
* It was generated using rpcgen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <memory.h> /* for memset */
|
||||||
|
#include "fs454.h"
|
||||||
|
|
||||||
|
/* Default timeout can be changed using clnt_control() */
|
||||||
|
static struct timeval TIMEOUT = { 25, 0 };
|
||||||
|
|
||||||
|
error_code *
|
||||||
|
allocate_1(long arg1, long arg2, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
allocate_1_argument arg;
|
||||||
|
static error_code clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
arg.arg1 = arg1;
|
||||||
|
arg.arg2 = arg2;
|
||||||
|
if (clnt_call (clnt, ALLOCATE, (xdrproc_t) xdr_allocate_1_argument, (caddr_t) &arg,
|
||||||
|
(xdrproc_t) xdr_error_code, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *
|
||||||
|
getattr_1(long arg1, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
static attribute_res clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
if (clnt_call (clnt, GETATTR,
|
||||||
|
(xdrproc_t) xdr_long, (caddr_t) &arg1,
|
||||||
|
(xdrproc_t) xdr_attribute_res, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *
|
||||||
|
link_1(long arg1, char *arg2, long arg3, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
link_1_argument arg;
|
||||||
|
static attribute_res clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
arg.arg1 = arg1;
|
||||||
|
arg.arg2 = arg2;
|
||||||
|
arg.arg3 = arg3;
|
||||||
|
if (clnt_call (clnt, LINK, (xdrproc_t) xdr_link_1_argument, (caddr_t) &arg,
|
||||||
|
(xdrproc_t) xdr_attribute_res, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *
|
||||||
|
lookup_1(char *arg1, long arg2, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
lookup_1_argument arg;
|
||||||
|
static attribute_res clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
arg.arg1 = arg1;
|
||||||
|
arg.arg2 = arg2;
|
||||||
|
if (clnt_call (clnt, LOOKUP, (xdrproc_t) xdr_lookup_1_argument, (caddr_t) &arg,
|
||||||
|
(xdrproc_t) xdr_attribute_res, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *
|
||||||
|
mkdir_1(char *arg1, long arg2, long arg3, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
mkdir_1_argument arg;
|
||||||
|
static attribute_res clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
arg.arg1 = arg1;
|
||||||
|
arg.arg2 = arg2;
|
||||||
|
arg.arg3 = arg3;
|
||||||
|
if (clnt_call (clnt, MKDIR, (xdrproc_t) xdr_mkdir_1_argument, (caddr_t) &arg,
|
||||||
|
(xdrproc_t) xdr_attribute_res, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *
|
||||||
|
mknod_1(char *arg1, long arg2, long arg3, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
mknod_1_argument arg;
|
||||||
|
static attribute_res clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
arg.arg1 = arg1;
|
||||||
|
arg.arg2 = arg2;
|
||||||
|
arg.arg3 = arg3;
|
||||||
|
if (clnt_call (clnt, MKNOD, (xdrproc_t) xdr_mknod_1_argument, (caddr_t) &arg,
|
||||||
|
(xdrproc_t) xdr_attribute_res, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_res *
|
||||||
|
read_1(long arg1, long arg2, long arg3, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
read_1_argument arg;
|
||||||
|
static buffer_res clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
arg.arg1 = arg1;
|
||||||
|
arg.arg2 = arg2;
|
||||||
|
arg.arg3 = arg3;
|
||||||
|
if (clnt_call (clnt, READ, (xdrproc_t) xdr_read_1_argument, (caddr_t) &arg,
|
||||||
|
(xdrproc_t) xdr_buffer_res, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
readdir_res *
|
||||||
|
readdir_1(long arg1, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
static readdir_res clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
if (clnt_call (clnt, READDIR,
|
||||||
|
(xdrproc_t) xdr_long, (caddr_t) &arg1,
|
||||||
|
(xdrproc_t) xdr_readdir_res, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
string_res *
|
||||||
|
readlink_1(long arg1, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
static string_res clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
if (clnt_call (clnt, READLINK,
|
||||||
|
(xdrproc_t) xdr_long, (caddr_t) &arg1,
|
||||||
|
(xdrproc_t) xdr_string_res, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *
|
||||||
|
setattr_1(long arg1, long arg2, struct file_attributes arg3, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
setattr_1_argument arg;
|
||||||
|
static attribute_res clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
arg.arg1 = arg1;
|
||||||
|
arg.arg2 = arg2;
|
||||||
|
arg.arg3 = arg3;
|
||||||
|
if (clnt_call (clnt, SETATTR, (xdrproc_t) xdr_setattr_1_argument, (caddr_t) &arg,
|
||||||
|
(xdrproc_t) xdr_attribute_res, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *
|
||||||
|
symlink_1(char *arg1, long arg2, char *arg3, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
symlink_1_argument arg;
|
||||||
|
static attribute_res clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
arg.arg1 = arg1;
|
||||||
|
arg.arg2 = arg2;
|
||||||
|
arg.arg3 = arg3;
|
||||||
|
if (clnt_call (clnt, SYMLINK, (xdrproc_t) xdr_symlink_1_argument, (caddr_t) &arg,
|
||||||
|
(xdrproc_t) xdr_attribute_res, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
error_code *
|
||||||
|
unlink_1(long arg1, char *arg2, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
unlink_1_argument arg;
|
||||||
|
static error_code clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
arg.arg1 = arg1;
|
||||||
|
arg.arg2 = arg2;
|
||||||
|
if (clnt_call (clnt, UNLINK, (xdrproc_t) xdr_unlink_1_argument, (caddr_t) &arg,
|
||||||
|
(xdrproc_t) xdr_error_code, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
error_code *
|
||||||
|
write_1(long arg1, byte_buffer arg2, long arg3, long arg4, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
write_1_argument arg;
|
||||||
|
static error_code clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
arg.arg1 = arg1;
|
||||||
|
arg.arg2 = arg2;
|
||||||
|
arg.arg3 = arg3;
|
||||||
|
arg.arg4 = arg4;
|
||||||
|
if (clnt_call (clnt, WRITE, (xdrproc_t) xdr_write_1_argument, (caddr_t) &arg,
|
||||||
|
(xdrproc_t) xdr_error_code, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
|
|
||||||
|
error_code *
|
||||||
|
copy_1(long arg1, long arg2, long arg3, long arg4, long arg5, CLIENT *clnt)
|
||||||
|
{
|
||||||
|
copy_1_argument arg;
|
||||||
|
static error_code clnt_res;
|
||||||
|
|
||||||
|
memset((char *)&clnt_res, 0, sizeof(clnt_res));
|
||||||
|
arg.arg1 = arg1;
|
||||||
|
arg.arg2 = arg2;
|
||||||
|
arg.arg3 = arg3;
|
||||||
|
arg.arg4 = arg4;
|
||||||
|
arg.arg5 = arg5;
|
||||||
|
if (clnt_call (clnt, COPY, (xdrproc_t) xdr_copy_1_argument, (caddr_t) &arg,
|
||||||
|
(xdrproc_t) xdr_error_code, (caddr_t) &clnt_res,
|
||||||
|
TIMEOUT) != RPC_SUCCESS) {
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
return (&clnt_res);
|
||||||
|
}
|
||||||
428
src/fs454_fuse.c
Normal file
428
src/fs454_fuse.c
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
#define FUSE_USE_VERSION 34
|
||||||
|
|
||||||
|
#include "fuse3/fuse_lowlevel.h"
|
||||||
|
#include "fs454.h"
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
CLIENT *rpc_client;
|
||||||
|
|
||||||
|
struct buffer_t
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
void fill_stat(struct stat *dest, file_attributes *src) {
|
||||||
|
memset(dest, 0, sizeof(struct stat));
|
||||||
|
dest->st_ino = src->id;
|
||||||
|
dest->st_size = src->filesize;
|
||||||
|
dest->st_uid = src->owner;
|
||||||
|
dest->st_gid = 0;
|
||||||
|
dest->st_mode = src->mode;
|
||||||
|
dest->st_nlink = src->link_count;
|
||||||
|
dest->st_atime = src->last_access;
|
||||||
|
dest->st_ctime = src->last_change;
|
||||||
|
dest->st_mtime = src->last_modify;
|
||||||
|
}
|
||||||
|
|
||||||
|
int buffer_resize(struct buffer_t *buffer, size_t size) {
|
||||||
|
if(buffer != NULL) {
|
||||||
|
buffer->ptr = realloc(buffer->ptr, size);
|
||||||
|
if(buffer->ptr == NULL) {
|
||||||
|
buffer->size = 0;
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
buffer->size = size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void buffer_free(struct buffer_t *buffer) {
|
||||||
|
if(buffer != NULL) {
|
||||||
|
if(buffer->ptr != NULL) {
|
||||||
|
free(buffer->ptr);
|
||||||
|
buffer->ptr = NULL;
|
||||||
|
}
|
||||||
|
buffer->size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int append_dirent(fuse_req_t request, struct buffer_t *buffer, const char *name, struct stat *attr) {
|
||||||
|
size_t prev_size = buffer->size;
|
||||||
|
if(buffer_resize(buffer, prev_size + fuse_add_direntry(request, NULL, 0, name, NULL, 0))) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
fuse_add_direntry(request, buffer->ptr + prev_size, buffer->size - prev_size, name, attr, buffer->size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_access(fuse_req_t req, fuse_ino_t ino, int mask) {
|
||||||
|
fuse_reply_err(req, ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_copy_file_range(fuse_req_t req, fuse_ino_t ino_in, off_t off_in, struct fuse_file_info *fi_in, fuse_ino_t ino_out, off_t off_out, struct fuse_file_info *fi_out, size_t len, int flags) {
|
||||||
|
fuse_reply_err(req, ENOSYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_fallocate(fuse_req_t request, fuse_ino_t inode, int mode, off_t offset, off_t length, struct fuse_file_info *fi) {
|
||||||
|
if(mode == 0) {
|
||||||
|
error_code *result = allocate_1(inode, offset + length, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else if(*result == FS454_ENONE) {
|
||||||
|
fuse_reply_err(request, 0);
|
||||||
|
} else {
|
||||||
|
fuse_reply_err(request, ENOENT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fuse_reply_err(request, EOPNOTSUPP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_getattr(fuse_req_t request, ino_t inode, struct fuse_file_info *info) {
|
||||||
|
attribute_res *result = getattr_1(inode, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else if(result->err == FS454_ENONE) {
|
||||||
|
struct stat s;
|
||||||
|
fill_stat(&s, &result->attribute_res_u.attributes);
|
||||||
|
fuse_reply_attr(request, &s, 0);
|
||||||
|
} else {
|
||||||
|
printf("\terror %i in getattr\n", result->err);
|
||||||
|
fuse_reply_err(request, ENOENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_link(fuse_req_t request, fuse_ino_t inode, fuse_ino_t newparent, const char *newname) {
|
||||||
|
attribute_res *result = link_1(inode, newname, newparent, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else if(result->err != FS454_ENONE) {
|
||||||
|
printf("link %i/%s -> %i failed with error %i\n", newparent, newname, inode, result->err);
|
||||||
|
fuse_reply_err(request, ENOENT);
|
||||||
|
} else {
|
||||||
|
struct fuse_entry_param entry = {
|
||||||
|
.attr_timeout = 0,
|
||||||
|
.entry_timeout = 0,
|
||||||
|
.generation = 0,
|
||||||
|
.ino = result->attribute_res_u.attributes.id
|
||||||
|
};
|
||||||
|
fill_stat(&entry.attr, &result->attribute_res_u.attributes);
|
||||||
|
fuse_reply_entry(request, &entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_lookup(fuse_req_t request, fuse_ino_t parent, const char *name) {
|
||||||
|
attribute_res *result = lookup_1(name, parent, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else if(result->err == FS454_ENONE) {
|
||||||
|
struct fuse_entry_param entry = {
|
||||||
|
.attr_timeout = 0,
|
||||||
|
.entry_timeout = 0,
|
||||||
|
.generation = 0,
|
||||||
|
.ino = result->attribute_res_u.attributes.id
|
||||||
|
};
|
||||||
|
fill_stat(&entry.attr, &result->attribute_res_u.attributes);
|
||||||
|
fuse_reply_entry(request, &entry);
|
||||||
|
} else {
|
||||||
|
fuse_reply_err(request, ENOENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_mknod(fuse_req_t request, fuse_ino_t parent, const char *name, mode_t mode, dev_t rdev) {
|
||||||
|
attribute_res *result = mknod_1(name, parent, mode, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else if(result->err == FS454_ENONE) {
|
||||||
|
struct fuse_entry_param entry = {
|
||||||
|
.attr_timeout = 0,
|
||||||
|
.entry_timeout = 0,
|
||||||
|
.generation = 0,
|
||||||
|
.ino = result->attribute_res_u.attributes.id
|
||||||
|
};
|
||||||
|
fill_stat(&entry.attr, &result->attribute_res_u.attributes);
|
||||||
|
fuse_reply_entry(request, &entry);
|
||||||
|
} else {
|
||||||
|
fuse_reply_err(request, EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_mkdir(fuse_req_t request, fuse_ino_t parent, const char *name, mode_t mode) {
|
||||||
|
attribute_res *result = mkdir_1(name, parent, mode, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else if(result->err == FS454_ENONE) {
|
||||||
|
struct fuse_entry_param entry = {
|
||||||
|
.attr_timeout = 0,
|
||||||
|
.entry_timeout = 0,
|
||||||
|
.generation = 0,
|
||||||
|
.ino = result->attribute_res_u.attributes.id
|
||||||
|
};
|
||||||
|
fill_stat(&entry.attr, &result->attribute_res_u.attributes);
|
||||||
|
fuse_reply_entry(request, &entry);
|
||||||
|
} else {
|
||||||
|
printf("mkdir failed error %i\n", result->err);
|
||||||
|
fuse_reply_err(request, EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_open(fuse_req_t request, fuse_ino_t inode, struct fuse_file_info *finfo) {
|
||||||
|
finfo->keep_cache = 0;
|
||||||
|
fuse_reply_open(request, finfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_read(fuse_req_t request, fuse_ino_t inode, size_t size, off_t off, struct fuse_file_info *info) {
|
||||||
|
buffer_res *result = read_1(inode, off, size, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else if(result->err == FS454_ENONE) {
|
||||||
|
fuse_reply_buf(request, result->buffer_res_u.buffer.byte_buffer_val, result->buffer_res_u.buffer.byte_buffer_len);
|
||||||
|
} else {
|
||||||
|
printf("read failed error %i\n", result->err);
|
||||||
|
fuse_reply_err(request, ENOENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_readdir(fuse_req_t request, fuse_ino_t inode, size_t size, off_t off, struct fuse_file_info *info) {
|
||||||
|
readdir_res *result = readdir_1(inode, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else if(result->err == FS454_ENONE) {
|
||||||
|
struct buffer_t buffer = {0};
|
||||||
|
struct dir_entry *entry = result->readdir_res_u.entries;
|
||||||
|
while(entry != NULL) {
|
||||||
|
struct stat attr;
|
||||||
|
fill_stat(&attr, &entry->attributes);
|
||||||
|
append_dirent(request, &buffer, entry->name.name_val, &attr);
|
||||||
|
entry = entry->next;
|
||||||
|
}
|
||||||
|
if(off < buffer.size) {
|
||||||
|
if(buffer.size - off < size) {
|
||||||
|
fuse_reply_buf(request, buffer.ptr + off, buffer.size - off);
|
||||||
|
} else {
|
||||||
|
fuse_reply_buf(request, buffer.ptr + off, size);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fuse_reply_buf(request, NULL, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printf("readdir failed error %i\n", result->err);
|
||||||
|
fuse_reply_err(request, EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_readlink(fuse_req_t request, fuse_ino_t inode) {
|
||||||
|
string_res *link = readlink_1(inode, rpc_client);
|
||||||
|
if(link == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else {
|
||||||
|
fuse_reply_readlink(request, link->string_res_u.str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_rename(fuse_req_t request, fuse_ino_t parent, const char *name, fuse_ino_t newparent, const char *newname, unsigned int flags) {
|
||||||
|
if(parent == newparent && strcmp(name, newname) == 0) {
|
||||||
|
fuse_reply_err(request, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
attribute_res *oldattr = lookup_1(name, parent, rpc_client);
|
||||||
|
if(oldattr == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
return;
|
||||||
|
} else if(oldattr->err != FS454_ENONE) {
|
||||||
|
fuse_reply_err(request, ENOENT);
|
||||||
|
}
|
||||||
|
attribute_res *link_result = link_1(oldattr->attribute_res_u.attributes.id, newname, newparent, rpc_client);
|
||||||
|
if(link_result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else if(link_result->err != FS454_ENONE) {
|
||||||
|
printf("rename failed to link with error %i\n", link_result->err);
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else {
|
||||||
|
error_code *unlink_result = unlink_1(parent, name, rpc_client);
|
||||||
|
if(*unlink_result != FS454_ENONE) {
|
||||||
|
printf("rename failed to unlink with error %i\n", link_result->err);
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else {
|
||||||
|
fuse_reply_err(request, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_rmdir(fuse_req_t request, fuse_ino_t parent, const char *name) {
|
||||||
|
error_code *result = unlink_1(parent, name, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else {
|
||||||
|
fuse_reply_err(request, *result == FS454_ENONE ? 0 : EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_setattr(fuse_req_t request, fuse_ino_t inode, struct stat *attr, int to_set, struct fuse_file_info *fi) {
|
||||||
|
file_attributes attributes = {
|
||||||
|
.id = inode,
|
||||||
|
.filesize = attr->st_size,
|
||||||
|
.owner = attr->st_uid,
|
||||||
|
.mode = attr->st_mode,
|
||||||
|
.last_access = attr->st_atime,
|
||||||
|
.last_change = attr->st_ctime,
|
||||||
|
.last_modify = attr->st_mtime
|
||||||
|
};
|
||||||
|
attribute_res *result = setattr_1(inode, to_set, attributes, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else if(result->err == FS454_ENONE) {
|
||||||
|
struct stat s;
|
||||||
|
fill_stat(&s, &result->attribute_res_u.attributes);
|
||||||
|
fuse_reply_attr(request, &s, 0);
|
||||||
|
} else {
|
||||||
|
printf("setattr error %i\n", result->err);
|
||||||
|
fuse_reply_err(request, EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_symlink(fuse_req_t request, const char *link, fuse_ino_t parent, const char *name) {
|
||||||
|
attribute_res *result = symlink_1(link, parent, name, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else {
|
||||||
|
file_attributes *attr = &result->attribute_res_u.attributes;
|
||||||
|
struct stat n;
|
||||||
|
struct fuse_entry_param entry = {
|
||||||
|
.attr_timeout = 0,
|
||||||
|
.entry_timeout = 0,
|
||||||
|
.generation = 0,
|
||||||
|
.ino = attr->id
|
||||||
|
};
|
||||||
|
fill_stat(&entry.attr, attr);
|
||||||
|
fuse_reply_entry(request, &entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_unlink(fuse_req_t request, fuse_ino_t parent, const char *name) {
|
||||||
|
error_code *result = unlink_1(parent, name, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else {
|
||||||
|
fuse_reply_err(request, (int) (*result == FS454_ENONE ? 0 : ENOENT));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void fs454_write(fuse_req_t request, fuse_ino_t inode, const char *buffer, size_t size, off_t offset, struct fuse_file_info *fi) {
|
||||||
|
char *copy = malloc(size);
|
||||||
|
memcpy(copy, buffer, size);
|
||||||
|
byte_buffer arg_buffer = {
|
||||||
|
.byte_buffer_len = size,
|
||||||
|
.byte_buffer_val = copy
|
||||||
|
};
|
||||||
|
error_code *result = write_1(inode, arg_buffer, offset, size, rpc_client);
|
||||||
|
if(result == NULL) {
|
||||||
|
fuse_reply_err(request, EIO);
|
||||||
|
} else if(*result == FS454_ENONE) {
|
||||||
|
fuse_reply_write(request, size);
|
||||||
|
} else {
|
||||||
|
printf("write failed error %i\n", *result);
|
||||||
|
fuse_reply_write(request, ENOENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
const struct fuse_lowlevel_ops fs454_ops = {
|
||||||
|
.access = fs454_access,
|
||||||
|
.copy_file_range = fs454_copy_file_range,
|
||||||
|
.fallocate = fs454_fallocate,
|
||||||
|
.getattr = fs454_getattr,
|
||||||
|
.link = fs454_link,
|
||||||
|
.lookup = fs454_lookup,
|
||||||
|
.mknod = fs454_mknod,
|
||||||
|
.mkdir = fs454_mkdir,
|
||||||
|
.open = fs454_open,
|
||||||
|
.read = fs454_read,
|
||||||
|
.readdir = fs454_readdir,
|
||||||
|
.readlink = fs454_readlink,
|
||||||
|
.rename = fs454_rename,
|
||||||
|
.rmdir = fs454_rmdir,
|
||||||
|
.setattr = fs454_setattr,
|
||||||
|
.symlink = fs454_symlink,
|
||||||
|
.unlink = fs454_unlink,
|
||||||
|
.write = fs454_write
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *host = NULL;
|
||||||
|
if(argc > 2) {
|
||||||
|
host = argv[argc - 1];
|
||||||
|
argc--;
|
||||||
|
} else {
|
||||||
|
printf("Please specify a host. Usage: %s [fuse options] [host]\n", argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
||||||
|
struct fuse_cmdline_opts opts;
|
||||||
|
struct fuse_loop_config cfg;
|
||||||
|
struct fuse_session *session;
|
||||||
|
|
||||||
|
if(fuse_parse_cmdline(&args, &opts) != 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(opts.show_help) {
|
||||||
|
fuse_cmdline_help();
|
||||||
|
fuse_lowlevel_help();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(opts.mountpoint == NULL) {
|
||||||
|
fuse_opt_free_args(&args);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Connecting to '%s'...\n", host);
|
||||||
|
|
||||||
|
rpc_client = clnt_create(host, FS454, MESSAGEVERS, "tcp");
|
||||||
|
if(rpc_client == NULL) {
|
||||||
|
clnt_pcreateerror(host);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Connected.\n");
|
||||||
|
|
||||||
|
session = fuse_session_new(&args, &fs454_ops, sizeof(fs454_ops), NULL);
|
||||||
|
|
||||||
|
if(fuse_set_signal_handlers(session) != 0) {
|
||||||
|
fuse_session_destroy(session);
|
||||||
|
fuse_opt_free_args(&args);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fuse_session_mount(session, opts.mountpoint) != 0) {
|
||||||
|
fuse_remove_signal_handlers(session);
|
||||||
|
fuse_session_destroy(session);
|
||||||
|
fuse_opt_free_args(&args);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = 0;
|
||||||
|
fuse_daemonize(opts.foreground);
|
||||||
|
if(opts.singlethread) {
|
||||||
|
status = fuse_session_loop(session);
|
||||||
|
} else {
|
||||||
|
cfg.clone_fd = opts.clone_fd;
|
||||||
|
cfg.max_idle_threads = opts.max_idle_threads;
|
||||||
|
status = fuse_session_loop_mt(session, &cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
fuse_session_unmount(session);
|
||||||
|
fuse_remove_signal_handlers(session);
|
||||||
|
fuse_session_destroy(session);
|
||||||
|
fuse_opt_free_args(&args);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
428
src/fs454_server.c
Normal file
428
src/fs454_server.c
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
#include "inode_tree.h"
|
||||||
|
#include "file_tree.h"
|
||||||
|
#include "fsio.h"
|
||||||
|
#include "fs454.h"
|
||||||
|
#include <time.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#define SET_MODE (1 << 0)
|
||||||
|
#define SET_OWNER (1 << 1)
|
||||||
|
#define SET_SIZE (1 << 3)
|
||||||
|
#define SET_ACCESS (1 << 4)
|
||||||
|
#define SET_MODIFY (1 << 5)
|
||||||
|
#define SET_ACCESS_NOW (1 << 7)
|
||||||
|
#define SET_MODIFY_NOW (1 << 8)
|
||||||
|
#define SET_CHANGE (1 << 10)
|
||||||
|
|
||||||
|
extern inode_tree *inodes;
|
||||||
|
extern directory_list *directories;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Manually check supported bits and copy them to a new mode
|
||||||
|
* value. This ensures only valid file modes can be given to the filesystem.
|
||||||
|
* If the input mode indicates the use of unsupported features, this function
|
||||||
|
* shall return 0 indicating the input mode is illegal.
|
||||||
|
*
|
||||||
|
* @param mode file mode to sanitize
|
||||||
|
* @return long a sanitized file mode
|
||||||
|
*/
|
||||||
|
long sanitize_mode(long mode) {
|
||||||
|
long newmode = 0;
|
||||||
|
|
||||||
|
/* Test file type. Only files, directories, and links allowed. */
|
||||||
|
if(S_ISBLK(mode)) {
|
||||||
|
return 0;
|
||||||
|
} else if(S_ISCHR(mode)) {
|
||||||
|
return 0;
|
||||||
|
} else if(S_ISDIR(mode)) {
|
||||||
|
newmode |= __S_IFDIR;
|
||||||
|
} else if(S_ISFIFO(mode)) {
|
||||||
|
return 0;
|
||||||
|
} else if(S_ISREG(mode)) {
|
||||||
|
newmode |= __S_IFREG;
|
||||||
|
} else if(S_ISLNK(mode)) {
|
||||||
|
newmode |= __S_IFLNK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build a bitmask for supported permissions. Execute permissions are disabled. */
|
||||||
|
long permission_mask = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||||
|
newmode |= mode & permission_mask;
|
||||||
|
|
||||||
|
return newmode;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_code *allocate_1_svc(long inode, long length, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static error_code result;
|
||||||
|
file_descriptor *desc = inode_tree_find(inodes, inode);
|
||||||
|
if(desc == NULL) {
|
||||||
|
result = FS454_ENOINODE;
|
||||||
|
} else if(length < 0 || length > (1 << 30)) {
|
||||||
|
result = FS454_EINVAL;
|
||||||
|
} else if(desc->attributes.filesize >= length) {
|
||||||
|
result = FS454_ENONE;
|
||||||
|
} else {
|
||||||
|
if(do_allocate(desc->location, length) != 0) {
|
||||||
|
result = FS454_EIO;
|
||||||
|
} else {
|
||||||
|
desc->attributes.filesize = length;
|
||||||
|
desc->attributes.last_change = time(0);
|
||||||
|
result = FS454_ENONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *getattr_1_svc(long inode, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static attribute_res result;
|
||||||
|
file_descriptor *desc = inode_tree_find(inodes, inode);
|
||||||
|
if(desc == NULL) {
|
||||||
|
result.err = FS454_ENOINODE;
|
||||||
|
} else {
|
||||||
|
result.attribute_res_u.attributes = desc->attributes;
|
||||||
|
result.err = FS454_ENONE;
|
||||||
|
}
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *link_1_svc(long inode, char *newname, long newparent, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static attribute_res result;
|
||||||
|
if(inode <= 0 || newparent <= 0 || newname == NULL) {
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
}
|
||||||
|
file_descriptor *descriptor = NULL;
|
||||||
|
file_descriptor *parent_descriptor = NULL;
|
||||||
|
if((descriptor = inode_tree_find(inodes, inode)) == NULL) {
|
||||||
|
result.err = FS454_ENOINODE;
|
||||||
|
} else if((descriptor = inode_tree_find(inodes, newparent)) == NULL) {
|
||||||
|
result.err = FS454_ENOINODE;
|
||||||
|
} else if(!S_ISDIR(parent_descriptor->attributes.mode)) {
|
||||||
|
result.err = FS454_ENOTDIR;
|
||||||
|
} else if(!S_ISREG(descriptor->attributes.mode)) {
|
||||||
|
result.err = FS454_EBADF;
|
||||||
|
} else if(file_tree_insert(directories, newparent, newname, descriptor->attributes.id) != 0) {
|
||||||
|
result.err = FS454_EIO;
|
||||||
|
} else {
|
||||||
|
result.err = FS454_ENONE;
|
||||||
|
descriptor->attributes.link_count++;
|
||||||
|
result.attribute_res_u.attributes = descriptor->attributes;
|
||||||
|
}
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *lookup_1_svc(char *name, long parent, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static attribute_res result;
|
||||||
|
if(name == NULL || parent <= 0) {
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
directory_entry *entry = file_tree_lookup(directories, parent, name);
|
||||||
|
if(entry == NULL) {
|
||||||
|
result.err = FS454_ENOINODE;
|
||||||
|
} else {
|
||||||
|
file_descriptor *descriptor = inode_tree_find(inodes, entry->inode);
|
||||||
|
if(descriptor == NULL) {
|
||||||
|
/* There's a serious problem; this lookup should not fail. */
|
||||||
|
fprintf(stderr, "WARNING: Broken link %ld->%ld stored in directory table.\n", parent, entry->inode);
|
||||||
|
result.err = FS454_EIO;
|
||||||
|
} else {
|
||||||
|
result.attribute_res_u.attributes = descriptor->attributes;
|
||||||
|
result.err = FS454_ENONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *mkdir_1_svc(char *name, long parent, long mode, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static attribute_res result;
|
||||||
|
if(name == NULL) {
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
} else if((mode = sanitize_mode(mode)) == 0 || S_ISREG(mode) || S_ISLNK(mode)) {
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
} else if(parent <= 0) {
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
} else {
|
||||||
|
file_descriptor *parent_descriptor = inode_tree_find(inodes, parent);
|
||||||
|
file_descriptor *descriptor = NULL;
|
||||||
|
if(parent_descriptor == NULL) {
|
||||||
|
result.err = FS454_ENOINODE;
|
||||||
|
} else if(!S_ISDIR(parent_descriptor->attributes.mode)) {
|
||||||
|
result.err = FS454_ENOTDIR;
|
||||||
|
} else if((descriptor = inode_tree_create(inodes)) == NULL) {
|
||||||
|
result.err = FS454_EIO;
|
||||||
|
} else if(file_tree_insert_dir(directories, parent, name, descriptor->attributes.id) != 0) {
|
||||||
|
/* There's a serious problem; if a directory is stored in the inode table, inserting a new node should not fail. */
|
||||||
|
fprintf(stderr, "WARNING: Failed to insert a new node %s under %ld into the file tree.\n", name, parent);
|
||||||
|
if(inode_tree_remove(inodes, descriptor->attributes.id) != 0) {
|
||||||
|
/* There's a really serious problem. This inode is known to exist; why can't we remove it? */
|
||||||
|
fprintf(stderr, "WARNING: Failed to clean up orphaned inode %ld\n", descriptor->attributes.id);
|
||||||
|
/* No obvious way to recover... */
|
||||||
|
}
|
||||||
|
result.err = FS454_EIO;
|
||||||
|
} else {
|
||||||
|
descriptor->location = 0;
|
||||||
|
descriptor->attributes.mode = mode | __S_IFDIR;
|
||||||
|
result.err = FS454_ENONE;
|
||||||
|
result.attribute_res_u.attributes = descriptor->attributes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *mknod_1_svc(char *name, long parent, long mode, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static attribute_res result;
|
||||||
|
if(name == NULL) {
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
} else if((mode = sanitize_mode(mode)) == 0 || S_ISDIR(mode) || S_ISLNK(mode)) {
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
} else if(parent <= 0) {
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
} else {
|
||||||
|
file_descriptor *parent_descriptor = inode_tree_find(inodes, parent);
|
||||||
|
file_descriptor *descriptor = NULL;
|
||||||
|
if(parent_descriptor == NULL) {
|
||||||
|
result.err = FS454_ENOINODE;
|
||||||
|
} else if(!S_ISDIR(parent_descriptor->attributes.mode)) {
|
||||||
|
result.err = FS454_ENOTDIR;
|
||||||
|
} else if((descriptor = inode_tree_create(inodes)) == NULL) {
|
||||||
|
result.err = FS454_EIO;
|
||||||
|
} else if(file_tree_insert(directories, parent, name, descriptor->attributes.id) != 0) {
|
||||||
|
/* There's a serious problem; if a directory is stored in the inode table, inserting a new node should not fail. */
|
||||||
|
fprintf(stderr, "WARNING: Failed to insert a new node %s under %ld into the file tree.\n", name, parent);
|
||||||
|
if(inode_tree_remove(inodes, descriptor->attributes.id) != 0) {
|
||||||
|
/* There's a really serious problem. This inode is known to exist; why can't we remove it? */
|
||||||
|
fprintf(stderr, "WARNING: Failed to clean up orphaned inode %ld\n", descriptor->attributes.id);
|
||||||
|
/* No obvious way to recover... */
|
||||||
|
}
|
||||||
|
result.err = FS454_EIO;
|
||||||
|
} else {
|
||||||
|
descriptor->location = do_mknod();
|
||||||
|
descriptor->attributes.mode = mode | __S_IFREG;
|
||||||
|
result.err = FS454_ENONE;
|
||||||
|
result.attribute_res_u.attributes = descriptor->attributes;
|
||||||
|
fprintf(stderr, "INFO: Made new inode %ld at location %ld.\n", descriptor->attributes.id, descriptor->location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer_res *read_1_svc(long inode, long offset, long len, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static buffer_res result;
|
||||||
|
file_descriptor *desc = inode_tree_find(inodes, inode);
|
||||||
|
if(desc == NULL) {
|
||||||
|
result.err = FS454_ENOINODE;
|
||||||
|
} else if(desc->location == 0) {
|
||||||
|
result.err = FS454_EBADF;
|
||||||
|
} else if(len < 0 || offset < 0 || offset >= desc->attributes.filesize) {
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
} else {
|
||||||
|
if(offset + len > desc->attributes.filesize) {
|
||||||
|
len = desc->attributes.filesize - offset;
|
||||||
|
}
|
||||||
|
result.buffer_res_u.buffer.byte_buffer_val = malloc(len);
|
||||||
|
result.buffer_res_u.buffer.byte_buffer_len = len;
|
||||||
|
if(do_read(desc->location, result.buffer_res_u.buffer.byte_buffer_val, offset, len) != 0) {
|
||||||
|
result.err = FS454_EIO;
|
||||||
|
free(result.buffer_res_u.buffer.byte_buffer_val);
|
||||||
|
result.buffer_res_u.buffer.byte_buffer_val = NULL;
|
||||||
|
result.buffer_res_u.buffer.byte_buffer_len = 0;
|
||||||
|
} else {
|
||||||
|
desc->attributes.last_access = time(0);
|
||||||
|
result.err = FS454_ENONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
readdir_res *readdir_1_svc(long inode, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static readdir_res result;
|
||||||
|
directory_list_node *entry_list = file_tree_list_dir(directories, inode);
|
||||||
|
if(entry_list == NULL) {
|
||||||
|
result.err = FS454_ENOINODE;
|
||||||
|
} else {
|
||||||
|
xdr_free(xdr_readdir_res, &result);
|
||||||
|
file_descriptor *dir_desc = inode_tree_find(inodes, entry_list->self.inode);
|
||||||
|
file_descriptor *parent_desc = NULL;
|
||||||
|
if(entry_list->self.parent > 0) {
|
||||||
|
parent_desc = inode_tree_find(inodes, entry_list->self.parent);
|
||||||
|
} else {
|
||||||
|
parent_desc = dir_desc;
|
||||||
|
}
|
||||||
|
result.readdir_res_u.entries = malloc(sizeof(dir_entry));
|
||||||
|
dir_entry *current_entry = result.readdir_res_u.entries;
|
||||||
|
current_entry->name.name_val = malloc(2);
|
||||||
|
strcpy(current_entry->name.name_val, ".");
|
||||||
|
current_entry->name.name_len = strlen(".") + 1;
|
||||||
|
current_entry->attributes = dir_desc->attributes;
|
||||||
|
current_entry->next = malloc(sizeof(dir_entry));
|
||||||
|
current_entry = current_entry->next;
|
||||||
|
current_entry->name.name_val = malloc(3);
|
||||||
|
strcpy(current_entry->name.name_val, "..");
|
||||||
|
current_entry->name.name_len = strlen("..") + 1;
|
||||||
|
current_entry->attributes = parent_desc->attributes;
|
||||||
|
dirent_list_node *node = entry_list->directory.first;
|
||||||
|
while(node != NULL) {
|
||||||
|
current_entry->next = malloc(sizeof(dir_entry));
|
||||||
|
current_entry = current_entry->next;
|
||||||
|
u_int namelen = strlen(node->entry.name) + 1;
|
||||||
|
current_entry->name.name_val = malloc(namelen);
|
||||||
|
strcpy(current_entry->name.name_val, node->entry.name);
|
||||||
|
current_entry->name.name_len = namelen;
|
||||||
|
current_entry->attributes = inode_tree_find(inodes, node->entry.inode)->attributes;
|
||||||
|
current_entry->next = NULL;
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
result.err = FS454_ENONE;
|
||||||
|
}
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
string_res *readlink_1_svc(long arg1, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static string_res result;
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *setattr_1_svc(long inode, long to_set, struct file_attributes attributes, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static attribute_res result;
|
||||||
|
file_descriptor *descriptor = NULL;
|
||||||
|
if(to_set & SET_SIZE) {
|
||||||
|
fprintf(stderr, "INFO: Received request to change file size\n");
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
} else if((attributes.mode = sanitize_mode(attributes.mode)) == 0 && (to_set & SET_MODE)) {
|
||||||
|
fprintf(stderr, "INFO: Received invalid file mode\n");
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
} else if(/*(S_ISREG(attributes.mode) || S_ISDIR(attributes.mode) || S_ISLNK(attributes.mode)) && (to_set & SET_MODE)*/ 0) {
|
||||||
|
fprintf(stderr, "INFO: Received request to change file type\n");
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
} else if((descriptor = inode_tree_find(inodes, inode)) == NULL) {
|
||||||
|
result.err = FS454_ENOINODE;
|
||||||
|
} else {
|
||||||
|
if(to_set & SET_MODE)
|
||||||
|
descriptor->attributes.mode = attributes.mode;
|
||||||
|
if(to_set & SET_OWNER)
|
||||||
|
descriptor->attributes.owner = attributes.owner;
|
||||||
|
if(to_set & SET_CHANGE)
|
||||||
|
descriptor->attributes.last_change = attributes.last_change;
|
||||||
|
if(to_set & SET_ACCESS)
|
||||||
|
descriptor->attributes.last_access = attributes.last_access;
|
||||||
|
if(to_set & SET_MODIFY)
|
||||||
|
descriptor->attributes.last_modify = attributes.last_modify;
|
||||||
|
if(to_set & SET_ACCESS_NOW)
|
||||||
|
descriptor->attributes.last_access = time(0);
|
||||||
|
if(to_set & SET_MODIFY_NOW)
|
||||||
|
descriptor->attributes.last_modify = time(0);
|
||||||
|
result.attribute_res_u.attributes = descriptor->attributes;
|
||||||
|
result.err = FS454_ENONE;
|
||||||
|
}
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute_res *symlink_1_svc(char *arg1, long arg2, char *arg3, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static attribute_res result;
|
||||||
|
result.err = FS454_EINVAL;
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_code *unlink_1_svc(long parent, char *name, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static error_code result;
|
||||||
|
directory_entry *entry = NULL;
|
||||||
|
file_descriptor *descriptor = NULL;
|
||||||
|
if(parent <= 0 || name == NULL) {
|
||||||
|
result = FS454_EINVAL;
|
||||||
|
} else if((entry = file_tree_lookup(directories, parent, name)) == NULL) {
|
||||||
|
result = FS454_ENOINODE;
|
||||||
|
} else if((descriptor = inode_tree_find(inodes, entry->inode)) == NULL) {
|
||||||
|
/* There's a serious problem; this lookup should not fail. */
|
||||||
|
fprintf(stderr, "WARNING: Broken link %ld->%ld stored in directory table.\n", parent, entry->inode);
|
||||||
|
result = FS454_EIO;
|
||||||
|
} else if(S_ISDIR(descriptor->attributes.mode)) {
|
||||||
|
/* We should only delete empty directories */
|
||||||
|
directory_list_node *entry_list = file_tree_list_dir(directories, descriptor->attributes.id);
|
||||||
|
if(entry_list == NULL) {
|
||||||
|
/* This is a problem. There exists a directory with no entry list stored in the filesystem. */
|
||||||
|
fprintf(stderr, "WARNING: Count not find entry list for directory %ld.\n", descriptor->attributes.id);
|
||||||
|
result = FS454_EIO;
|
||||||
|
} else if(entry_list->directory.count > 0) {
|
||||||
|
result = FS454_ENOTEMPTY;
|
||||||
|
} else if(file_tree_remove(directories, parent, name) != 0) {
|
||||||
|
/* There's a serious problem; this node was found in a lookup, and has no children; why can't we remove it? */
|
||||||
|
fprintf(stderr, "WARNING: Failed to remove empty directory node %ld->%s.\n", parent, name);
|
||||||
|
result = FS454_EIO;
|
||||||
|
} else if(inode_tree_remove(inodes, descriptor->attributes.id) != 0) {
|
||||||
|
/* This is a more serious problem; we've removed the link, but can't remove the inode. */
|
||||||
|
fprintf(stderr, "WARNING: Failed to remove inode %ld from filesystem.\n", descriptor->attributes.id);
|
||||||
|
result = FS454_ENONE;
|
||||||
|
} else {
|
||||||
|
result = FS454_ENONE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(file_tree_remove(directories, parent, name) != 0) {
|
||||||
|
/* There's a serious problem; this node was found in a lookup; why can't we remove it? */
|
||||||
|
fprintf(stderr, "WARNING: Failed to remove file node %ld->%s.\n", parent, name);
|
||||||
|
result = FS454_EIO;
|
||||||
|
} else if((descriptor->attributes.link_count--) == 0) {
|
||||||
|
/* Neither of the two following functions should ever fail. */
|
||||||
|
if(do_rmnod(descriptor->location) != 0) {
|
||||||
|
fprintf(stderr, "WARNING: Failed to delete location %ld from disk.\n", descriptor->location);
|
||||||
|
}
|
||||||
|
if(inode_tree_remove(inodes, descriptor->attributes.id) != 0) {
|
||||||
|
fprintf(stderr, "WARNING: Failed to remove inode %ld from filesystem.\n", descriptor->attributes.id);
|
||||||
|
}
|
||||||
|
result = FS454_ENONE;
|
||||||
|
} else {
|
||||||
|
result = FS454_ENONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_code *write_1_svc(long inode, byte_buffer buffer, long offset, long length, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static error_code result;
|
||||||
|
file_descriptor *desc = inode_tree_find(inodes, inode);
|
||||||
|
if(desc == NULL) {
|
||||||
|
result = FS454_ENOINODE;
|
||||||
|
} else if(desc->location == 0) {
|
||||||
|
result = FS454_EBADF;
|
||||||
|
} else if(offset < 0 || length < 0 || length > (1 << 30) || offset > (1 << 30)) {
|
||||||
|
result = FS454_EINVAL;
|
||||||
|
} else if(length == 0) {
|
||||||
|
result = FS454_ENONE;
|
||||||
|
} else if(length > buffer.byte_buffer_len) {
|
||||||
|
result = FS454_EINVAL;
|
||||||
|
} else if(!(desc->attributes.mode & S_IWUSR)) {
|
||||||
|
result = FS454_EACCESS;
|
||||||
|
} else if(do_write(desc->location, buffer.byte_buffer_val, offset, length) != 0) {
|
||||||
|
result = FS454_EIO;
|
||||||
|
} else {
|
||||||
|
if(offset + length > desc->attributes.filesize) {
|
||||||
|
desc->attributes.filesize = offset + length;
|
||||||
|
desc->attributes.last_access = time(0);
|
||||||
|
desc->attributes.last_modify = time(0);
|
||||||
|
desc->attributes.last_change = time(0);
|
||||||
|
}
|
||||||
|
result = FS454_ENONE;
|
||||||
|
}
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_code *copy_1_svc(long arg1, long arg2, long arg3, long arg4, long arg5, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
static error_code result;
|
||||||
|
result = FS454_EINVAL;
|
||||||
|
return &result;
|
||||||
|
}
|
||||||
279
src/fs454_svc.c
Normal file
279
src/fs454_svc.c
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
/*
|
||||||
|
* Please do not edit this file.
|
||||||
|
* It was generated using rpcgen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "fs454.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <rpc/pmap_clnt.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <memory.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include "inode_tree.h"
|
||||||
|
#include "file_tree.h"
|
||||||
|
#include "fsio.h"
|
||||||
|
|
||||||
|
#ifndef SIG_PF
|
||||||
|
#define SIG_PF void(*)(int)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inode_tree *inodes;
|
||||||
|
directory_list *directories;
|
||||||
|
|
||||||
|
static error_code *
|
||||||
|
_allocate_1 (allocate_1_argument *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (allocate_1_svc(argp->arg1, argp->arg2, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static attribute_res *
|
||||||
|
_getattr_1 (long *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (getattr_1_svc(*argp, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static attribute_res *
|
||||||
|
_link_1 (link_1_argument *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (link_1_svc(argp->arg1, argp->arg2, argp->arg3, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static attribute_res *
|
||||||
|
_lookup_1 (lookup_1_argument *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (lookup_1_svc(argp->arg1, argp->arg2, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static attribute_res *
|
||||||
|
_mkdir_1 (mkdir_1_argument *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (mkdir_1_svc(argp->arg1, argp->arg2, argp->arg3, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static attribute_res *
|
||||||
|
_mknod_1 (mknod_1_argument *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (mknod_1_svc(argp->arg1, argp->arg2, argp->arg3, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static buffer_res *
|
||||||
|
_read_1 (read_1_argument *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (read_1_svc(argp->arg1, argp->arg2, argp->arg3, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static readdir_res *
|
||||||
|
_readdir_1 (long *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (readdir_1_svc(*argp, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static string_res *
|
||||||
|
_readlink_1 (long *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (readlink_1_svc(*argp, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static attribute_res *
|
||||||
|
_setattr_1 (setattr_1_argument *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (setattr_1_svc(argp->arg1, argp->arg2, argp->arg3, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static attribute_res *
|
||||||
|
_symlink_1 (symlink_1_argument *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (symlink_1_svc(argp->arg1, argp->arg2, argp->arg3, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static error_code *
|
||||||
|
_unlink_1 (unlink_1_argument *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (unlink_1_svc(argp->arg1, argp->arg2, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static error_code *
|
||||||
|
_write_1 (write_1_argument *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (write_1_svc(argp->arg1, argp->arg2, argp->arg3, argp->arg4, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static error_code *
|
||||||
|
_copy_1 (copy_1_argument *argp, struct svc_req *rqstp)
|
||||||
|
{
|
||||||
|
return (copy_1_svc(argp->arg1, argp->arg2, argp->arg3, argp->arg4, argp->arg5, rqstp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
fs454_1(struct svc_req *rqstp, register SVCXPRT *transp)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
allocate_1_argument allocate_1_arg;
|
||||||
|
long getattr_1_arg;
|
||||||
|
link_1_argument link_1_arg;
|
||||||
|
lookup_1_argument lookup_1_arg;
|
||||||
|
mkdir_1_argument mkdir_1_arg;
|
||||||
|
mknod_1_argument mknod_1_arg;
|
||||||
|
read_1_argument read_1_arg;
|
||||||
|
long readdir_1_arg;
|
||||||
|
long readlink_1_arg;
|
||||||
|
setattr_1_argument setattr_1_arg;
|
||||||
|
symlink_1_argument symlink_1_arg;
|
||||||
|
unlink_1_argument unlink_1_arg;
|
||||||
|
write_1_argument write_1_arg;
|
||||||
|
copy_1_argument copy_1_arg;
|
||||||
|
} argument;
|
||||||
|
char *result;
|
||||||
|
xdrproc_t _xdr_argument, _xdr_result;
|
||||||
|
char *(*local)(char *, struct svc_req *);
|
||||||
|
|
||||||
|
switch (rqstp->rq_proc) {
|
||||||
|
case NULLPROC:
|
||||||
|
(void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case ALLOCATE:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_allocate_1_argument;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_error_code;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _allocate_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GETATTR:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_long;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_attribute_res;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _getattr_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LINK:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_link_1_argument;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_attribute_res;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _link_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOOKUP:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_lookup_1_argument;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_attribute_res;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _lookup_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MKDIR:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_mkdir_1_argument;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_attribute_res;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _mkdir_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MKNOD:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_mknod_1_argument;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_attribute_res;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _mknod_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case READ:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_read_1_argument;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_buffer_res;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _read_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case READDIR:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_long;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_readdir_res;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _readdir_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case READLINK:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_long;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_string_res;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _readlink_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SETATTR:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_setattr_1_argument;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_attribute_res;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _setattr_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYMLINK:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_symlink_1_argument;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_attribute_res;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _symlink_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UNLINK:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_unlink_1_argument;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_error_code;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _unlink_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WRITE:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_write_1_argument;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_error_code;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _write_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COPY:
|
||||||
|
_xdr_argument = (xdrproc_t) xdr_copy_1_argument;
|
||||||
|
_xdr_result = (xdrproc_t) xdr_error_code;
|
||||||
|
local = (char *(*)(char *, struct svc_req *)) _copy_1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
svcerr_noproc (transp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memset ((char *)&argument, 0, sizeof (argument));
|
||||||
|
if (!svc_getargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
|
||||||
|
svcerr_decode (transp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
result = (*local)((char *)&argument, rqstp);
|
||||||
|
if (result != NULL && !svc_sendreply(transp, (xdrproc_t) _xdr_result, result)) {
|
||||||
|
svcerr_systemerr (transp);
|
||||||
|
}
|
||||||
|
if (!svc_freeargs (transp, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) {
|
||||||
|
fprintf (stderr, "%s", "unable to free arguments");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
register SVCXPRT *transp;
|
||||||
|
|
||||||
|
inodes = inode_tree_new();
|
||||||
|
directories = file_tree_new();
|
||||||
|
|
||||||
|
inode_tree_insert_root(inodes);
|
||||||
|
file_tree_insert_root(directories);
|
||||||
|
fsio_init();
|
||||||
|
|
||||||
|
pmap_unset (FS454, MESSAGEVERS);
|
||||||
|
|
||||||
|
transp = svcudp_create(RPC_ANYSOCK);
|
||||||
|
if (transp == NULL) {
|
||||||
|
fprintf (stderr, "%s", "cannot create udp service.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (!svc_register(transp, FS454, MESSAGEVERS, fs454_1, IPPROTO_UDP)) {
|
||||||
|
fprintf (stderr, "%s", "unable to register (FS454, MESSAGEVERS, udp).");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
transp = svctcp_create(RPC_ANYSOCK, 0, 0);
|
||||||
|
if (transp == NULL) {
|
||||||
|
fprintf (stderr, "%s", "cannot create tcp service.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (!svc_register(transp, FS454, MESSAGEVERS, fs454_1, IPPROTO_TCP)) {
|
||||||
|
fprintf (stderr, "%s", "unable to register (FS454, MESSAGEVERS, tcp).");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
svc_run ();
|
||||||
|
fprintf (stderr, "%s", "svc_run returned");
|
||||||
|
exit (1);
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
343
src/fs454_xdr.c
Normal file
343
src/fs454_xdr.c
Normal file
@@ -0,0 +1,343 @@
|
|||||||
|
/*
|
||||||
|
* Please do not edit this file.
|
||||||
|
* It was generated using rpcgen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "fs454.h"
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_file_attributes (XDR *xdrs, file_attributes *objp)
|
||||||
|
{
|
||||||
|
register int32_t *buf;
|
||||||
|
|
||||||
|
|
||||||
|
if (xdrs->x_op == XDR_ENCODE) {
|
||||||
|
buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT);
|
||||||
|
if (buf == NULL) {
|
||||||
|
if (!xdr_long (xdrs, &objp->id))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->link_count))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->filesize))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->owner))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->mode))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->last_access))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->last_modify))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->last_change))
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
IXDR_PUT_LONG(buf, objp->id);
|
||||||
|
IXDR_PUT_LONG(buf, objp->link_count);
|
||||||
|
IXDR_PUT_LONG(buf, objp->filesize);
|
||||||
|
IXDR_PUT_LONG(buf, objp->owner);
|
||||||
|
IXDR_PUT_LONG(buf, objp->mode);
|
||||||
|
IXDR_PUT_LONG(buf, objp->last_access);
|
||||||
|
IXDR_PUT_LONG(buf, objp->last_modify);
|
||||||
|
IXDR_PUT_LONG(buf, objp->last_change);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
} else if (xdrs->x_op == XDR_DECODE) {
|
||||||
|
buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT);
|
||||||
|
if (buf == NULL) {
|
||||||
|
if (!xdr_long (xdrs, &objp->id))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->link_count))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->filesize))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->owner))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->mode))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->last_access))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->last_modify))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->last_change))
|
||||||
|
return FALSE;
|
||||||
|
} else {
|
||||||
|
objp->id = IXDR_GET_LONG(buf);
|
||||||
|
objp->link_count = IXDR_GET_LONG(buf);
|
||||||
|
objp->filesize = IXDR_GET_LONG(buf);
|
||||||
|
objp->owner = IXDR_GET_LONG(buf);
|
||||||
|
objp->mode = IXDR_GET_LONG(buf);
|
||||||
|
objp->last_access = IXDR_GET_LONG(buf);
|
||||||
|
objp->last_modify = IXDR_GET_LONG(buf);
|
||||||
|
objp->last_change = IXDR_GET_LONG(buf);
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!xdr_long (xdrs, &objp->id))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->link_count))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->filesize))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->owner))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->mode))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->last_access))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->last_modify))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->last_change))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_dir_entry (XDR *xdrs, dir_entry *objp)
|
||||||
|
{
|
||||||
|
register int32_t *buf;
|
||||||
|
|
||||||
|
if (!xdr_array (xdrs, (char **)&objp->name.name_val, (u_int *) &objp->name.name_len, ~0,
|
||||||
|
sizeof (char), (xdrproc_t) xdr_char))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_file_attributes (xdrs, &objp->attributes))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_pointer (xdrs, (char **)&objp->next, sizeof (dir_entry), (xdrproc_t) xdr_dir_entry))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_error_code (XDR *xdrs, error_code *objp)
|
||||||
|
{
|
||||||
|
register int32_t *buf;
|
||||||
|
|
||||||
|
if (!xdr_enum (xdrs, (enum_t *) objp))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_entry_list (XDR *xdrs, entry_list *objp)
|
||||||
|
{
|
||||||
|
register int32_t *buf;
|
||||||
|
|
||||||
|
if (!xdr_pointer (xdrs, (char **)objp, sizeof (dir_entry), (xdrproc_t) xdr_dir_entry))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_byte_buffer (XDR *xdrs, byte_buffer *objp)
|
||||||
|
{
|
||||||
|
register int32_t *buf;
|
||||||
|
|
||||||
|
if (!xdr_array (xdrs, (char **)&objp->byte_buffer_val, (u_int *) &objp->byte_buffer_len, ~0,
|
||||||
|
sizeof (u_char), (xdrproc_t) xdr_u_char))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_attribute_res (XDR *xdrs, attribute_res *objp)
|
||||||
|
{
|
||||||
|
register int32_t *buf;
|
||||||
|
|
||||||
|
if (!xdr_error_code (xdrs, &objp->err))
|
||||||
|
return FALSE;
|
||||||
|
switch (objp->err) {
|
||||||
|
case FS454_ENONE:
|
||||||
|
if (!xdr_file_attributes (xdrs, &objp->attribute_res_u.attributes))
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_string_res (XDR *xdrs, string_res *objp)
|
||||||
|
{
|
||||||
|
register int32_t *buf;
|
||||||
|
|
||||||
|
if (!xdr_error_code (xdrs, &objp->err))
|
||||||
|
return FALSE;
|
||||||
|
switch (objp->err) {
|
||||||
|
case FS454_ENONE:
|
||||||
|
if (!xdr_string (xdrs, &objp->string_res_u.str, ~0))
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_readdir_res (XDR *xdrs, readdir_res *objp)
|
||||||
|
{
|
||||||
|
register int32_t *buf;
|
||||||
|
|
||||||
|
if (!xdr_error_code (xdrs, &objp->err))
|
||||||
|
return FALSE;
|
||||||
|
switch (objp->err) {
|
||||||
|
case FS454_ENONE:
|
||||||
|
if (!xdr_entry_list (xdrs, &objp->readdir_res_u.entries))
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_buffer_res (XDR *xdrs, buffer_res *objp)
|
||||||
|
{
|
||||||
|
register int32_t *buf;
|
||||||
|
|
||||||
|
if (!xdr_error_code (xdrs, &objp->err))
|
||||||
|
return FALSE;
|
||||||
|
switch (objp->err) {
|
||||||
|
case FS454_ENONE:
|
||||||
|
if (!xdr_byte_buffer (xdrs, &objp->buffer_res_u.buffer))
|
||||||
|
return FALSE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_allocate_1_argument (XDR *xdrs, allocate_1_argument *objp)
|
||||||
|
{
|
||||||
|
if (!xdr_long (xdrs, &objp->arg1))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg2))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_link_1_argument (XDR *xdrs, link_1_argument *objp)
|
||||||
|
{
|
||||||
|
if (!xdr_long (xdrs, &objp->arg1))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_string (xdrs, &objp->arg2, ~0))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg3))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_lookup_1_argument (XDR *xdrs, lookup_1_argument *objp)
|
||||||
|
{
|
||||||
|
if (!xdr_string (xdrs, &objp->arg1, ~0))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg2))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_mkdir_1_argument (XDR *xdrs, mkdir_1_argument *objp)
|
||||||
|
{
|
||||||
|
if (!xdr_string (xdrs, &objp->arg1, ~0))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg2))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg3))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_mknod_1_argument (XDR *xdrs, mknod_1_argument *objp)
|
||||||
|
{
|
||||||
|
if (!xdr_string (xdrs, &objp->arg1, ~0))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg2))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg3))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_read_1_argument (XDR *xdrs, read_1_argument *objp)
|
||||||
|
{
|
||||||
|
if (!xdr_long (xdrs, &objp->arg1))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg2))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg3))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_setattr_1_argument (XDR *xdrs, setattr_1_argument *objp)
|
||||||
|
{
|
||||||
|
if (!xdr_long (xdrs, &objp->arg1))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg2))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_file_attributes (xdrs, &objp->arg3))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_symlink_1_argument (XDR *xdrs, symlink_1_argument *objp)
|
||||||
|
{
|
||||||
|
if (!xdr_string (xdrs, &objp->arg1, ~0))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg2))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_string (xdrs, &objp->arg3, ~0))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_unlink_1_argument (XDR *xdrs, unlink_1_argument *objp)
|
||||||
|
{
|
||||||
|
if (!xdr_long (xdrs, &objp->arg1))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_string (xdrs, &objp->arg2, ~0))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_write_1_argument (XDR *xdrs, write_1_argument *objp)
|
||||||
|
{
|
||||||
|
if (!xdr_long (xdrs, &objp->arg1))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_byte_buffer (xdrs, &objp->arg2))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg3))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg4))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool_t
|
||||||
|
xdr_copy_1_argument (XDR *xdrs, copy_1_argument *objp)
|
||||||
|
{
|
||||||
|
if (!xdr_long (xdrs, &objp->arg1))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg2))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg3))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg4))
|
||||||
|
return FALSE;
|
||||||
|
if (!xdr_long (xdrs, &objp->arg5))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
77
src/fsio.c
Normal file
77
src/fsio.c
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#include "fsio.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
long next_location;
|
||||||
|
|
||||||
|
void get_filename(char *dest, long location) {
|
||||||
|
mkdir("data/", 0700);
|
||||||
|
sprintf(dest, "data/%ld", location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fsio_init() {
|
||||||
|
next_location = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long do_mknod() {
|
||||||
|
long location = next_location;
|
||||||
|
next_location++;
|
||||||
|
char filename[80];
|
||||||
|
get_filename(filename, location);
|
||||||
|
FILE *fd = fopen(filename, "wx");
|
||||||
|
if(fd != NULL) {
|
||||||
|
fclose(fd);
|
||||||
|
return location;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int do_rmnod(long location) {
|
||||||
|
char filename[80];
|
||||||
|
get_filename(filename, location);
|
||||||
|
remove(filename);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int do_read(long location, unsigned char *buffer, long offset, long length) {
|
||||||
|
printf("do_read %i %i %i %p\n", location, length, offset, buffer);
|
||||||
|
char filename[80];
|
||||||
|
get_filename(filename, location);
|
||||||
|
int fd = open(filename, O_RDONLY);
|
||||||
|
if(fd > 0) {
|
||||||
|
lseek(fd, offset, SEEK_SET);
|
||||||
|
read(fd, buffer, length);
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int do_write(long location, const unsigned char *buffer, long offset, long length) {
|
||||||
|
printf("do_write %i %i %i %p\n", location, length, offset, buffer);
|
||||||
|
char filename[80];
|
||||||
|
get_filename(filename, location);
|
||||||
|
int fd = open(filename, O_WRONLY);
|
||||||
|
if(fd > 0) {
|
||||||
|
lseek(fd, offset, SEEK_SET);
|
||||||
|
write(fd, buffer, length);
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int do_allocate(long location, long size) {
|
||||||
|
char filename[80];
|
||||||
|
get_filename(filename, location);
|
||||||
|
int fd = open(filename, O_RDWR);
|
||||||
|
posix_fallocate(fd, 0, size);
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
16
src/fsio.h
Normal file
16
src/fsio.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef FS454_IO
|
||||||
|
#define FS454_IO
|
||||||
|
|
||||||
|
void fsio_init();
|
||||||
|
|
||||||
|
long do_mknod();
|
||||||
|
|
||||||
|
int do_rmnod(long location);
|
||||||
|
|
||||||
|
int do_read(long location, unsigned char *buffer, long offset, long length);
|
||||||
|
|
||||||
|
int do_write(long location, const unsigned char *buffer, long offset, long length);
|
||||||
|
|
||||||
|
int do_allocate(long location, long size);
|
||||||
|
|
||||||
|
#endif
|
||||||
120
src/inode_tree.c
Normal file
120
src/inode_tree.c
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include "inode_tree.h"
|
||||||
|
|
||||||
|
inode_tree *inode_tree_new() {
|
||||||
|
inode_tree *tree = malloc(sizeof(inode_tree));
|
||||||
|
if(tree != NULL) {
|
||||||
|
tree->first = NULL;
|
||||||
|
tree->last = NULL;
|
||||||
|
tree->count = 0;
|
||||||
|
tree->next_inode = 2;
|
||||||
|
}
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_descriptor *inode_tree_create(inode_tree *tree) {
|
||||||
|
inode_tree_node *newnode = malloc(sizeof(inode_tree_node));
|
||||||
|
newnode->descriptor = malloc(sizeof(file_descriptor));
|
||||||
|
newnode->next = NULL;
|
||||||
|
newnode->descriptor->location = 0;
|
||||||
|
newnode->descriptor->attributes.id = tree->next_inode;
|
||||||
|
newnode->descriptor->attributes.link_count = 1;
|
||||||
|
newnode->descriptor->attributes.owner = 0;
|
||||||
|
newnode->descriptor->attributes.mode = 0;
|
||||||
|
newnode->descriptor->attributes.last_access = time(0);
|
||||||
|
newnode->descriptor->attributes.last_modify = time(0);
|
||||||
|
newnode->descriptor->attributes.last_change = time(0);
|
||||||
|
if(tree->last != NULL) {
|
||||||
|
tree->last->next = newnode;
|
||||||
|
tree->last = newnode;
|
||||||
|
} else {
|
||||||
|
tree->first = newnode;
|
||||||
|
tree->last = newnode;
|
||||||
|
}
|
||||||
|
tree->count++;
|
||||||
|
tree->next_inode++;
|
||||||
|
return newnode->descriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_descriptor *inode_tree_find(inode_tree *tree, long inode) {
|
||||||
|
inode_tree_node *node = tree->first;
|
||||||
|
while(node != NULL) {
|
||||||
|
if(node->descriptor->attributes.id == inode) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(node != NULL) {
|
||||||
|
return node->descriptor;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int inode_tree_insert_root(inode_tree *tree) {
|
||||||
|
file_descriptor *root = malloc(sizeof(file_descriptor));
|
||||||
|
root->location = 0;
|
||||||
|
root->attributes.id = 1;
|
||||||
|
root->attributes.filesize = 0;
|
||||||
|
root->attributes.last_access = time(0);
|
||||||
|
root->attributes.last_change = time(0);
|
||||||
|
root->attributes.last_modify = time(0);
|
||||||
|
root->attributes.owner = 0;
|
||||||
|
root->attributes.mode = __S_IFDIR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
|
||||||
|
return inode_tree_insert(tree, root);
|
||||||
|
}
|
||||||
|
|
||||||
|
int inode_tree_insert(inode_tree *tree, file_descriptor *descriptor) {
|
||||||
|
inode_tree_node *node = malloc(sizeof(inode_tree_node));
|
||||||
|
if(node != NULL) {
|
||||||
|
node->next = NULL;
|
||||||
|
node->descriptor = descriptor;
|
||||||
|
if(tree->last != NULL) {
|
||||||
|
tree->last->next = node;
|
||||||
|
tree->last = node;
|
||||||
|
} else {
|
||||||
|
tree->first = node;
|
||||||
|
tree->last = node;
|
||||||
|
}
|
||||||
|
tree->count++;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int inode_tree_remove(inode_tree *tree, long inode) {
|
||||||
|
inode_tree_node *prev = NULL;
|
||||||
|
inode_tree_node *node = tree->first;
|
||||||
|
while(node != NULL) {
|
||||||
|
if(node->descriptor->attributes.id == inode) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
prev = node;
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(node != NULL) {
|
||||||
|
if(prev != NULL) {
|
||||||
|
prev->next = node->next;
|
||||||
|
if(prev->next == NULL) {
|
||||||
|
tree->last = prev;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(tree->first == tree->last) {
|
||||||
|
tree->first = tree->last = NULL;
|
||||||
|
} else {
|
||||||
|
tree->first = node->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(node->descriptor);
|
||||||
|
free(node);
|
||||||
|
tree->count--;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/inode_tree.h
Normal file
34
src/inode_tree.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#ifndef FS454_INODE_TREE
|
||||||
|
#define FS454_INODE_TREE
|
||||||
|
|
||||||
|
#include "fs454.h"
|
||||||
|
|
||||||
|
typedef struct file_descriptor_t {
|
||||||
|
struct file_attributes attributes;
|
||||||
|
long location;
|
||||||
|
} file_descriptor;
|
||||||
|
|
||||||
|
typedef struct inode_tree_node_t {
|
||||||
|
struct inode_tree_node_t *next;
|
||||||
|
file_descriptor *descriptor;
|
||||||
|
} inode_tree_node;
|
||||||
|
|
||||||
|
typedef struct inode_tree_t {
|
||||||
|
inode_tree_node *first, *last;
|
||||||
|
long count;
|
||||||
|
long next_inode;
|
||||||
|
} inode_tree;
|
||||||
|
|
||||||
|
inode_tree *inode_tree_new();
|
||||||
|
|
||||||
|
file_descriptor *inode_tree_create(inode_tree *tree);
|
||||||
|
|
||||||
|
file_descriptor *inode_tree_find(inode_tree *tree, long inode);
|
||||||
|
|
||||||
|
int inode_tree_insert_root(inode_tree *tree);
|
||||||
|
|
||||||
|
int inode_tree_insert(inode_tree *tree, file_descriptor *descriptor);
|
||||||
|
|
||||||
|
int inode_tree_remove(inode_tree *tree, long inode);
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user