Merge branch 'master' of ssh://Aleaxander@repo.or.cz/srv/git/fstk
[fstk.git] / file.c
blob7661c6e42192fc022b6f83676f2d72701f8129bc
1 /*
2 * All functions related with file, such as open, close, lseek and so on.
4 * Copyright (C) 2009 Liu Aleaxander -- All rights reserved. This file
5 * may be redistributed under the terms of the GNU Public License.
6 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include "fstk.h"
13 #include "file.h"
14 #include "dirent.h"
15 #include "fstklib.h"
16 #include "fstk_malloc.h"
19 struct file *fstk_open(struct fstk *fs, const char *name)
21 struct file *file;
22 struct inode *inode;
23 struct inode *parent;
24 char part[256];
25 char *p;
26 int symlink_count = 64;
28 if (*name == '/') {
29 inode = fs->ops->iget_root();
30 while(*name == '/')
31 name++;
32 } else {
33 inode = this_dir->dd_dir->inode;
35 parent = inode;
37 while (*name) {
38 p = part;
39 while(*name && *name != '/')
40 *p++ = *name++;
41 *p = '\0';
42 inode = fs->ops->iget(part, parent);
43 if (!inode)
44 return NULL;
45 if (inode->mode == SYMLINK_TYPE) {
46 if (--symlink_count == 0 || /* limit check */
47 (int)inode->size >= inode->blksize)
48 return NULL;
49 name = fs->ops->follow_symlink(inode, name);
50 free_inode(inode);
51 continue;
53 if (parent != this_dir->dd_dir->inode)
54 free_inode(parent);
55 parent = inode;
56 if (! *name)
57 break;
58 while(*name == '/')
59 name++;
62 file = fstk_malloc(sizeof(*file));
63 if (!file) {
64 malloc_error("file strucutre");
65 return NULL;
67 file->fs = fs;
68 file->inode = inode;
69 file->offset = 0;
71 return file;
74 #define MIN(a,b) ((a) < (b) ? (a) : (b))
76 int fstk_read(struct file *file, void *buf, uint32_t len)
78 struct inode *inode = file->inode;
79 struct fstk *fs = file->fs;
80 uint32_t bytes_need = MIN(len, inode->size - file->offset);
81 int blocks = (bytes_need + inode->blksize - 1) >> fs->block_shift;
83 if (!bytes_need)
84 return -1;
85 if ((fs->ops->read(file, buf, blocks)) < 0)
86 return -1;
87 memmove(buf, buf + (file->offset & (inode->blksize -1)), bytes_need);
88 file->offset += bytes_need;
90 return bytes_need;
94 * lseek function, use the macro from unistd.h. Well, it aslo
95 * would be easy if you want define your macros, like FSTK_SEEK_
97 int fstk_lseek(struct file *file, int off, int mode)
99 if (mode == SEEK_CUR)
100 file->offset += off;
101 else if (mode == SEEK_END)
102 file->offset = file->inode->size + off;
103 else if (mode == SEEK_SET)
104 file->offset = off;
105 else
106 file->offset = -1;
107 return file->offset;
110 void fstk_close(struct file *file)
112 if (file) {
113 if (file->inode->data)
114 fstk_free(file->inode->data);
115 fstk_free(file->inode);
116 fstk_free(file);