source: mainline/uspace/srv/fs/fat/fat_dentry.c@ ed19497

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ed19497 was ed19497, checked in by Oleg Romanenko <romanenko.oleg@…>, 14 years ago

Function for compute cheksum for Node name

  • Property mode set to 100644
File size: 5.8 KB
Line 
1/*
2 * Copyright (c) 2008 Jakub Jermar
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 fs
30 * @{
31 */
32
33/**
34 * @file fat_dentry.c
35 * @brief Functions that work with FAT directory entries.
36 */
37
38#include "fat_dentry.h"
39#include <ctype.h>
40#include <str.h>
41
42static bool is_d_char(const char ch)
43{
44 if (isalnum(ch) || ch == '_')
45 return true;
46 else
47 return false;
48}
49
50/** Compare path component with the name read from the dentry.
51 *
52 * This function compares the path component with the name read from the dentry.
53 * The comparison is case insensitive and tolerates a mismatch on the trailing
54 * dot character at the end of the name (i.e. when there is a dot, but no
55 * extension).
56 *
57 * @param name Node name read from the dentry.
58 * @param component Path component.
59 *
60 * @return Zero on match, non-zero otherwise.
61 */
62int fat_dentry_namecmp(char *name, const char *component)
63{
64 int rc;
65 size_t size;
66
67 if (!(rc = stricmp(name, component)))
68 return rc;
69 if (!str_chr(name, '.')) {
70 /*
71 * There is no '.' in the name, so we know that there is enough
72 * space for appending an extra '.' to name.
73 */
74 size = str_size(name);
75 name[size] = '.';
76 name[size + 1] = '\0';
77 rc = stricmp(name, component);
78 }
79 return rc;
80}
81
82bool fat_dentry_name_verify(const char *name)
83{
84 unsigned int i;
85 unsigned int dot = 0;
86 bool dot_found = false;
87
88
89 for (i = 0; name[i]; i++) {
90 if (name[i] == '.') {
91 if (dot_found) {
92 return false;
93 } else {
94 dot_found = true;
95 dot = i;
96 }
97 } else {
98 if (!is_d_char(name[i]))
99 return false;
100 }
101 }
102
103 if (dot_found) {
104 if (dot > FAT_NAME_LEN)
105 return false;
106 if (i - dot > FAT_EXT_LEN + 1)
107 return false;
108 } else {
109 if (i > FAT_NAME_LEN)
110 return false;
111 }
112
113 return true;
114}
115
116void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
117{
118 unsigned int i;
119
120 for (i = 0; i < FAT_NAME_LEN; i++) {
121 if (d->name[i] == FAT_PAD)
122 break;
123
124 if (d->name[i] == FAT_DENTRY_E5_ESC)
125 *buf++ = 0xe5;
126 else {
127 if (d->lcase & FAT_LCASE_LOWER_NAME)
128 *buf++ = tolower(d->name[i]);
129 else
130 *buf++ = d->name[i];
131 }
132 }
133
134 if (d->ext[0] != FAT_PAD)
135 *buf++ = '.';
136
137 for (i = 0; i < FAT_EXT_LEN; i++) {
138 if (d->ext[i] == FAT_PAD) {
139 *buf = '\0';
140 return;
141 }
142
143 if (d->ext[i] == FAT_DENTRY_E5_ESC)
144 *buf++ = 0xe5;
145 else {
146 if (d->lcase & FAT_LCASE_LOWER_EXT)
147 *buf++ = tolower(d->ext[i]);
148 else
149 *buf++ = d->ext[i];
150 }
151 }
152
153 *buf = '\0';
154}
155
156void fat_dentry_name_set(fat_dentry_t *d, const char *name)
157{
158 unsigned int i;
159 const char fake_ext[] = " ";
160 bool lower_name = true;
161 bool lower_ext = true;
162
163 for (i = 0; i < FAT_NAME_LEN; i++) {
164 switch ((uint8_t) *name) {
165 case 0xe5:
166 d->name[i] = FAT_DENTRY_E5_ESC;
167 name++;
168 break;
169 case '\0':
170 case '.':
171 d->name[i] = FAT_PAD;
172 break;
173 default:
174 if (isalpha(*name)) {
175 if (!islower(*name))
176 lower_name = false;
177 }
178
179 d->name[i] = toupper(*name++);
180 break;
181 }
182 }
183
184 if (*name++ != '.')
185 name = fake_ext;
186
187 for (i = 0; i < FAT_EXT_LEN; i++) {
188 switch ((uint8_t) *name) {
189 case 0xe5:
190 d->ext[i] = FAT_DENTRY_E5_ESC;
191 name++;
192 break;
193 case '\0':
194 d->ext[i] = FAT_PAD;
195 break;
196 default:
197 if (isalpha(*name)) {
198 if (!islower(*name))
199 lower_ext = false;
200 }
201
202 d->ext[i] = toupper(*name++);
203 break;
204 }
205 }
206
207 if (lower_name)
208 d->lcase |= FAT_LCASE_LOWER_NAME;
209 else
210 d->lcase &= ~FAT_LCASE_LOWER_NAME;
211
212 if (lower_ext)
213 d->lcase |= FAT_LCASE_LOWER_EXT;
214 else
215 d->lcase &= ~FAT_LCASE_LOWER_EXT;
216}
217
218fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
219{
220 if (d->attr & FAT_ATTR_VOLLABEL) {
221 /* volume label entry */
222 return FAT_DENTRY_SKIP;
223 }
224 if (d->name[0] == FAT_DENTRY_ERASED) {
225 /* not-currently-used entry */
226 return FAT_DENTRY_FREE;
227 }
228 if (d->name[0] == FAT_DENTRY_UNUSED) {
229 /* never used entry */
230 return FAT_DENTRY_LAST;
231 }
232 if (d->name[0] == FAT_DENTRY_DOT) {
233 /*
234 * Most likely '.' or '..'.
235 * It cannot occur in a regular file name.
236 */
237 return FAT_DENTRY_SKIP;
238 }
239 return FAT_DENTRY_VALID;
240}
241
242/** Compute checksum of Node name.
243 *
244 * Returns an unsigned byte checksum computed on an unsigned byte
245 * array. The array must be 11 bytes long and is assumed to contain
246 * a name stored in the format of a MS-DOS directory entry.
247 *
248 * @param name Node name read from the dentry.
249 *
250 * @return An 8-bit unsigned checksum of the name.
251 */
252uint8_t fat_dentry_chksum(uint8_t *name)
253{
254 uint8_t i, sum=0;
255 for (i=0; i<(FAT_NAME_LEN+FAT_EXT_LEN); i++) {
256 sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + name[i];
257 }
258 return sum;
259}
260
261
262/**
263 * @}
264 */
Note: See TracBrowser for help on using the repository browser.