source: mainline/uspace/srv/fs/mfs/mfs_dentry.c@ 08e103d4

Last change on this file since 08e103d4 was 08e103d4, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

Use clearer naming for string length functions

This and the following commit change the names of functions, as well as
their documentation, to use unambiguous terms "bytes" and "code points"
instead of ambiguous terms "size", "length", and "characters".

  • Property mode set to 100644
File size: 6.8 KB
Line 
1/*
2 * Copyright (c) 2011 Maurizio Lombardi
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup mfs
30 * @{
31 */
32
33#include <str.h>
34#include "mfs.h"
35
36/**Read a directory entry from disk.
37 *
38 * @param mnode Pointer to the directory node.
39 * @param d_info Pointer to a directory entry structure where
40 * the dentry info will be stored.
41 * @param index index of the dentry in the list.
42 *
43 * @return EOK on success or an error code.
44 */
45errno_t
46mfs_read_dentry(struct mfs_node *mnode,
47 struct mfs_dentry_info *d_info, unsigned index)
48{
49 const struct mfs_instance *inst = mnode->instance;
50 const struct mfs_sb_info *sbi = inst->sbi;
51 const bool longnames = sbi->long_names;
52 uint32_t block;
53 block_t *b;
54
55 errno_t r = mfs_read_map(&block, mnode, index * sbi->dirsize);
56 if (r != EOK)
57 goto out_err;
58
59 if (block == 0) {
60 /* End of the dentries list */
61 r = EOK;
62 goto out_err;
63 }
64
65 r = block_get(&b, inst->service_id, block, BLOCK_FLAGS_NONE);
66 if (r != EOK)
67 goto out_err;
68
69 unsigned dentries_per_zone = sbi->block_size / sbi->dirsize;
70 unsigned dentry_off = index % dentries_per_zone;
71
72 if (sbi->fs_version == MFS_VERSION_V3) {
73 struct mfs3_dentry *d3;
74
75 d3 = b->data + (dentry_off * MFS3_DIRSIZE);
76
77 d_info->d_inum = conv32(sbi->native, d3->d_inum);
78 memcpy(d_info->d_name, d3->d_name, MFS3_MAX_NAME_LEN);
79 d_info->d_name[MFS3_MAX_NAME_LEN] = 0;
80 } else {
81 const int namelen = longnames ? MFS_L_MAX_NAME_LEN :
82 MFS_MAX_NAME_LEN;
83
84 struct mfs_dentry *d;
85
86 d = b->data + dentry_off * (longnames ? MFSL_DIRSIZE :
87 MFS_DIRSIZE);
88 d_info->d_inum = conv16(sbi->native, d->d_inum);
89 memcpy(d_info->d_name, d->d_name, namelen);
90 d_info->d_name[namelen] = 0;
91 }
92
93 r = block_put(b);
94
95 d_info->index = index;
96 d_info->node = mnode;
97
98out_err:
99 return r;
100}
101
102/**Write a directory entry on disk.
103 *
104 * @param d_info The directory entry to write to disk.
105 *
106 * @return EOK on success or an error code.
107 */
108errno_t
109mfs_write_dentry(struct mfs_dentry_info *d_info)
110{
111 struct mfs_node *mnode = d_info->node;
112 struct mfs_sb_info *sbi = mnode->instance->sbi;
113 const unsigned d_off_bytes = d_info->index * sbi->dirsize;
114 const unsigned dirs_per_block = sbi->block_size / sbi->dirsize;
115 block_t *b;
116 uint32_t block;
117 errno_t r;
118
119 r = mfs_read_map(&block, mnode, d_off_bytes);
120 if (r != EOK)
121 goto out;
122
123 r = block_get(&b, mnode->instance->service_id, block, BLOCK_FLAGS_NONE);
124 if (r != EOK)
125 goto out;
126
127 const size_t name_len = sbi->max_name_len;
128 uint8_t *ptr = b->data;
129 ptr += (d_info->index % dirs_per_block) * sbi->dirsize;
130
131 if (sbi->fs_version == MFS_VERSION_V3) {
132 struct mfs3_dentry *dentry;
133 dentry = (struct mfs3_dentry *) ptr;
134
135 dentry->d_inum = conv32(sbi->native, d_info->d_inum);
136 memcpy(dentry->d_name, d_info->d_name, name_len);
137 } else {
138 struct mfs_dentry *dentry;
139 dentry = (struct mfs_dentry *) ptr;
140
141 dentry->d_inum = conv16(sbi->native, d_info->d_inum);
142 memcpy(dentry->d_name, d_info->d_name, name_len);
143 }
144
145 b->dirty = true;
146 r = block_put(b);
147
148out:
149 return r;
150}
151
152/**Remove a directory entry from a directory.
153 *
154 * @param mnode Pointer to the directory node.
155 * @param d_name Name of the directory entry to delete.
156 *
157 * @return EOK on success or an error code.
158 */
159errno_t
160mfs_remove_dentry(struct mfs_node *mnode, const char *d_name)
161{
162 struct mfs_sb_info *sbi = mnode->instance->sbi;
163 struct mfs_dentry_info d_info;
164 errno_t r;
165
166 const size_t name_len = str_bytes(d_name);
167
168 if (name_len > sbi->max_name_len)
169 return ENAMETOOLONG;
170
171 /* Search the directory entry to be removed */
172 unsigned i;
173 for (i = 0; i < mnode->ino_i->i_size / sbi->dirsize; ++i) {
174 r = mfs_read_dentry(mnode, &d_info, i);
175 if (r != EOK)
176 return r;
177
178 const size_t d_name_len = str_bytes(d_info.d_name);
179
180 if (name_len == d_name_len &&
181 memcmp(d_info.d_name, d_name, name_len) == 0) {
182
183 d_info.d_inum = 0;
184 r = mfs_write_dentry(&d_info);
185 return r;
186 }
187 }
188
189 return ENOENT;
190}
191
192/**Insert a new directory entry in a existing directory.
193 *
194 * @param mnode Pointer to the directory node.
195 * @param d_name Name of the new directory entry.
196 * @param d_inum index of the inode that will be pointed by the new dentry.
197 *
198 * @return EOK on success or an error code.
199 */
200errno_t
201mfs_insert_dentry(struct mfs_node *mnode, const char *d_name,
202 fs_index_t d_inum)
203{
204 errno_t r;
205 struct mfs_sb_info *sbi = mnode->instance->sbi;
206 struct mfs_dentry_info d_info;
207 bool empty_dentry_found = false;
208
209 const size_t name_len = str_bytes(d_name);
210
211 if (name_len > sbi->max_name_len)
212 return ENAMETOOLONG;
213
214 /* Search for an empty dentry */
215 unsigned i;
216 for (i = 0; i < mnode->ino_i->i_size / sbi->dirsize; ++i) {
217 r = mfs_read_dentry(mnode, &d_info, i);
218 if (r != EOK)
219 return r;
220
221 if (d_info.d_inum == 0) {
222 /* This entry is not used */
223 empty_dentry_found = true;
224 break;
225 }
226 }
227
228 if (!empty_dentry_found) {
229 uint32_t b, pos;
230 pos = mnode->ino_i->i_size;
231 r = mfs_read_map(&b, mnode, pos);
232 if (r != EOK)
233 goto out;
234
235 if (b == 0) {
236 /* Increase the inode size */
237
238 uint32_t dummy;
239 r = mfs_alloc_zone(mnode->instance, &b);
240 if (r != EOK)
241 goto out;
242 r = mfs_write_map(mnode, pos, b, &dummy);
243 if (r != EOK) {
244 mfs_free_zone(mnode->instance, b);
245 goto out;
246 }
247 }
248
249 mnode->ino_i->i_size += sbi->dirsize;
250 mnode->ino_i->dirty = true;
251
252 d_info.index = i;
253 d_info.node = mnode;
254 }
255
256 d_info.d_inum = d_inum;
257 memcpy(d_info.d_name, d_name, name_len);
258 if (name_len < sbi->max_name_len)
259 d_info.d_name[name_len] = 0;
260
261 r = mfs_write_dentry(&d_info);
262out:
263 return r;
264}
265
266/**
267 * @}
268 */
Note: See TracBrowser for help on using the repository browser.