Rev 3628 | Rev 3638 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3628 | Rev 3634 | ||
---|---|---|---|
1 | /* |
1 | /* |
2 | * Copyright (c) 2008 Jakub Jermar |
2 | * Copyright (c) 2008 Jakub Jermar |
3 | * All rights reserved. |
3 | * All rights reserved. |
4 | * |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
7 | * are met: |
8 | * |
8 | * |
9 | * - Redistributions of source code must retain the above copyright |
9 | * - Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * - Redistributions in binary form must reproduce the above copyright |
11 | * - Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the |
12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. |
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 |
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. |
15 | * derived from this software without specific prior written permission. |
16 | * |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
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 |
18 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
21 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
22 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
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 |
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
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 |
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. |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
27 | */ |
28 | 28 | ||
29 | /** @addtogroup fs |
29 | /** @addtogroup fs |
30 | * @{ |
30 | * @{ |
31 | */ |
31 | */ |
32 | 32 | ||
33 | /** |
33 | /** |
34 | * @file fat_dentry.c |
34 | * @file fat_dentry.c |
35 | * @brief Functions that work with FAT directory entries. |
35 | * @brief Functions that work with FAT directory entries. |
36 | */ |
36 | */ |
37 | 37 | ||
38 | #include "fat_dentry.h" |
38 | #include "fat_dentry.h" |
39 | #include <ctype.h> |
39 | #include <ctype.h> |
- | 40 | #include <string.h> |
|
40 | 41 | ||
41 | #define FAT_PAD ' ' |
42 | #define FAT_PAD ' ' |
42 | 43 | ||
43 | #define FAT_DENTRY_UNUSED 0x00 |
44 | #define FAT_DENTRY_UNUSED 0x00 |
44 | #define FAT_DENTRY_E5_ESC 0x05 |
45 | #define FAT_DENTRY_E5_ESC 0x05 |
45 | #define FAT_DENTRY_DOT 0x2e |
46 | #define FAT_DENTRY_DOT 0x2e |
46 | #define FAT_DENTRY_ERASED 0xe5 |
47 | #define FAT_DENTRY_ERASED 0xe5 |
47 | 48 | ||
48 | static bool is_d_char(const char ch) |
49 | static bool is_d_char(const char ch) |
49 | { |
50 | { |
50 | if (isalnum(ch) || ch == '_') |
51 | if (isalnum(ch) || ch == '_') |
51 | return true; |
52 | return true; |
52 | else |
53 | else |
53 | return false; |
54 | return false; |
54 | } |
55 | } |
- | 56 | ||
- | 57 | /** Compare path component with the name read from the dentry. |
|
- | 58 | * |
|
- | 59 | * This function compares the path component with the name read from the dentry. |
|
- | 60 | * The comparison is case insensitive and tolerates a mismatch on the trailing |
|
- | 61 | * dot character at the end of the name (i.e. when there is a dot, but no |
|
- | 62 | * extension). |
|
- | 63 | * |
|
- | 64 | * @param name Node name read from the dentry. |
|
- | 65 | * @param component Path component. |
|
- | 66 | * |
|
- | 67 | * @return Zero on match, non-zero otherwise. |
|
- | 68 | */ |
|
- | 69 | int fat_dentry_namecmp(char *name, const char *component) |
|
- | 70 | { |
|
- | 71 | int rc; |
|
- | 72 | if (!(rc = stricmp(name, component))) |
|
- | 73 | return rc; |
|
- | 74 | if (!strchr(name, '.')) { |
|
- | 75 | /* |
|
- | 76 | * There is no '.' in the name, so we know that there is enough |
|
- | 77 | * space for appending an extra '.' to name. |
|
- | 78 | */ |
|
- | 79 | name[strlen(name)] = '.'; |
|
- | 80 | name[strlen(name) + 1] = '\0'; |
|
- | 81 | rc = stricmp(name, component); |
|
- | 82 | } |
|
- | 83 | return rc; |
|
- | 84 | } |
|
55 | 85 | ||
56 | bool fat_dentry_name_verify(const char *name) |
86 | bool fat_dentry_name_verify(const char *name) |
57 | { |
87 | { |
58 | unsigned i, dot; |
88 | unsigned i, dot; |
59 | bool dot_found = false; |
89 | bool dot_found = false; |
60 | 90 | ||
61 | 91 | ||
62 | for (i = 0; name[i]; i++) { |
92 | for (i = 0; name[i]; i++) { |
63 | if (name[i] == '.') { |
93 | if (name[i] == '.') { |
64 | if (dot_found) { |
94 | if (dot_found) { |
65 | return false; |
95 | return false; |
66 | } else { |
96 | } else { |
67 | dot_found = true; |
97 | dot_found = true; |
68 | dot = i; |
98 | dot = i; |
69 | } |
99 | } |
70 | } else { |
100 | } else { |
71 | if (!is_d_char(name[i])) |
101 | if (!is_d_char(name[i])) |
72 | return false; |
102 | return false; |
73 | } |
103 | } |
74 | } |
104 | } |
75 | 105 | ||
76 | if (dot_found) { |
106 | if (dot_found) { |
77 | if (dot > FAT_NAME_LEN) |
107 | if (dot > FAT_NAME_LEN) |
78 | return false; |
108 | return false; |
79 | if (i - dot > FAT_EXT_LEN + 1) |
109 | if (i - dot > FAT_EXT_LEN + 1) |
80 | return false; |
110 | return false; |
81 | } else { |
111 | } else { |
82 | if (i > FAT_NAME_LEN) |
112 | if (i > FAT_NAME_LEN) |
83 | return false; |
113 | return false; |
84 | } |
114 | } |
85 | 115 | ||
86 | return true; |
116 | return true; |
87 | } |
117 | } |
88 | 118 | ||
89 | void fat_dentry_name_get(const fat_dentry_t *d, char *buf) |
119 | void fat_dentry_name_get(const fat_dentry_t *d, char *buf) |
90 | { |
120 | { |
91 | int i; |
121 | int i; |
92 | 122 | ||
93 | for (i = 0; i < FAT_NAME_LEN; i++) { |
123 | for (i = 0; i < FAT_NAME_LEN; i++) { |
94 | if (d->name[i] == FAT_PAD) |
124 | if (d->name[i] == FAT_PAD) |
95 | break; |
125 | break; |
96 | if (d->name[i] == FAT_DENTRY_E5_ESC) |
126 | if (d->name[i] == FAT_DENTRY_E5_ESC) |
97 | *buf++ = 0xe5; |
127 | *buf++ = 0xe5; |
98 | else |
128 | else |
99 | *buf++ = d->name[i]; |
129 | *buf++ = d->name[i]; |
100 | } |
130 | } |
101 | if (d->ext[0] != FAT_PAD) |
131 | if (d->ext[0] != FAT_PAD) |
102 | *buf++ = '.'; |
132 | *buf++ = '.'; |
103 | for (i = 0; i < FAT_EXT_LEN; i++) { |
133 | for (i = 0; i < FAT_EXT_LEN; i++) { |
104 | if (d->ext[i] == FAT_PAD) { |
134 | if (d->ext[i] == FAT_PAD) { |
105 | *buf = '\0'; |
135 | *buf = '\0'; |
106 | return; |
136 | return; |
107 | } |
137 | } |
108 | if (d->ext[i] == FAT_DENTRY_E5_ESC) |
138 | if (d->ext[i] == FAT_DENTRY_E5_ESC) |
109 | *buf++ = 0xe5; |
139 | *buf++ = 0xe5; |
110 | else |
140 | else |
111 | *buf++ = d->ext[i]; |
141 | *buf++ = d->ext[i]; |
112 | } |
142 | } |
113 | *buf = '\0'; |
143 | *buf = '\0'; |
114 | } |
144 | } |
115 | 145 | ||
116 | void fat_dentry_name_set(fat_dentry_t *d, const char *name) |
146 | void fat_dentry_name_set(fat_dentry_t *d, const char *name) |
117 | { |
147 | { |
118 | int i; |
148 | int i; |
119 | const char fake_ext[] = " "; |
149 | const char fake_ext[] = " "; |
120 | 150 | ||
121 | 151 | ||
122 | for (i = 0; i < FAT_NAME_LEN; i++) { |
152 | for (i = 0; i < FAT_NAME_LEN; i++) { |
123 | switch ((uint8_t) *name) { |
153 | switch ((uint8_t) *name) { |
124 | case 0xe5: |
154 | case 0xe5: |
125 | d->name[i] = FAT_DENTRY_E5_ESC; |
155 | d->name[i] = FAT_DENTRY_E5_ESC; |
126 | name++; |
156 | name++; |
127 | break; |
157 | break; |
128 | case '\0': |
158 | case '\0': |
129 | case '.': |
159 | case '.': |
130 | d->name[i] = FAT_PAD; |
160 | d->name[i] = FAT_PAD; |
131 | break; |
161 | break; |
132 | default: |
162 | default: |
133 | d->name[i] = toupper(*name++); |
163 | d->name[i] = toupper(*name++); |
134 | break; |
164 | break; |
135 | } |
165 | } |
136 | } |
166 | } |
137 | if (*name++ != '.') |
167 | if (*name++ != '.') |
138 | name = fake_ext; |
168 | name = fake_ext; |
139 | for (i = 0; i < FAT_EXT_LEN; i++) { |
169 | for (i = 0; i < FAT_EXT_LEN; i++) { |
140 | switch ((uint8_t) *name) { |
170 | switch ((uint8_t) *name) { |
141 | case 0xe5: |
171 | case 0xe5: |
142 | d->ext[i] = FAT_DENTRY_E5_ESC; |
172 | d->ext[i] = FAT_DENTRY_E5_ESC; |
143 | name++; |
173 | name++; |
144 | break; |
174 | break; |
145 | case '\0': |
175 | case '\0': |
146 | d->ext[i] = FAT_PAD; |
176 | d->ext[i] = FAT_PAD; |
147 | break; |
177 | break; |
148 | default: |
178 | default: |
149 | d->ext[i] = toupper(*name++); |
179 | d->ext[i] = toupper(*name++); |
150 | break; |
180 | break; |
151 | } |
181 | } |
152 | } |
182 | } |
153 | } |
183 | } |
154 | 184 | ||
155 | fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d) |
185 | fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d) |
156 | { |
186 | { |
157 | if (d->attr & FAT_ATTR_VOLLABEL) { |
187 | if (d->attr & FAT_ATTR_VOLLABEL) { |
158 | /* volume label entry */ |
188 | /* volume label entry */ |
159 | return FAT_DENTRY_SKIP; |
189 | return FAT_DENTRY_SKIP; |
160 | } |
190 | } |
161 | if (d->name[0] == FAT_DENTRY_ERASED) { |
191 | if (d->name[0] == FAT_DENTRY_ERASED) { |
162 | /* not-currently-used entry */ |
192 | /* not-currently-used entry */ |
163 | return FAT_DENTRY_FREE; |
193 | return FAT_DENTRY_FREE; |
164 | } |
194 | } |
165 | if (d->name[0] == FAT_DENTRY_UNUSED) { |
195 | if (d->name[0] == FAT_DENTRY_UNUSED) { |
166 | /* never used entry */ |
196 | /* never used entry */ |
167 | return FAT_DENTRY_LAST; |
197 | return FAT_DENTRY_LAST; |
168 | } |
198 | } |
169 | if (d->name[0] == FAT_DENTRY_DOT) { |
199 | if (d->name[0] == FAT_DENTRY_DOT) { |
170 | /* |
200 | /* |
171 | * Most likely '.' or '..'. |
201 | * Most likely '.' or '..'. |
172 | * It cannot occur in a regular file name. |
202 | * It cannot occur in a regular file name. |
173 | */ |
203 | */ |
174 | return FAT_DENTRY_SKIP; |
204 | return FAT_DENTRY_SKIP; |
175 | } |
205 | } |
176 | return FAT_DENTRY_VALID; |
206 | return FAT_DENTRY_VALID; |
177 | } |
207 | } |
178 | 208 | ||
179 | /** |
209 | /** |
180 | * @} |
210 | * @} |
181 | */ |
211 | */ |
182 | 212 |