Initial commit

This commit is contained in:
2024-02-21 19:24:26 -06:00
commit e5399fc6ce
14 changed files with 2611 additions and 0 deletions

15
Makefile Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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