Code format.
[lwext4.git] / src / lwext4 / ext4_inode.c
1 /*\r
2  * Copyright (c) 2013 Grzegorz Kostka (kostka.grzegorz@gmail.com)\r
3  *\r
4  *\r
5  * HelenOS:\r
6  * Copyright (c) 2012 Martin Sucha\r
7  * Copyright (c) 2012 Frantisek Princ\r
8  * All rights reserved.\r
9  *\r
10  * Redistribution and use in source and binary forms, with or without\r
11  * modification, are permitted provided that the following conditions\r
12  * are met:\r
13  *\r
14  * - Redistributions of source code must retain the above copyright\r
15  *   notice, this list of conditions and the following disclaimer.\r
16  * - Redistributions in binary form must reproduce the above copyright\r
17  *   notice, this list of conditions and the following disclaimer in the\r
18  *   documentation and/or other materials provided with the distribution.\r
19  * - The name of the author may not be used to endorse or promote products\r
20  *   derived from this software without specific prior written permission.\r
21  *\r
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
32  */\r
33 \r
34 /** @addtogroup lwext4\r
35  * @{\r
36  */\r
37 /**\r
38  * @file  ext4_inode.c\r
39  * @brief Inode handle functions\r
40  */\r
41 \r
42 #include <ext4_config.h>\r
43 #include <ext4_types.h>\r
44 #include <ext4_inode.h>\r
45 #include <ext4_super.h>\r
46 \r
47 static uint32_t ext4_inode_block_bits_count(uint32_t block_size)\r
48 {\r
49     uint32_t bits = 8;\r
50     uint32_t size = block_size;\r
51 \r
52     do {\r
53         bits++;\r
54         size = size >> 1;\r
55     } while (size > 256);\r
56 \r
57     return bits;\r
58 }\r
59 \r
60 \r
61 uint32_t ext4_inode_get_mode(struct ext4_sblock *sb, struct ext4_inode *inode)\r
62 {\r
63     uint32_t v = to_le16(inode->mode);\r
64 \r
65     if(ext4_get32(sb, creator_os) == EXT4_SUPERBLOCK_OS_HURD){\r
66         v |= ((uint32_t) to_le16(inode->osd2.hurd2.mode_high)) << 16;\r
67     }\r
68 \r
69     return v;\r
70 }\r
71 \r
72 void     ext4_inode_set_mode(struct ext4_sblock *sb, struct ext4_inode *inode, uint32_t mode)\r
73 {\r
74     inode->mode = to_le16((mode << 16) >> 16);\r
75 \r
76     if(ext4_get32(sb, creator_os) == EXT4_SUPERBLOCK_OS_HURD)\r
77         inode->osd2.hurd2.mode_high = to_le16(mode >> 16);\r
78 }\r
79 \r
80 \r
81 \r
82 uint32_t ext4_inode_get_uid(struct ext4_inode *inode)\r
83 {\r
84     return to_le32(inode->uid);\r
85 }\r
86 \r
87 void     ext4_inode_set_uid(struct ext4_inode *inode, uint32_t uid)\r
88 {\r
89     inode->uid = to_le32(uid);\r
90 }\r
91 \r
92 \r
93 uint64_t ext4_inode_get_size(struct ext4_sblock *sb, struct ext4_inode *inode)\r
94 {\r
95     uint64_t v = to_le32(inode->size_lo);\r
96 \r
97     if ((ext4_get32(sb, rev_level) > 0) && (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)))\r
98         v |= ((uint64_t)to_le32(inode->size_hi)) << 32;\r
99 \r
100     return v;\r
101 }\r
102 \r
103 void     ext4_inode_set_size(struct ext4_inode *inode, uint64_t size)\r
104 {\r
105     inode->size_lo = to_le32((size << 32) >> 32);\r
106     inode->size_hi = to_le32(size >> 32);\r
107 }\r
108 \r
109 \r
110 uint32_t ext4_inode_get_access_time(struct ext4_inode *inode)\r
111 {\r
112     return to_le32(inode->access_time);\r
113 }\r
114 void     ext4_inode_set_access_time(struct ext4_inode *inode, uint32_t time)\r
115 {\r
116     inode->access_time = to_le32(time);\r
117 }\r
118 \r
119 \r
120 uint32_t ext4_inode_get_change_inode_time(struct ext4_inode *inode)\r
121 {\r
122     return to_le32(inode->change_inode_time);\r
123 }\r
124 void     ext4_inode_set_change_inode_time(struct ext4_inode *inode, uint32_t time)\r
125 {\r
126     inode->change_inode_time = to_le32(time);\r
127 }\r
128 \r
129 \r
130 uint32_t ext4_inode_get_modification_time(struct ext4_inode *inode)\r
131 {\r
132     return to_le32(inode->modification_time);\r
133 }\r
134 \r
135 void     ext4_inode_set_modification_time(struct ext4_inode *inode, uint32_t time)\r
136 {\r
137     inode->modification_time = to_le32(time);\r
138 }\r
139 \r
140 \r
141 uint32_t ext4_inode_get_deletion_time(struct ext4_inode *inode)\r
142 {\r
143     return to_le32(inode->deletion_time);\r
144 }\r
145 \r
146 void     ext4_inode_set_deletion_time(struct ext4_inode *inode, uint32_t time)\r
147 {\r
148     inode->deletion_time = to_le32(time);\r
149 }\r
150 \r
151 uint32_t ext4_inode_get_gid(struct ext4_inode *inode)\r
152 {\r
153     return to_le32(inode->gid);\r
154 }\r
155 void     ext4_inode_set_gid(struct ext4_inode *inode, uint32_t gid)\r
156 {\r
157     inode->gid  = to_le32(gid);\r
158 }\r
159 \r
160 uint16_t ext4_inode_get_links_count(struct ext4_inode *inode)\r
161 {\r
162     return to_le16(inode->links_count);\r
163 }\r
164 void     ext4_inode_set_links_count(struct ext4_inode *inode, uint16_t cnt)\r
165 {\r
166     inode->links_count = to_le16(cnt);\r
167 }\r
168 \r
169 \r
170 uint64_t ext4_inode_get_blocks_count(struct ext4_sblock *sb,  struct ext4_inode *inode)\r
171 {\r
172     uint64_t count = to_le32(inode->blocks_count_lo);\r
173 \r
174     if (ext4_sb_check_read_only(sb,\r
175             EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {\r
176 \r
177         /* 48-bit field */\r
178         count = ((uint64_t) to_le16(inode->osd2.linux2.blocks_high)) << 32;\r
179 \r
180         if (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_HUGE_FILE)) {\r
181 \r
182             uint32_t block_bits = ext4_inode_block_bits_count(ext4_sb_get_block_size(sb));\r
183             return count << (block_bits - 9);\r
184         } else\r
185             return count;\r
186     }\r
187 \r
188     return count;\r
189 }\r
190 \r
191 \r
192 int      ext4_inode_set_blocks_count(struct ext4_sblock *sb,  struct ext4_inode *inode, uint64_t count)\r
193 {\r
194     /* 32-bit maximum */\r
195     uint64_t max = 0;\r
196     max = ~max >> 32;\r
197 \r
198     if (count <= max) {\r
199         inode->blocks_count_lo = to_le32(count);\r
200         inode->osd2.linux2.blocks_high = 0;\r
201         ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);\r
202 \r
203         return EOK;\r
204     }\r
205 \r
206     /* Check if there can be used huge files (many blocks) */\r
207     if (!ext4_sb_check_read_only(sb,\r
208             EXT4_FEATURE_RO_COMPAT_HUGE_FILE))\r
209         return EINVAL;\r
210 \r
211     /* 48-bit maximum */\r
212     max = 0;\r
213     max = ~max >> 16;\r
214 \r
215     if (count <= max) {\r
216         inode->blocks_count_lo = to_le32(count);\r
217         inode->osd2.linux2.blocks_high = to_le16(count >> 32);\r
218         ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);\r
219     } else {\r
220         uint32_t block_bits = ext4_inode_block_bits_count(ext4_sb_get_block_size(sb));\r
221 \r
222         ext4_inode_set_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);\r
223         count = count >> (block_bits - 9);\r
224         inode->blocks_count_lo = to_le32(count);\r
225         inode->osd2.linux2.blocks_high = to_le16(count >> 32);\r
226     }\r
227 \r
228     return EOK;\r
229 }\r
230 \r
231 \r
232 uint32_t ext4_inode_get_flags(struct ext4_inode *inode)\r
233 {\r
234     return to_le32(inode->flags);\r
235 }\r
236 void     ext4_inode_set_flags(struct ext4_inode *inode, uint32_t flags)\r
237 {\r
238     inode->flags =      to_le32(flags);\r
239 }\r
240 \r
241 uint32_t ext4_inode_get_generation(struct ext4_inode *inode)\r
242 {\r
243     return to_le32(inode->generation);\r
244 }\r
245 void     ext4_inode_set_generation(struct ext4_inode *inode, uint32_t gen)\r
246 {\r
247     inode->generation = to_le32(gen);\r
248 }\r
249 \r
250 uint64_t ext4_inode_get_file_acl(struct ext4_inode *inode, struct ext4_sblock *sb)\r
251 {\r
252     /*TODO: Verify it*/\r
253     uint64_t v = to_le32(inode->file_acl_lo);\r
254 \r
255     if (ext4_get32(sb, creator_os) == EXT4_SUPERBLOCK_OS_LINUX)\r
256         v |= ((uint32_t) to_le16(inode->osd2.linux2.file_acl_high)) << 16;\r
257 \r
258 \r
259     return v;\r
260 }\r
261 \r
262 void     ext4_inode_set_file_acl(struct ext4_inode *inode, struct ext4_sblock *sb, uint64_t acl)\r
263 {\r
264     /*TODO: Verify it*/\r
265     inode->file_acl_lo = to_le32((acl << 32) >> 32);\r
266 \r
267     if (ext4_get32(sb, creator_os) == EXT4_SUPERBLOCK_OS_LINUX)\r
268         inode->osd2.linux2.file_acl_high = to_le16(acl >> 32);\r
269 }\r
270 \r
271 \r
272 \r
273 uint32_t ext4_inode_get_direct_block(struct ext4_inode *inode, uint32_t idx)\r
274 {\r
275     return to_le32(inode->blocks[idx]);\r
276 }\r
277 void     ext4_inode_set_direct_block(struct ext4_inode *inode, uint32_t idx, uint32_t block)\r
278 {\r
279     inode->blocks[idx] = to_le32(block);\r
280 }\r
281 \r
282 \r
283 uint32_t ext4_inode_get_indirect_block(struct ext4_inode *inode, uint32_t idx)\r
284 {\r
285     return to_le32(inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK]);\r
286 }\r
287 \r
288 void     ext4_inode_set_indirect_block(struct ext4_inode *inode, uint32_t idx, uint32_t block)\r
289 {\r
290     inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK] = to_le32(block);\r
291 }\r
292 \r
293 bool     ext4_inode_is_type(struct ext4_sblock *sb, struct ext4_inode *inode, uint32_t type)\r
294 {\r
295     return (ext4_inode_get_mode(sb, inode) & EXT4_INODE_MODE_TYPE_MASK) == type;\r
296 }\r
297 \r
298 bool     ext4_inode_has_flag(struct ext4_inode *inode, uint32_t f)\r
299 {\r
300     return ext4_inode_get_flags(inode) & f;\r
301 }\r
302 \r
303 void     ext4_inode_clear_flag(struct ext4_inode *inode, uint32_t f)\r
304 {\r
305     uint32_t flags = ext4_inode_get_flags(inode);\r
306     flags = flags & (~f);\r
307     ext4_inode_set_flags(inode, flags);\r
308 }\r
309 \r
310 void     ext4_inode_set_flag(struct ext4_inode *inode, uint32_t f)\r
311 {\r
312     uint32_t flags = ext4_inode_get_flags(inode);\r
313     flags = flags | f;\r
314     ext4_inode_set_flags(inode, flags);\r
315 }\r
316 \r
317 bool     ext4_inode_can_truncate(struct ext4_sblock *sb, struct ext4_inode *inode)\r
318 {\r
319     if ((ext4_inode_has_flag(inode, EXT4_INODE_FLAG_APPEND)) ||\r
320             (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_IMMUTABLE)))\r
321         return false;\r
322 \r
323     if ((ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)) ||\r
324             (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_DIRECTORY)))\r
325         return true;\r
326 \r
327     return false;\r
328 }\r
329 \r
330 \r
331 struct ext4_extent_header * ext4_inode_get_extent_header(struct ext4_inode *inode)\r
332 {\r
333     return (struct ext4_extent_header *) inode->blocks;\r
334 }\r
335 \r
336 /**\r
337  * @}\r
338  */\r