source: mainline/uspace/lib/ext4/src/inode.c@ 84239b1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 84239b1 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 14.3 KB
RevLine 
[eb91db7]1/*
[d1538a1]2 * Copyright (c) 2011 Martin Sucha
[f22d5ef0]3 * Copyright (c) 2012 Frantisek Princ
[eb91db7]4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libext4
31 * @{
[38542dc]32 */
[eb91db7]33/**
[4bfad34]34 * @file inode.c
[38542dc]35 * @brief Ext4 i-node structure operations.
[eb91db7]36 */
37
[fcb0d76]38#include <block.h>
[9c0c0e1]39#include <byteorder.h>
[1a7756a]40#include <errno.h>
[fcb0d76]41#include "ext4/inode.h"
42#include "ext4/superblock.h"
[6c501f8]43
[296ef5d6]44/** Compute number of bits for block count.
45 *
[38542dc]46 * @param block_size Filesystem block_size
47 *
48 * @return Number of bits
49 *
[296ef5d6]50 */
[b3d7277]51static uint32_t ext4_inode_block_bits_count(uint32_t block_size)
52{
53 uint32_t bits = 8;
54 uint32_t size = block_size;
[a35b458]55
[b3d7277]56 do {
57 bits++;
58 size = size >> 1;
59 } while (size > 256);
[a35b458]60
[b3d7277]61 return bits;
62}
63
[296ef5d6]64/** Get mode of the i-node.
65 *
[38542dc]66 * @param sb Superblock
67 * @param inode I-node to load mode from
68 *
69 * @return Mode of the i-node
70 *
[296ef5d6]71 */
[9b9d37bb]72uint32_t ext4_inode_get_mode(ext4_superblock_t *sb, ext4_inode_t *inode)
73{
74 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_HURD) {
[38542dc]75 return ((uint32_t) uint16_t_le2host(inode->osd2.hurd2.mode_high)) << 16 |
76 ((uint32_t) uint16_t_le2host(inode->mode));
[9b9d37bb]77 }
[a35b458]78
[9b9d37bb]79 return uint16_t_le2host(inode->mode);
80}
81
[296ef5d6]82/** Set mode of the i-node.
83 *
[38542dc]84 * @param sb Superblock
85 * @param inode I-node to set mode to
86 * @param mode Mode to set to i-node
87 *
[296ef5d6]88 */
[fe27eb4]89void ext4_inode_set_mode(ext4_superblock_t *sb, ext4_inode_t *inode, uint32_t mode)
[9b9d37bb]90{
[fe27eb4]91 inode->mode = host2uint16_t_le((mode << 16) >> 16);
[a35b458]92
[38542dc]93 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_HURD)
[fe27eb4]94 inode->osd2.hurd2.mode_high = host2uint16_t_le(mode >> 16);
[9b9d37bb]95}
96
[296ef5d6]97/** Get ID of the i-node owner (user id).
98 *
[38542dc]99 * @param inode I-node to load uid from
100 *
101 * @return User ID of the i-node owner
102 *
[296ef5d6]103 */
[3712434]104uint32_t ext4_inode_get_uid(ext4_inode_t *inode)
[fe27eb4]105{
106 return uint32_t_le2host(inode->uid);
107}
108
[296ef5d6]109/** Set ID of the i-node owner.
110 *
[38542dc]111 * @param inode I-node to set uid to
112 * @param uid ID of the i-node owner
113 *
[296ef5d6]114 */
[fe27eb4]115void ext4_inode_set_uid(ext4_inode_t *inode, uint32_t uid)
116{
117 inode->uid = host2uint32_t_le(uid);
118}
[3712434]119
[296ef5d6]120/** Get real i-node size.
121 *
[38542dc]122 * @param sb Superblock
123 * @param inode I-node to load size from
124 *
125 * @return Real size of i-node
126 *
[296ef5d6]127 */
[9b9d37bb]128uint64_t ext4_inode_get_size(ext4_superblock_t *sb, ext4_inode_t *inode)
[3712434]129{
[9b9d37bb]130 uint32_t major_rev = ext4_superblock_get_rev_level(sb);
[a35b458]131
[38542dc]132 if ((major_rev > 0) &&
133 (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)))
[9b9d37bb]134 return ((uint64_t)uint32_t_le2host(inode->size_hi)) << 32 |
[38542dc]135 ((uint64_t)uint32_t_le2host(inode->size_lo));
[a35b458]136
[9b9d37bb]137 return uint32_t_le2host(inode->size_lo);
[3712434]138}
139
[296ef5d6]140/** Set real i-node size.
141 *
[38542dc]142 * @param inode I-node to set size to
143 * @param size Size of the i-node
144 *
[296ef5d6]145 */
[38542dc]146void ext4_inode_set_size(ext4_inode_t *inode, uint64_t size)
147{
[296ef5d6]148 inode->size_lo = host2uint32_t_le((size << 32) >> 32);
149 inode->size_hi = host2uint32_t_le(size >> 32);
[052e82d]150}
151
[2add9ec]152/** Get time, when i-node was last accessed.
153 *
[38542dc]154 * @param inode I-node
155 *
156 * @return Time of the last access (POSIX)
157 *
[2add9ec]158 */
[fe27eb4]159uint32_t ext4_inode_get_access_time(ext4_inode_t *inode)
160{
161 return uint32_t_le2host(inode->access_time);
162}
163
[2add9ec]164/** Set time, when i-node was last accessed.
[296ef5d6]165 *
[38542dc]166 * @param inode I-node
167 * @param time Time of the last access (POSIX)
168 *
[296ef5d6]169 */
[fe27eb4]170void ext4_inode_set_access_time(ext4_inode_t *inode, uint32_t time)
171{
172 inode->access_time = host2uint32_t_le(time);
173}
174
[da9f220d]175/** Get time, when i-node was last changed.
[296ef5d6]176 *
[38542dc]177 * @param inode I-node
178 *
179 * @return Time of the last change (POSIX)
180 *
[296ef5d6]181 */
[fe27eb4]182uint32_t ext4_inode_get_change_inode_time(ext4_inode_t *inode)
183{
184 return uint32_t_le2host(inode->change_inode_time);
185}
186
[da9f220d]187/** Set time, when i-node was last changed.
[296ef5d6]188 *
[38542dc]189 * @param inode I-node
190 * @param time Time of the last change (POSIX)
191 *
[296ef5d6]192 */
[fe27eb4]193void ext4_inode_set_change_inode_time(ext4_inode_t *inode, uint32_t time)
194{
195 inode->change_inode_time = host2uint32_t_le(time);
196}
197
[da9f220d]198/** Get time, when i-node content was last modified.
[296ef5d6]199 *
[38542dc]200 * @param inode I-node
201 *
202 * @return Time of the last content modification (POSIX)
203 *
[296ef5d6]204 */
[fe27eb4]205uint32_t ext4_inode_get_modification_time(ext4_inode_t *inode)
206{
207 return uint32_t_le2host(inode->modification_time);
208}
209
[da9f220d]210/** Set time, when i-node content was last modified.
[296ef5d6]211 *
[38542dc]212 * @param inode I-node
213 * @param time Time of the last content modification (POSIX)
214 *
[296ef5d6]215 */
[fe27eb4]216void ext4_inode_set_modification_time(ext4_inode_t *inode, uint32_t time)
217{
218 inode->modification_time = host2uint32_t_le(time);
219}
220
[5b26747]221/** Get time, when i-node was deleted.
[296ef5d6]222 *
[38542dc]223 * @param inode I-node
224 *
225 * @return Time of the delete action (POSIX)
226 *
[296ef5d6]227 */
[fe27eb4]228uint32_t ext4_inode_get_deletion_time(ext4_inode_t *inode)
229{
230 return uint32_t_le2host(inode->deletion_time);
231}
232
[5b26747]233/** Set time, when i-node was deleted.
[296ef5d6]234 *
[38542dc]235 * @param inode I-node
236 * @param time Time of the delete action (POSIX)
237 *
[296ef5d6]238 */
[fe27eb4]239void ext4_inode_set_deletion_time(ext4_inode_t *inode, uint32_t time)
240{
241 inode->deletion_time = host2uint32_t_le(time);
242}
243
[296ef5d6]244/** Get ID of the i-node owner's group.
245 *
[38542dc]246 * @param inode I-node to load gid from
247 *
248 * @return Group ID of the i-node owner
249 *
[296ef5d6]250 */
[fe27eb4]251uint32_t ext4_inode_get_gid(ext4_inode_t *inode)
252{
253 return uint32_t_le2host(inode->gid);
254}
255
[296ef5d6]256/** Set ID ot the i-node owner's group.
257 *
[38542dc]258 * @param inode I-node to set gid to
259 * @param gid Group ID of the i-node owner
260 *
[296ef5d6]261 */
[fe27eb4]262void ext4_inode_set_gid(ext4_inode_t *inode, uint32_t gid)
263{
264 inode->gid = host2uint32_t_le(gid);
265}
[3712434]266
[296ef5d6]267/** Get number of links to i-node.
268 *
[38542dc]269 * @param inode I-node to load number of links from
270 *
271 * @return Number of links to i-node
272 *
[296ef5d6]273 */
[3712434]274uint16_t ext4_inode_get_links_count(ext4_inode_t *inode)
[6c501f8]275{
[9c0c0e1]276 return uint16_t_le2host(inode->links_count);
[6c501f8]277}
278
[296ef5d6]279/** Set number of links to i-node.
280 *
[38542dc]281 * @param inode I-node to set number of links to
282 * @param count Number of links to i-node
283 *
[296ef5d6]284 */
[fe27eb4]285void ext4_inode_set_links_count(ext4_inode_t *inode, uint16_t count)
286{
287 inode->links_count = host2uint16_t_le(count);
288}
[b3d7277]289
[2add9ec]290/** Get number of 512-bytes blocks used for i-node.
[296ef5d6]291 *
[38542dc]292 * @param sb Superblock
293 * @param inode I-node
294 *
295 * @return Number of 512-bytes blocks
296 *
[296ef5d6]297 */
[b3d7277]298uint64_t ext4_inode_get_blocks_count(ext4_superblock_t *sb, ext4_inode_t *inode)
299{
[38542dc]300 if (ext4_superblock_has_feature_read_only(sb,
301 EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) {
[06d85e5]302 /* 48-bit field */
[38542dc]303 uint64_t count = ((uint64_t)
304 uint16_t_le2host(inode->osd2.linux2.blocks_high)) << 32 |
305 uint32_t_le2host(inode->blocks_count_lo);
[a35b458]306
[b3d7277]307 if (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_HUGE_FILE)) {
[38542dc]308 uint32_t block_size = ext4_superblock_get_block_size(sb);
309 uint32_t block_bits = ext4_inode_block_bits_count(block_size);
310 return count << (block_bits - 9);
311 } else
[b3d7277]312 return count;
[38542dc]313 } else
[b3d7277]314 return uint32_t_le2host(inode->blocks_count_lo);
315}
316
[2add9ec]317/** Set number of 512-bytes blocks used for i-node.
[296ef5d6]318 *
[38542dc]319 * @param sb Superblock
320 * @param inode I-node
321 * @param count Number of 512-bytes blocks
322 *
323 * @return Error code
324 *
[296ef5d6]325 */
[b7fd2a0]326errno_t ext4_inode_set_blocks_count(ext4_superblock_t *sb, ext4_inode_t *inode,
[38542dc]327 uint64_t count)
328{
329 /* 32-bit maximum */
330 uint64_t max = 0;
331 max = ~max >> 32;
[a35b458]332
[38542dc]333 if (count <= max) {
334 inode->blocks_count_lo = host2uint32_t_le(count);
335 inode->osd2.linux2.blocks_high = 0;
336 ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
[a35b458]337
[38542dc]338 return EOK;
339 }
[a35b458]340
[38542dc]341 /* Check if there can be used huge files (many blocks) */
342 if (!ext4_superblock_has_feature_read_only(sb,
343 EXT4_FEATURE_RO_COMPAT_HUGE_FILE))
344 return EINVAL;
[a35b458]345
[38542dc]346 /* 48-bit maximum */
347 max = 0;
348 max = ~max >> 16;
[a35b458]349
[38542dc]350 if (count <= max) {
351 inode->blocks_count_lo = host2uint32_t_le(count);
352 inode->osd2.linux2.blocks_high = host2uint16_t_le(count >> 32);
353 ext4_inode_clear_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
354 } else {
355 uint32_t block_size = ext4_superblock_get_block_size(sb);
356 uint32_t block_bits = ext4_inode_block_bits_count(block_size);
357 ext4_inode_set_flag(inode, EXT4_INODE_FLAG_HUGE_FILE);
358 count = count >> (block_bits - 9);
359 inode->blocks_count_lo = host2uint32_t_le(count);
360 inode->osd2.linux2.blocks_high = host2uint16_t_le(count >> 32);
361 }
[a35b458]362
[38542dc]363 return EOK;
[b3d7277]364}
[eb91db7]365
[296ef5d6]366/** Get flags (features) of i-node.
[38542dc]367 *
368 * @param inode I-node to get flags from
369 *
370 * @return Flags (bitmap)
371 *
[296ef5d6]372 */
[38542dc]373uint32_t ext4_inode_get_flags(ext4_inode_t *inode)
374{
[7b9381b]375 return uint32_t_le2host(inode->flags);
376}
377
[296ef5d6]378/** Set flags (features) of i-node.
379 *
[38542dc]380 * @param inode I-node to set flags to
381 * @param flags Flags to set to i-node
382 *
[296ef5d6]383 */
[38542dc]384void ext4_inode_set_flags(ext4_inode_t *inode, uint32_t flags)
385{
[b3d7277]386 inode->flags = host2uint32_t_le(flags);
387}
388
[2add9ec]389/** Get file generation (used by NFS).
[296ef5d6]390 *
[38542dc]391 * @param inode I-node
392 *
393 * @return File generation
394 *
[296ef5d6]395 */
[fe27eb4]396uint32_t ext4_inode_get_generation(ext4_inode_t *inode)
397{
398 return uint32_t_le2host(inode->generation);
399}
400
[2add9ec]401/** Set file generation (used by NFS).
[296ef5d6]402 *
[38542dc]403 * @param inode I-node
404 * @param generation File generation
405 *
[296ef5d6]406 */
[fe27eb4]407void ext4_inode_set_generation(ext4_inode_t *inode, uint32_t generation)
408{
409 inode->generation = host2uint32_t_le(generation);
410}
411
[2add9ec]412/** Get address of block, where are extended attributes located.
[296ef5d6]413 *
[38542dc]414 * @param inode I-node
415 * @param sb Superblock
416 *
417 * @return Block address
418 *
[296ef5d6]419 */
[b191acae]420uint64_t ext4_inode_get_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb)
[343ccfd]421{
[38542dc]422 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_LINUX)
423 return ((uint32_t)
424 uint16_t_le2host(inode->osd2.linux2.file_acl_high)) << 16 |
[343ccfd]425 (uint32_t_le2host(inode->file_acl_lo));
[a35b458]426
[343ccfd]427 return uint32_t_le2host(inode->file_acl_lo);
428}
429
[2add9ec]430/** Set address of block, where are extended attributes located.
[296ef5d6]431 *
[38542dc]432 * @param inode I-node
433 * @param sb Superblock
434 * @param file_acl Block address
435 *
[296ef5d6]436 */
[b191acae]437void ext4_inode_set_file_acl(ext4_inode_t *inode, ext4_superblock_t *sb,
[38542dc]438 uint64_t file_acl)
[343ccfd]439{
440 inode->file_acl_lo = host2uint32_t_le((file_acl << 32) >> 32);
[a35b458]441
[38542dc]442 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_LINUX)
[343ccfd]443 inode->osd2.linux2.file_acl_high = host2uint16_t_le(file_acl >> 32);
444}
445
[296ef5d6]446/** Get block address of specified direct block.
447 *
[38542dc]448 * @param inode I-node to load block from
449 * @param idx Index of logical block
450 *
451 * @return Physical block address
452 *
[296ef5d6]453 */
[1e65444]454uint32_t ext4_inode_get_direct_block(ext4_inode_t *inode, uint32_t idx)
[9b9d37bb]455{
456 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
[a35b458]457
[9b9d37bb]458 return uint32_t_le2host(inode->blocks[idx]);
459}
460
[296ef5d6]461/** Set block address of specified direct block.
462 *
[38542dc]463 * @param inode I-node to set block address to
464 * @param idx Index of logical block
465 * @param fblock Physical block address
466 *
[296ef5d6]467 */
[1e65444]468void ext4_inode_set_direct_block(ext4_inode_t *inode, uint32_t idx, uint32_t fblock)
[d5a78e28]469{
470 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT);
[a35b458]471
[d5a78e28]472 inode->blocks[idx] = host2uint32_t_le(fblock);
473}
474
[296ef5d6]475/** Get block address of specified indirect block.
476 *
[38542dc]477 * @param inode I-node to get block address from
[1b20da0]478 * @param idx Index of indirect block
[38542dc]479 *
480 * @return Physical block address
481 *
[296ef5d6]482 */
[1e65444]483uint32_t ext4_inode_get_indirect_block(ext4_inode_t *inode, uint32_t idx)
[9b9d37bb]484{
485 return uint32_t_le2host(inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK]);
486}
487
[296ef5d6]488/** Set block address of specified indirect block.
489 *
[38542dc]490 * @param inode I-node to set block address to
491 * @param idx Index of indirect block
492 * @param fblock Physical block address
493 *
[296ef5d6]494 */
[38542dc]495void ext4_inode_set_indirect_block(ext4_inode_t *inode, uint32_t idx,
496 uint32_t fblock)
[1e65444]497{
[38542dc]498 inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK] =
499 host2uint32_t_le(fblock);
[1e65444]500}
501
[296ef5d6]502/** Check if i-node has specified type.
503 *
[38542dc]504 * @param sb Superblock
505 * @param inode I-node to check type of
506 * @param type Type to check
507 *
508 * @return Result of check operation
509 *
[296ef5d6]510 */
[38542dc]511bool ext4_inode_is_type(ext4_superblock_t *sb, ext4_inode_t *inode,
512 uint32_t type)
[fe27eb4]513{
514 uint32_t mode = ext4_inode_get_mode(sb, inode);
515 return (mode & EXT4_INODE_MODE_TYPE_MASK) == type;
516}
517
[296ef5d6]518/** Get extent header from the root of the extent tree.
519 *
[38542dc]520 * @param inode I-node to get extent header from
521 *
522 * @return Pointer to extent header of the root node
523 *
[296ef5d6]524 */
[acd869e]525ext4_extent_header_t * ext4_inode_get_extent_header(ext4_inode_t *inode)
526{
[38542dc]527 return (ext4_extent_header_t *) inode->blocks;
[acd869e]528}
[7b9381b]529
[296ef5d6]530/** Check if i-node has specified flag.
531 *
[38542dc]532 * @param inode I-node to check flags of
533 * @param flag Flag to check
534 *
535 * @return Result of check operation
536 *
[296ef5d6]537 */
[7bc4508]538bool ext4_inode_has_flag(ext4_inode_t *inode, uint32_t flag)
539{
[38542dc]540 if (ext4_inode_get_flags(inode) & flag)
[7b9381b]541 return true;
[a35b458]542
[7b9381b]543 return false;
544}
545
[296ef5d6]546/** Remove specified flag from i-node.
547 *
[38542dc]548 * @param inode I-node to clear flag on
549 * @param clear_flag Flag to be cleared
550 *
[296ef5d6]551 */
[b3d7277]552void ext4_inode_clear_flag(ext4_inode_t *inode, uint32_t clear_flag)
553{
554 uint32_t flags = ext4_inode_get_flags(inode);
555 flags = flags & (~clear_flag);
556 ext4_inode_set_flags(inode, flags);
557}
558
[296ef5d6]559/** Set specified flag to i-node.
560 *
[38542dc]561 * @param inode I-node to set flag on
562 * @param set_flag Flag to be set
563 *
[296ef5d6]564 */
[b3d7277]565void ext4_inode_set_flag(ext4_inode_t *inode, uint32_t set_flag)
566{
567 uint32_t flags = ext4_inode_get_flags(inode);
568 flags = flags | set_flag;
569 ext4_inode_set_flags(inode, flags);
570}
571
[296ef5d6]572/** Check if i-node can be truncated.
573 *
[38542dc]574 * @param sb Superblock
575 * @param inode I-node to check
576 *
577 * @return Result of the check operation
578 *
[296ef5d6]579 */
[43a9968]580bool ext4_inode_can_truncate(ext4_superblock_t *sb, ext4_inode_t *inode)
[12b4a7f]581{
[38542dc]582 if ((ext4_inode_has_flag(inode, EXT4_INODE_FLAG_APPEND)) ||
583 (ext4_inode_has_flag(inode, EXT4_INODE_FLAG_IMMUTABLE)))
584 return false;
[a35b458]585
[38542dc]586 if ((ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)) ||
587 (ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_DIRECTORY)))
588 return true;
[a35b458]589
[38542dc]590 return false;
[12b4a7f]591}
592
[eb91db7]593/**
594 * @}
[38542dc]595 */
Note: See TracBrowser for help on using the repository browser.