source: mainline/uspace/srv/fs/fat/fat_directory.c@ 4372b49

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

Fixes for api and better unicode support.

  • Property mode set to 100644
File size: 5.9 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_directory.c
35 * @brief Functions that work with FAT directory.
36 */
37
38#include "fat_directory.h"
39#include <libblock.h>
40#include <errno.h>
41#include <byteorder.h>
42#include <mem.h>
43#include <str.h>
44
45int fat_directory_block_load(fat_directory_t *);
46
47
48int fat_directory_open(fat_node_t *nodep, fat_directory_t *di)
49{
50 di->b = NULL;
51 di->nodep = nodep;
52 if (di->nodep->type != FAT_DIRECTORY)
53 return EINVAL;
54
55 di->bs = block_bb_get(di->nodep->idx->devmap_handle);
56 di->blocks = di->nodep->size / BPS(di->bs);
57 di->pos = 0;
58 di->bnum = 0;
59 di->last = false;
60
61 di->wname[0] = '\0';
62 di->lfn_offset = 0;
63 di->lfn_size = 0;
64 di->long_entry = false;
65 di->long_entry_count = 0;
66 di->checksum=0;
67
68 return EOK;
69}
70
71int fat_directory_close(fat_directory_t *di)
72{
73 int rc=EOK;
74
75 if (di->b)
76 rc = block_put(di->b);
77
78 return rc;
79}
80
81int fat_directory_block_load(fat_directory_t *di)
82{
83 uint32_t i;
84 int rc;
85
86 i = (di->pos * sizeof(fat_dentry_t)) / BPS(di->bs);
87 if (i < di->blocks) {
88 if (di->b && di->bnum != i) {
89 block_put(di->b);
90 di->b = NULL;
91 }
92 if (!di->b) {
93 rc = fat_block_get(&di->b, di->bs, di->nodep, i, BLOCK_FLAGS_NONE);
94 if (rc != EOK) {
95 di->b = NULL;
96 return rc;
97 }
98 di->bnum = i;
99 }
100 return EOK;
101 }
102 return ENOENT;
103}
104
105int fat_directory_next(fat_directory_t *di)
106{
107 int rc;
108
109 di->pos += 1;
110 rc = fat_directory_block_load(di);
111 if (rc!=EOK)
112 di->pos -= 1;
113
114 return rc;
115}
116
117int fat_directory_prev(fat_directory_t *di)
118{
119 int rc=EOK;
120
121 if (di->pos > 0) {
122 di->pos -= 1;
123 rc=fat_directory_block_load(di);
124 }
125 else
126 return ENOENT;
127
128 if (rc!=EOK)
129 di->pos += 1;
130
131 return rc;
132}
133
134int fat_directory_seek(fat_directory_t *di, aoff64_t pos)
135{
136 aoff64_t _pos = di->pos;
137 int rc;
138 di->pos = pos;
139 rc = fat_directory_block_load(di);
140 if (rc!=EOK)
141 di->pos = _pos;
142
143 return rc;
144}
145
146int fat_directory_get(fat_directory_t *di, fat_dentry_t **d)
147{
148 int rc;
149
150 rc = fat_directory_block_load(di);
151 if (rc == EOK) {
152 aoff64_t o = di->pos % (BPS(di->bs) / sizeof(fat_dentry_t));
153 *d = ((fat_dentry_t *)di->b->data) + o;
154 }
155
156 return rc;
157}
158
159int fat_directory_read(fat_directory_t *di, char *name, fat_dentry_t **de)
160{
161 fat_dentry_t *d = NULL;
162
163 do {
164 if (fat_directory_get(di, &d) == EOK) {
165 switch (fat_classify_dentry(d)) {
166 case FAT_DENTRY_LAST:
167 di->long_entry_count = 0;
168 di->long_entry = false;
169 return ENOENT;
170 case FAT_DENTRY_LFN:
171 if (di->long_entry) {
172 /* We found long entry */
173 di->long_entry_count--;
174 if ((FAT_LFN_ORDER(d) == di->long_entry_count) &&
175 (di->checksum == FAT_LFN_CHKSUM(d))) {
176 /* Right order! */
177 fat_lfn_copy_entry(d, di->wname, &di->lfn_offset);
178 } else {
179 /* Something wrong with order. Skip this long entries set */
180 di->long_entry_count = 0;
181 di->long_entry = false;
182 }
183 } else {
184 if (FAT_IS_LFN(d)) {
185 /* We found Last long entry! */
186 if (FAT_LFN_COUNT(d) <= FAT_LFN_MAX_COUNT) {
187 di->long_entry = true;
188 di->long_entry_count = FAT_LFN_COUNT(d);
189 di->lfn_size = (FAT_LFN_ENTRY_SIZE *
190 (FAT_LFN_COUNT(d) - 1)) + fat_lfn_size(d);
191 di->lfn_offset = di->lfn_size;
192 fat_lfn_copy_entry(d, di->wname, &di->lfn_offset);
193 di->checksum = FAT_LFN_CHKSUM(d);
194 }
195 }
196 }
197 break;
198 case FAT_DENTRY_VALID:
199 if (di->long_entry &&
200 (di->checksum == fat_dentry_chksum(d->name))) {
201 di->wname[di->lfn_size] = '\0';
202 if (utf16_to_str(name, FAT_LFN_NAME_SIZE, di->wname)!=EOK)
203 fat_dentry_name_get(d, name);
204 }
205 else
206 fat_dentry_name_get(d, name);
207
208 *de = d;
209 di->long_entry_count = 0;
210 di->long_entry = false;
211 return EOK;
212 default:
213 case FAT_DENTRY_SKIP:
214 case FAT_DENTRY_FREE:
215 di->long_entry_count = 0;
216 di->long_entry = false;
217 break;
218 }
219 }
220 } while (fat_directory_next(di) == EOK);
221
222 return ENOENT;
223}
224
225int fat_directory_erase(fat_directory_t *di)
226{
227 int rc;
228 fat_dentry_t *d;
229 bool flag = false;
230
231 rc = fat_directory_get(di, &d);
232 if (rc != EOK)
233 return rc;
234 di->checksum = fat_dentry_chksum(d->name);
235
236 d->name[0] = FAT_DENTRY_ERASED;
237 di->b->dirty = true;
238
239 while (!flag && fat_directory_prev(di) == EOK) {
240 if (fat_directory_get(di, &d) == EOK &&
241 fat_classify_dentry(d) == FAT_DENTRY_LFN &&
242 di->checksum == FAT_LFN_CHKSUM(d)) {
243 if (FAT_IS_LFN(d))
244 flag = true;
245 memset(d, 0, sizeof(fat_dentry_t));
246 d->name[0] = FAT_DENTRY_ERASED;
247 di->b->dirty = true;
248 }
249 else
250 break;
251 }
252
253 return EOK;
254}
255
256
257/**
258 * @}
259 */
Note: See TracBrowser for help on using the repository browser.