aboutsummaryrefslogtreecommitdiff
path: root/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'file.c')
-rw-r--r--file.c178
1 files changed, 178 insertions, 0 deletions
diff --git a/file.c b/file.c
new file mode 100644
index 0000000..71f84ac
--- /dev/null
+++ b/file.c
@@ -0,0 +1,178 @@
+#include "file.h"
+#include "block_walker.h"
+
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "defs.h"
+
+uint16_t file_create(const char *disk_mem, mode_t mode)
+{
+ uint16_t ipos = 0;
+ file *f = NULL;
+ bwalker *bw = NULL;
+
+ assert (disk_mem != NULL);
+
+ bw = bwalker_create (disk_mem, 0, 0);
+ ipos = inode_allocate_block(disk_mem);
+
+ f = (file *) disk_mem + INODEPOOL_OFFSET + (ipos * INODE_SIZE);
+ f->uid = getuid();
+ f->gid = getgid();
+ f->mode = mode;
+ f->size = 0;
+ f->type = I_FILE;
+ f->nlinks = 1;
+ f->ctime = NEW_TIME;
+ f->mtime = NEW_TIME;
+ f->atime = NEW_TIME;
+
+ bwalker_destroy (bw);
+
+ return (ipos);
+}
+
+size_t file_read (const char *disk_mem, file *f, char *buf,
+ size_t size, off_t offset)
+{
+ size_t result = 0;
+ size_t len = 0;
+ bwalker *bw = NULL;
+ uint16_t *block;
+ uint16_t bnum;
+
+ assert (f != NULL);
+ assert (buf != NULL);
+
+ bw = bwalker_create (disk_mem, f->size, &(f->indirect));
+
+ while (size > 0 && (bnum = bwalker_next(bw)))
+ {
+ block = (uint16_t *) disk_mem + BLOCKPOOL_OFFSET + (bnum*BLOCK_SIZE);
+ if (offset >= BLOCK_SIZE){
+ /* Nos movemos (no escribimos) */
+ offset -= BLOCK_SIZE;
+ continue;
+ }
+ assert(offset < BLOCK_SIZE);
+
+ block += offset;
+
+ len = MIN(size,(BLOCK_SIZE - offset));
+
+ memcpy(buf, block, len);
+ result += len;
+ buf += len;
+ size -= len;
+ offset = 0;
+ if(bwalker_block_is_last(bw)){
+ break;
+ }
+
+ }
+
+ bwalker_destroy (bw);
+ return (result);
+}
+
+int file_truncate (const char *disk_mem, file *f, off_t size)
+{
+ bwalker *walker;
+ uint16_t offset, i, fb_size, block=0;
+ assert(disk_mem != NULL);
+ assert(f != NULL);
+
+
+ walker=bwalker_create(disk_mem, f->size, &(f->indirect));
+ /*el tamaño en bytes de la cantidad de bloques que ocupa el file
+ * siempre es >= file_size*/
+ fb_size=(bwalker_direct_length(walker)*BLOCK_SIZE);
+
+ if(f->size < size){
+ /*si el pedacito que jode...*/
+ offset=size-f->size;
+ /*es menor que 512, y ademas el nuevo tamaño no pasa al fb_size
+ * no es neceasrio alocar bloques, solo se cambia el tamaño*/
+ if(offset<BLOCK_SIZE&&size<=fb_size){
+ f->size=size;
+ bwalker_destroy(walker);
+ return 0;
+ }
+ for(i=0; i<(DIV_CEIL(offset, BLOCK_SIZE)); i++){
+ /*aloca lo que necesita*/
+ block=bwalker_allocate_block(walker);
+ }
+ /*change size*/
+ f->size=size;
+ }else{
+ /*idem, pero al verez*/
+ offset=f->size-size;
+ f->size=size;
+ if(offset<BLOCK_SIZE&&size>=fb_size){
+ f->size=size;
+ bwalker_destroy(walker);
+ return 0;
+ }
+ for(i=0; i<(DIV_CEIL(offset, BLOCK_SIZE)); i++){
+ bwalker_free_block(walker);
+ }
+ f->size=size;
+ }
+ bwalker_destroy(walker);
+ return 0;
+}
+
+size_t file_write (const char *disk_mem, file *f, char *buf,
+ size_t size, off_t offset)
+{
+ size_t result = 0;
+ size_t len = BLOCK_SIZE;
+ bwalker *bw = NULL;
+ uint16_t *block = NULL;
+ uint16_t bnum = 0;
+ time_t new_time = NEW_TIME;
+
+ assert (disk_mem != NULL);
+ assert (f != NULL);
+
+
+ bw = bwalker_create (disk_mem, f->size, &(f->indirect));
+
+ while (size > 0 && (bnum = bwalker_next(bw)))
+ {
+ assert(bnum != f->indirect);
+ if (offset >= BLOCK_SIZE){
+ /* Nos movemos (no escribimos) */
+ offset -= BLOCK_SIZE;
+ continue;
+ }
+ block = (uint16_t *) disk_mem + BLOCKPOOL_OFFSET + (bnum*BLOCK_SIZE);
+
+ assert(offset < BLOCK_SIZE);
+ block += offset;
+
+ len = MIN(size,(BLOCK_SIZE - offset));
+
+ memcpy(block, buf, len);
+
+ result += len;
+ buf += len;
+ size -= len;
+ offset = 0;
+
+ if(bwalker_direct_length(bw)<=1){
+ break;
+ }
+
+ }
+
+ f->atime = new_time;
+ f->mtime = new_time;
+
+ bwalker_destroy (bw);
+
+ return (result);
+}