0,0 → 1,344 |
/** @addtogroup FileLib |
* @{ |
*/ |
|
/** |
* @file file.c |
* @brief The user library for working with the file system |
*/ |
|
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <unistd.h> |
#include <async.h> |
#include <ipc/services.h> |
#include <ipc/ipc.h> |
#include <sys/mman.h> |
#include <io/file.h> |
#include <bool.h> |
#include <err.h> |
#include <align.h> |
#include "../../../fs/dir.h" |
#include "../../../share/message.h" |
#include "../../../share/shared_proto.h" |
|
#define CONNECT_SLEEP_INTERVAL 10000 |
#define CONNECT_SLEEP_TIMEOUT 100000 |
#define CON_FS_ATTEMPTS 1000 |
|
/** |
* |
*/ |
static int fs_phone; |
|
file_t * file_connect(); |
int file_disconnect(file_t * file); |
|
/** |
* Connect to the FS task and share memory with it for further data and |
* extended memory transfers |
*/ |
file_t * file_connect() { |
file_t * result; |
|
size_t size; |
void *share = NULL; |
int retval; |
|
printf("Connecting to the SERVICE_FS..."); |
if (!connect_to_fs(&fs_phone, CON_FS_ATTEMPTS)) { |
printf("Connection to SERVICE_FS was refused\n"); |
f_err = F_IPC_FAILURE; |
return NULL; |
} |
printf("OK\n"); |
return F_OK; |
|
printf("Creating address space area..."); |
size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE); |
share = mmap(share, size, AS_AREA_READ | AS_AREA_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0); |
if ((int)share < 0){ |
printf("As_area_create error: %d\n", (int)share); |
f_err = F_MMAP_FAILURE; |
return NULL; |
} |
printf("OK\n"); |
|
printf("Connecting the task to FS..."); |
retval = async_req_2(fs_phone, FS_NEW_CONSUMER, task_get_id(), 0, NULL, NULL); |
if (retval < 0) { |
printf("FS_NEW_CONSUMER error: %d\n", retval); |
f_err = F_COMM_FAILURE; |
return NULL; |
} |
printf("OK\n"); |
|
printf("Sending memory to FS_SERVICE..."); |
int flags = 0; |
flags = AS_AREA_READ | AS_AREA_WRITE; |
retval = async_req_3(fs_phone, IPC_M_AS_AREA_SEND, (uintptr_t)share, size, flags, NULL, NULL, NULL); |
if (retval < 0) { |
printf("%d\n", retval); |
f_err = F_COMM_FAILURE; |
return NULL; |
} |
printf("OK\n"); |
|
/* Allocating structure for extended message. */ |
message_params_t *params; |
params = malloc(sizeof(message_params_t)); |
memset((void*)params, 0, sizeof(message_params_t)); |
|
result = malloc(sizeof(file_t)); |
result->share = share; |
result->size = size; |
result->params = params; |
|
f_err = F_OK; |
return result; |
} |
|
/** |
* Disconnect from the FS task, unsharing memory and freeing the file data structure |
*/ |
int file_disconnect(file_t * file) { |
int retval; |
|
printf("Request for dropping the connection to the FS..."); |
retval = send_request(fs_phone, FS_DROP_CONSUMER, file->params, file->share); |
if (retval < 0) { |
printf("%d\n", retval); |
return -1; |
} |
printf("OK\n"); |
|
/* Unmapping share area. */ |
printf("Unmapping share area..."); |
retval = munmap(file->share, file->size); |
if (retval < 0) { |
printf("%d\n", retval); |
return -1; |
} |
printf("OK\n"); |
|
printf("Creating address space area..."); |
file->size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE); |
file->share = mmap(file->share, file->size, AS_AREA_READ | AS_AREA_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0); |
if ((int)(file->share) < 0){ |
printf("As_area_create error: %d\n", (int)(file->share)); |
return -1; |
} |
printf("OK\n"); |
|
free(file); |
f_err = F_OK; |
return F_OK; |
} |
|
/** |
* List contents of the current directory |
*/ |
dir_item_t * ls(unsigned int * length) { |
dir_item_t * result; |
unsigned short entries_num; |
int retval; |
|
file_t * shared_file = file_connect(); |
if (shared_file == NULL) { |
return NULL; |
} |
|
/* We want lookup our work directory. */ |
printf("Request for get number of entries..."); |
retval = send_request(fs_phone, FS_DSUM, shared_file->params, shared_file->share); |
if (retval < 0) { |
printf("%d\n", retval); |
f_err = F_READ_ERROR; |
return NULL; |
} |
printf("OK\n"); |
printf("Total number of entries: %d\n", retval); |
|
entries_num = retval; |
*length = entries_num; |
|
/* File list in working directory. */ |
printf("File list:\n"); |
|
result = malloc(entries_num * sizeof (dir_item_t)); |
|
int entry; |
for (entry = 0; entry < entries_num; entry++) { |
|
shared_file->params->entry_number = entry; |
retval = send_request(fs_phone, FS_READENTRY, shared_file->params, shared_file->share); |
if (retval < 0) { |
printf("%d\n", retval); |
f_err = F_READ_ERROR; |
return NULL; |
} |
|
memcpy(&(result[entry].inode_num), shared_file->share, sizeof(unsigned short)); |
memcpy(result[entry].name, (void *)(shared_file->share+sizeof(unsigned short)), retval-sizeof(unsigned short)); |
|
/* Do not show empty entries. */ |
if (!result[entry].inode_num) |
continue; |
|
printf("Inode number: %u\t\t", result[entry].inode_num); |
printf("File name: %s\n", result[entry].name); |
|
} |
printf("OK\n"); |
return result; |
} |
|
/** |
* Change the current working directory for the task |
*/ |
int chdir(char * new_dir) { |
int retval; |
file_t * shared_file = file_connect(); |
|
if (shared_file == NULL) { |
f_err = F_READ_ERROR; |
return F_READ_ERROR; |
} |
memcpy(shared_file->params->fname, new_dir, 30); |
|
printf("Request for changing the curret directory to %s...", new_dir); |
retval = send_request(fs_phone, FS_CHDIR, shared_file->params, shared_file->share); |
if (retval < 0) { |
printf("%d\n", retval); |
f_err = F_READ_ERROR; |
return F_READ_ERROR; |
} |
printf("OK\n"); |
|
retval = file_disconnect(shared_file); |
f_err = F_OK; |
return F_OK; |
} |
|
/** |
* Open a file for reading and/or writing |
*/ |
file_t * fopen (char * name, int mode){ |
int retval; |
file_t * file = file_connect(); |
|
/* We want to work with the specified file. */ |
memcpy(file->params->fname, name, 30); |
|
printf("Request for opening file %s...", name); |
retval = send_request(fs_phone, FS_OPEN, file->params, file->share); |
if (retval < 0) { |
printf("%d\n", retval); |
return NULL; |
} |
printf("OK\n"); |
|
file->handle = retval; |
printf("Returned file handle...%d\n", file->handle); |
|
return file; |
} |
|
/** |
* Read status information about a file |
*/ |
int fstat(file_t * file) { |
int retval; |
memcpy(file->params->fname, file->base_info.name, 30); |
file->params->fd = file->handle; |
|
printf("Request for getting info about file %s[FSTAT called]...", file->params->fname); |
retval = send_request(fs_phone, FS_FSTAT, file->params, file->share); |
if (retval < 0) { |
printf("%d\n", retval); |
return -1; |
} |
|
memcpy((void *)(&file->stat), file->share, sizeof(stat_t)); |
|
printf("Info about file: %s\n", file->params->fname); |
printf("Inode number: %d\n", file->stat.st_ino); |
printf("Mode: %d\n", file->stat.st_mode); |
printf("Links: %d\n", file->stat.st_nlink); |
printf("Size: %d\n", file->stat.st_size); |
|
printf("OK\n"); |
|
f_err = F_OK; |
return F_OK; |
} |
|
/** |
* Read data from a file |
*/ |
int fread(file_t * file, void* buffer, unsigned int size){ |
int retval; |
file->params->nbytes = size; |
|
printf("Request for reading %d bytes from file %s...", file->params->nbytes, file->params->fname); |
retval = send_request(fs_phone, FS_READ, file->params, file->share); |
if (retval < 0) { |
printf("%d\n", retval); |
return -1; |
} |
printf("OK\n"); |
|
printf("%d bytes was read into buffer\n", retval); |
printf("\nContent of the buffer:\n"); |
printf(file->share); |
printf("\n\n"); |
|
f_err = F_OK; |
return F_OK; |
} |
|
/** |
* Seek to a position within a file |
*/ |
int fseek(file_t * file, int offset, int whence) { |
int retval; |
file->params->offset = 0; |
file->params->whence = 0; /* from beginning of the file */ |
|
printf("Request for seeking after %d bytes inside file %s...", file->params->offset, file->params->fname); |
retval = send_request(fs_phone, FS_SEEK, file->params, file->share); |
if (retval < 0) { |
printf("%d\n", retval); |
return -1; |
} |
printf("OK\n"); |
printf("New file position is: %d\n", retval); |
|
f_err = F_OK; |
return F_OK; |
} |
|
/** |
* Close a file |
*/ |
int fclose(file_t * file) { |
int retval; |
|
printf("Request for closing file %s...", file->params->fname); |
retval = send_request(fs_phone, FS_CLOSE, file->params, file->share); |
if (retval < 0) { |
printf("%d\n", retval); |
return -1; |
} |
printf("OK\n"); |
|
if (file != NULL) file_disconnect(file); |
|
f_err = F_OK; |
return F_OK; |
} |
|
/** |
* } |
*/ |