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
RevLine 
[41202a9]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
[b1834a01]29/** @addtogroup mfs
[41202a9]30 * @{
31 */
32
[1d6dd2a]33#include <str.h>
[41202a9]34#include "mfs.h"
35
[bb8cd79]36/**Read a directory entry from disk.
37 *
38 * @param mnode Pointer to the directory node.
[013d0d7]39 * @param d_info Pointer to a directory entry structure where
40 * the dentry info will be stored.
[bb8cd79]41 * @param index index of the dentry in the list.
42 *
[cde999a]43 * @return EOK on success or an error code.
[bb8cd79]44 */
[b7fd2a0]45errno_t
[3a5ee6c]46mfs_read_dentry(struct mfs_node *mnode,
[6d4d883]47 struct mfs_dentry_info *d_info, unsigned index)
[41202a9]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
[b7fd2a0]55 errno_t r = mfs_read_map(&block, mnode, index * sbi->dirsize);
[c699b0c]56 if (r != EOK)
57 goto out_err;
[41202a9]58
[488f7ed]59 if (block == 0) {
[6d4d883]60 /* End of the dentries list */
[9e2d6dc]61 r = EOK;
[488f7ed]62 goto out_err;
63 }
64
[03bc76a]65 r = block_get(&b, inst->service_id, block, BLOCK_FLAGS_NONE);
[c699b0c]66 if (r != EOK)
67 goto out_err;
[41202a9]68
[7a57269f]69 unsigned dentries_per_zone = sbi->block_size / sbi->dirsize;
[1494e52]70 unsigned dentry_off = index % dentries_per_zone;
[7a57269f]71
[41202a9]72 if (sbi->fs_version == MFS_VERSION_V3) {
73 struct mfs3_dentry *d3;
74
[e666ddc]75 d3 = b->data + (dentry_off * MFS3_DIRSIZE);
[d0f3692]76
[e80c2ff]77 d_info->d_inum = conv32(sbi->native, d3->d_inum);
78 memcpy(d_info->d_name, d3->d_name, MFS3_MAX_NAME_LEN);
[f7d6b30]79 d_info->d_name[MFS3_MAX_NAME_LEN] = 0;
[41202a9]80 } else {
81 const int namelen = longnames ? MFS_L_MAX_NAME_LEN :
[6d4d883]82 MFS_MAX_NAME_LEN;
[41202a9]83
84 struct mfs_dentry *d;
85
[e666ddc]86 d = b->data + dentry_off * (longnames ? MFSL_DIRSIZE :
[6d4d883]87 MFS_DIRSIZE);
[e80c2ff]88 d_info->d_inum = conv16(sbi->native, d->d_inum);
89 memcpy(d_info->d_name, d->d_name, namelen);
[f7d6b30]90 d_info->d_name[namelen] = 0;
[41202a9]91 }
92
[9530d94]93 r = block_put(b);
[41202a9]94
[e80c2ff]95 d_info->index = index;
96 d_info->node = mnode;
[41202a9]97
98out_err:
[b89281b]99 return r;
[41202a9]100}
101
[bb8cd79]102/**Write a directory entry on disk.
103 *
[013d0d7]104 * @param d_info The directory entry to write to disk.
[bb8cd79]105 *
[cde999a]106 * @return EOK on success or an error code.
[bb8cd79]107 */
[b7fd2a0]108errno_t
[3a5ee6c]109mfs_write_dentry(struct mfs_dentry_info *d_info)
[87d4422]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;
[b7fd2a0]117 errno_t r;
[87d4422]118
[3a5ee6c]119 r = mfs_read_map(&block, mnode, d_off_bytes);
[c699b0c]120 if (r != EOK)
121 goto out;
[87d4422]122
[03bc76a]123 r = block_get(&b, mnode->instance->service_id, block, BLOCK_FLAGS_NONE);
[c699b0c]124 if (r != EOK)
125 goto out;
[87d4422]126
[07dcec5]127 const size_t name_len = sbi->max_name_len;
[87d4422]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;
[9530d94]146 r = block_put(b);
[87d4422]147
148out:
149 return r;
150}
151
[bb8cd79]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 *
[cde999a]157 * @return EOK on success or an error code.
[bb8cd79]158 */
[b7fd2a0]159errno_t
[3a5ee6c]160mfs_remove_dentry(struct mfs_node *mnode, const char *d_name)
[c955be91]161{
162 struct mfs_sb_info *sbi = mnode->instance->sbi;
[e80c2ff]163 struct mfs_dentry_info d_info;
[b7fd2a0]164 errno_t r;
[c955be91]165
[08e103d4]166 const size_t name_len = str_bytes(d_name);
[c955be91]167
168 if (name_len > sbi->max_name_len)
169 return ENAMETOOLONG;
170
[c2e50d7]171 /* Search the directory entry to be removed */
[e80c2ff]172 unsigned i;
[18b6a88]173 for (i = 0; i < mnode->ino_i->i_size / sbi->dirsize; ++i) {
[3a5ee6c]174 r = mfs_read_dentry(mnode, &d_info, i);
[c699b0c]175 if (r != EOK)
176 return r;
[c955be91]177
[08e103d4]178 const size_t d_name_len = str_bytes(d_info.d_name);
[7a2be00]179
180 if (name_len == d_name_len &&
[44ecf89]181 memcmp(d_info.d_name, d_name, name_len) == 0) {
[6d4d883]182
[e80c2ff]183 d_info.d_inum = 0;
[3a5ee6c]184 r = mfs_write_dentry(&d_info);
[c955be91]185 return r;
186 }
187 }
188
189 return ENOENT;
190}
191
[bb8cd79]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 *
[cde999a]198 * @return EOK on success or an error code.
[bb8cd79]199 */
[b7fd2a0]200errno_t
[6d4d883]201mfs_insert_dentry(struct mfs_node *mnode, const char *d_name,
202 fs_index_t d_inum)
[07dcec5]203{
[b7fd2a0]204 errno_t r;
[07dcec5]205 struct mfs_sb_info *sbi = mnode->instance->sbi;
[e80c2ff]206 struct mfs_dentry_info d_info;
[07dcec5]207 bool empty_dentry_found = false;
208
[08e103d4]209 const size_t name_len = str_bytes(d_name);
[07dcec5]210
[c955be91]211 if (name_len > sbi->max_name_len)
212 return ENAMETOOLONG;
[07dcec5]213
[6d4d883]214 /* Search for an empty dentry */
[e80c2ff]215 unsigned i;
216 for (i = 0; i < mnode->ino_i->i_size / sbi->dirsize; ++i) {
[3a5ee6c]217 r = mfs_read_dentry(mnode, &d_info, i);
[c699b0c]218 if (r != EOK)
219 return r;
[07dcec5]220
[e80c2ff]221 if (d_info.d_inum == 0) {
[6d4d883]222 /* This entry is not used */
[07dcec5]223 empty_dentry_found = true;
224 break;
225 }
226 }
227
228 if (!empty_dentry_found) {
[b2a18234]229 uint32_t b, pos;
230 pos = mnode->ino_i->i_size;
[3a5ee6c]231 r = mfs_read_map(&b, mnode, pos);
[c699b0c]232 if (r != EOK)
233 goto out;
[07dcec5]234
[b2a18234]235 if (b == 0) {
[6d4d883]236 /* Increase the inode size */
[b2a18234]237
238 uint32_t dummy;
239 r = mfs_alloc_zone(mnode->instance, &b);
[c699b0c]240 if (r != EOK)
241 goto out;
[3a5ee6c]242 r = mfs_write_map(mnode, pos, b, &dummy);
[64e63ce1]243 if (r != EOK) {
244 mfs_free_zone(mnode->instance, b);
[c699b0c]245 goto out;
[64e63ce1]246 }
[b2a18234]247 }
248
249 mnode->ino_i->i_size += sbi->dirsize;
250 mnode->ino_i->dirty = true;
251
[5b38ecf0]252 d_info.index = i;
253 d_info.node = mnode;
[07dcec5]254 }
255
[e80c2ff]256 d_info.d_inum = d_inum;
257 memcpy(d_info.d_name, d_name, name_len);
[f7d6b30]258 if (name_len < sbi->max_name_len)
259 d_info.d_name[name_len] = 0;
[07dcec5]260
[3a5ee6c]261 r = mfs_write_dentry(&d_info);
[2527b1d5]262out:
[9e2d6dc]263 return r;
[07dcec5]264}
265
[41202a9]266/**
267 * @}
[44c6091f]268 */
Note: See TracBrowser for help on using the repository browser.