update readme on build system
[lunaix-os.git] / lunaix-os / kernel / fs / twimap.c
1 #include <lunaix/fs.h>
2 #include <lunaix/fs/twimap.h>
3 #include <lunaix/mm/valloc.h>
4 #include <lunaix/spike.h>
5
6 #include <klibc/strfmt.h>
7 #include <klibc/string.h>
8
9 #include <asm/pagetable.h>
10
11 #define TWIMAP_BUFFER_SIZE PAGE_SIZE
12
13 void
14 __twimap_default_reset(struct twimap* map)
15 {
16     map->index = NULL;
17 }
18
19 int
20 __twimap_default_gonext(struct twimap* map)
21 {
22     return 0;
23 }
24
25 static int
26 __twimap_file_read(struct v_inode* inode, void* buf, size_t len, size_t fpos)
27 {
28     struct twimap* map = (struct twimap*)(inode->data);
29     return twimap_read(map, buf, len, fpos);
30 }
31
32 static int
33 __twimap_file_read_page(struct v_inode* inode, void* buf, size_t fpos)
34 {
35     return __twimap_file_read(inode, buf, PAGE_SIZE, fpos);
36 }
37
38 int
39 twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos)
40 {
41     map->buffer = valloc(TWIMAP_BUFFER_SIZE);
42     map->size_acc = 0;
43
44     map->reset(map);
45
46     // FIXME what if TWIMAP_BUFFER_SIZE is not big enough?
47
48     size_t pos = map->size_acc;
49     while (pos <= fpos) {
50         map->size_acc = 0;
51         map->read(map);
52         pos += map->size_acc;
53         
54         if (!map->go_next(map)) {
55             break;
56         }
57     }
58
59     if (pos <= fpos) {
60         vfree(map->buffer);
61         return 0;
62     }
63
64     if (!fpos) {
65         pos = 0;
66     }
67
68     size_t acc_size = MIN(len, map->size_acc - (pos - fpos)), rdlen = acc_size;
69     memcpy(buffer, map->buffer + (pos - fpos), acc_size);
70
71     while (acc_size < len && map->go_next(map)) {
72         map->size_acc = 0;
73         map->read(map);
74         rdlen = MIN(len - acc_size, map->size_acc);
75         memcpy(buffer + acc_size, map->buffer, rdlen);
76         acc_size += rdlen;
77     }
78
79     if (acc_size <= len - 1) {
80         // pad zero
81         *(char*)(buffer + acc_size + 1) = 0;
82     }
83
84     vfree(map->buffer);
85     return acc_size;
86 }
87
88 void
89 twimap_printf(struct twimap* mapping, const char* fmt, ...)
90 {
91     va_list args;
92     va_start(args, fmt);
93
94     char* buf = mapping->buffer + mapping->size_acc;
95
96     mapping->size_acc += ksnprintfv(buf, fmt, TWIMAP_BUFFER_SIZE, args) - 1;
97
98     va_end(args);
99 }
100
101 int
102 twimap_memcpy(struct twimap* mapping, const void* src, const size_t len)
103 {
104     mapping->size_acc = MIN(TWIMAP_BUFFER_SIZE, len);
105     memcpy(mapping->buffer, src, mapping->size_acc);
106
107     return mapping->size_acc;
108 }
109
110 int
111 twimap_memappend(struct twimap* mapping, const void* src, const size_t len)
112 {
113     size_t cpy_len = MIN(TWIMAP_BUFFER_SIZE - mapping->size_acc, len);
114     memcpy(mapping->buffer + mapping->size_acc, src, cpy_len);
115     mapping->size_acc += cpy_len;
116
117     return cpy_len;
118 }
119
120 struct twimap*
121 twimap_create(void* data)
122 {
123     struct twimap* map = vzalloc(sizeof(struct twimap));
124     map->reset = __twimap_default_reset;
125     map->go_next = __twimap_default_gonext;
126     map->data = data;
127
128     return map;
129 }
130
131 struct v_file_ops twimap_file_ops = { .close = default_file_close,
132                                       .read = __twimap_file_read,
133                                       .read_page = __twimap_file_read_page,
134                                       .readdir = default_file_readdir,
135                                       .seek = default_file_seek,
136                                       .write = default_file_write };