~vojtech-horky/helenos/numa

« back to all changes in this revision

Viewing changes to uspace/srv/fs/fat/fat_dentry.c

  • Committer: Vojtech Horky
  • Date: 2011-09-28 15:13:08 UTC
  • mfrom: (538.1.714 helenos-mainline)
  • Revision ID: vojtechhorky@users.sourceforge.net-20110928151308-2pz4s2w035n48o8a
Merge mainline changes

Conflicts fixed without problems (mostly caused by separating
ABI into /abi/).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Copyright (c) 2008 Jakub Jermar
 
3
 * Copyright (c) 2011 Oleg Romanenko
3
4
 * All rights reserved.
4
5
 *
5
6
 * Redistribution and use in source and binary forms, with or without
38
39
#include "fat_dentry.h"
39
40
#include <ctype.h>
40
41
#include <str.h>
41
 
 
42
 
static bool is_d_char(const char ch)
43
 
{
44
 
        if (isalnum(ch) || ch == '_')
45
 
                return true;
46
 
        else
47
 
                return false;
48
 
}
 
42
#include <errno.h>
 
43
#include <byteorder.h>
 
44
#include <assert.h>
49
45
 
50
46
/** Compare path component with the name read from the dentry.
51
47
 *
79
75
        return rc;
80
76
}
81
77
 
82
 
bool 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
 
 
116
78
void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
117
79
{
118
80
        unsigned int i;
217
179
 
218
180
fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
219
181
{
 
182
        if (d->attr == FAT_ATTR_LFN) {
 
183
                /* long name entry */
 
184
                if (FAT_LFN_ORDER(d) & FAT_LFN_ERASED)
 
185
                        return FAT_DENTRY_FREE;
 
186
                else
 
187
                        return FAT_DENTRY_LFN;
 
188
        }
220
189
        if (d->attr & FAT_ATTR_VOLLABEL) {
221
190
                /* volume label entry */
222
191
                return FAT_DENTRY_SKIP;
239
208
        return FAT_DENTRY_VALID;
240
209
}
241
210
 
 
211
/** Compute checksum of Node name.
 
212
 *
 
213
 * Returns an unsigned byte checksum computed on an unsigned byte
 
214
 * array. The array must be 11 bytes long and is assumed to contain
 
215
 * a name stored in the format of a MS-DOS directory entry.
 
216
 *
 
217
 * @param name          Node name read from the dentry.
 
218
 *
 
219
 * @return              An 8-bit unsigned checksum of the name.
 
220
 */
 
221
uint8_t fat_dentry_chksum(uint8_t *name)
 
222
{
 
223
        uint8_t i, sum = 0;
 
224
 
 
225
        for (i = 0; i < (FAT_NAME_LEN + FAT_EXT_LEN); i++)
 
226
                sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + name[i];
 
227
 
 
228
        return sum;
 
229
}
 
230
 
 
231
/** Get number of bytes in a string with size limit.
 
232
 *
 
233
 * @param str  NULL-terminated (or not) string.
 
234
 * @param size Maximum number of bytes to consider.
 
235
 *
 
236
 * @return Number of bytes in string (without 0 and ff).
 
237
 *
 
238
 */
 
239
size_t fat_lfn_str_nlength(const uint16_t *str, size_t size)
 
240
{
 
241
        size_t offset = 0;
 
242
 
 
243
        while (offset < size) {
 
244
                if (str[offset] == 0 || str[offset] == FAT_LFN_PAD) 
 
245
                        break;
 
246
                offset++;
 
247
        }
 
248
        return offset;
 
249
}
 
250
 
 
251
/** Get number of bytes in a FAT long entry occuped by characters.
 
252
 *
 
253
 * @param d FAT long entry.
 
254
 *
 
255
 * @return Number of bytes.
 
256
 *
 
257
 */
 
258
size_t fat_lfn_size(const fat_dentry_t *d)
 
259
{
 
260
        size_t size = 0;
 
261
        
 
262
        size += fat_lfn_str_nlength(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE);
 
263
        size += fat_lfn_str_nlength(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE);
 
264
        size += fat_lfn_str_nlength(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE);      
 
265
        
 
266
        return size;
 
267
}
 
268
 
 
269
size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset)
 
270
{
 
271
        int i;
 
272
        for (i = FAT_LFN_PART3_SIZE - 1; i >= 0 && *offset > 0; i--) {
 
273
                if (d->lfn.part3[i] == 0 || d->lfn.part3[i] == FAT_LFN_PAD)
 
274
                        continue;
 
275
                (*offset)--;
 
276
                dst[(*offset)] = uint16_t_le2host(d->lfn.part3[i]);
 
277
        }
 
278
        for (i = FAT_LFN_PART2_SIZE - 1; i >= 0 && *offset > 0; i--) {
 
279
                if (d->lfn.part2[i] == 0 || d->lfn.part2[i] == FAT_LFN_PAD)
 
280
                        continue;
 
281
                (*offset)--;
 
282
                dst[(*offset)] = uint16_t_le2host(d->lfn.part2[i]);
 
283
        }
 
284
        for (i = FAT_LFN_PART1_SIZE - 1; i >= 0 && *offset > 0; i--) {
 
285
                if (d->lfn.part1[i] == 0 || d->lfn.part1[i] == FAT_LFN_PAD)
 
286
                        continue;
 
287
                (*offset)--;
 
288
                dst[(*offset)] = uint16_t_le2host(d->lfn.part1[i]);
 
289
        }
 
290
        return *offset;
 
291
}
 
292
 
 
293
size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size,
 
294
    fat_dentry_t *d)
 
295
{
 
296
        size_t idx;
 
297
        for (idx = 0; idx < FAT_LFN_PART1_SIZE; idx++) {
 
298
                if (*offset < size) {
 
299
                        d->lfn.part1[idx] = host2uint16_t_le(src[*offset]);
 
300
                        (*offset)++;
 
301
                } else
 
302
                        d->lfn.part1[idx] = FAT_LFN_PAD;
 
303
        }
 
304
        for (idx = 0; idx < FAT_LFN_PART2_SIZE; idx++) {
 
305
                if (*offset < size) {
 
306
                        d->lfn.part2[idx] = host2uint16_t_le(src[*offset]);
 
307
                        (*offset)++;
 
308
                } else
 
309
                        d->lfn.part2[idx] = FAT_LFN_PAD;
 
310
        }
 
311
        for (idx = 0; idx < FAT_LFN_PART3_SIZE; idx++) {
 
312
                if (*offset < size) {
 
313
                        d->lfn.part3[idx] = host2uint16_t_le(src[*offset]);
 
314
                        (*offset)++;
 
315
                } else
 
316
                        d->lfn.part3[idx] = FAT_LFN_PAD;
 
317
        }
 
318
 
 
319
        if (src[*offset] == 0)
 
320
                offset++;
 
321
        FAT_LFN_ATTR(d) = FAT_ATTR_LFN;
 
322
        d->lfn.type = 0;
 
323
        d->lfn.firstc_lo = 0;
 
324
        
 
325
        return *offset;
 
326
}
 
327
 
 
328
void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad)
 
329
{
 
330
        wchar_t ch;
 
331
        size_t off = 0;
 
332
        size_t i = 0;
 
333
        
 
334
        while (i < count) {
 
335
                if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) {
 
336
                        if (ascii_check(ch) & IS_D_CHAR(ch))
 
337
                                *dst = toupper(ch);
 
338
                        else
 
339
                                *dst = pad;
 
340
                } else
 
341
                        break;
 
342
 
 
343
                dst++;
 
344
                i++;
 
345
        }
 
346
        *dst = '\0';
 
347
}
 
348
 
 
349
bool fat_valid_name(const char *name)
 
350
{
 
351
        wchar_t ch;
 
352
        size_t offset=0;
 
353
        bool result = true;
 
354
        
 
355
        while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) {
 
356
                if (str_chr(FAT_STOP_CHARS, ch) != NULL) {
 
357
                        result = false;
 
358
                        break;
 
359
                }
 
360
        }
 
361
        return result;
 
362
}
 
363
 
 
364
bool fat_valid_short_name(const char *name)
 
365
{
 
366
        unsigned int i;
 
367
        unsigned int dot = 0;
 
368
        bool dot_found = false;
 
369
 
 
370
        for (i = 0; name[i]; i++) {
 
371
                if (name[i] == '.') {
 
372
                        if (dot_found) {
 
373
                                return false;
 
374
                        } else {
 
375
                                dot_found = true;
 
376
                                dot = i;
 
377
                        }
 
378
                } else {
 
379
                        if (!IS_D_CHAR(name[i]))
 
380
                                return false;
 
381
                }
 
382
        }
 
383
 
 
384
        if (dot_found) {
 
385
                if (dot > FAT_NAME_LEN)
 
386
                        return false;
 
387
                if (i - dot > FAT_EXT_LEN + 1)
 
388
                        return false;
 
389
        } else {
 
390
                if (i > FAT_NAME_LEN)
 
391
                        return false;
 
392
        }
 
393
 
 
394
        return true;
 
395
}
 
396
 
 
397
size_t utf16_length(const uint16_t *wstr)
 
398
{
 
399
        size_t len = 0;
 
400
        
 
401
        while (*wstr++ != 0)
 
402
                len++;
 
403
        
 
404
        return len;
 
405
}
 
406
 
242
407
/**
243
408
 * @}
244
409
 */