1 /* Some of the source code in this file came from "linux/fs/fat/misc.c". */
5 * Written 1992,1993 by Werner Almesberger
6 * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980
7 * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru)
11 * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
28 #include <linux/version.h>
30 #include "exfat_config.h"
31 #include "exfat_global.h"
32 #include "exfat_data.h"
33 #include "exfat_oal.h"
35 #include "exfat_blkdev.h"
36 #include "exfat_cache.h"
37 #include "exfat_nls.h"
38 #include "exfat_api.h"
39 #include "exfat_super.h"
42 #include <linux/blkdev.h>
44 #define THERE_IS_MBR 0
46 #if (THERE_IS_MBR == 1)
47 #include "exfat_part.h"
50 #define DELAYED_SYNC 0
52 #define ELAPSED_TIME 0
54 #if (ELAPSED_TIME == 1)
55 #include <linux/time.h>
57 static UINT32 __t1, __t2;
58 static UINT32 get_current_msec(void)
62 return (UINT32)(tm.tv_sec*1000000 + tm.tv_usec);
64 #define TIME_START() do {__t1 = get_current_msec(); } while (0)
65 #define TIME_END() do {__t2 = get_current_msec(); } while (0)
66 #define PRINT_TIME(n) do {printk("[EXFAT] Elapsed time %d = %d (usec)\n", n, (__t2 - __t1)); } while (0)
73 extern UINT8 uni_upcase[];
74 static UINT8 name_buf[MAX_PATH_LENGTH *MAX_CHARSET_SIZE];
75 static INT8 *reserved_names[] = {
76 "AUX ", "CON ", "NUL ", "PRN ",
77 "COM1 ", "COM2 ", "COM3 ", "COM4 ",
78 "COM5 ", "COM6 ", "COM7 ", "COM8 ", "COM9 ",
79 "LPT1 ", "LPT2 ", "LPT3 ", "LPT4 ",
80 "LPT5 ", "LPT6 ", "LPT7 ", "LPT8 ", "LPT9 ",
84 static UINT8 free_bit[] = {
85 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,
86 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3,
87 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,
88 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
89 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2,
90 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3,
91 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,
92 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,
93 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,
94 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3,
95 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,
96 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
97 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
100 static UINT8 used_bit[] = {
101 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3,
102 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4,
103 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,
104 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
105 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,
106 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
107 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,
108 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
109 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5,
110 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,
111 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,
112 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
113 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
131 INT32 ffsShutdown(void)
138 ret = bdev_shutdown();
145 INT32 ffsMountVol(struct super_block *sb, INT32 drv)
148 #if (THERE_IS_MBR == 1)
153 struct buffer_head *tmp_bh = NULL;
154 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
155 BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
157 printk("[EXFAT] ===== ffsMountVol =====\n");
160 p_fs->dev_ejected = FALSE;
165 if (p_bd->sector_size < sb->s_blocksize)
167 if (p_bd->sector_size > sb->s_blocksize)
168 sb_set_blocksize(sb, p_bd->sector_size);
170 if (sector_read(sb, 0, &tmp_bh, 1) != FFS_SUCCESS)
173 #if (THERE_IS_MBR == 1)
174 if (buf[0] != 0xEB) {
175 p_mbr = (MBR_SECTOR_T *) tmp_bh->b_data;
177 if (GET16_A(p_mbr->signature) != MBR_SIGNATURE) {
180 return FFS_FORMATERR;
183 p_pte = (PART_ENTRY_T *) p_mbr->partition + 0;
184 p_fs->PBR_sector = GET32(p_pte->start_sector);
185 p_fs->num_sectors = GET32(p_pte->num_sectors);
187 if (p_fs->num_sectors == 0) {
193 if (sector_read(sb, p_fs->PBR_sector, &tmp_bh, 1) != FFS_SUCCESS) {
199 p_fs->PBR_sector = 0;
200 #if (THERE_IS_MBR == 1)
204 p_pbr = (PBR_SECTOR_T *) tmp_bh->b_data;
206 if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) {
209 return FFS_FORMATERR;
212 for (i = 0; i < 53; i++)
217 if (GET16(p_pbr->bpb+11))
218 ret = fat16_mount(sb, p_pbr);
220 ret = fat32_mount(sb, p_pbr);
222 ret = exfat_mount(sb, p_pbr);
232 if (p_fs->vol_type == EXFAT) {
233 ret = load_alloc_bitmap(sb);
238 ret = load_upcase_table(sb);
240 free_alloc_bitmap(sb);
246 if (p_fs->dev_ejected) {
247 if (p_fs->vol_type == EXFAT) {
248 free_upcase_table(sb);
249 free_alloc_bitmap(sb);
258 INT32 ffsUmountVol(struct super_block *sb)
260 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
263 fs_set_vol_flags(sb, VOL_CLEAN);
265 if (p_fs->vol_type == EXFAT) {
266 free_upcase_table(sb);
267 free_alloc_bitmap(sb);
275 if (p_fs->dev_ejected)
281 INT32 ffsGetVolInfo(struct super_block *sb, VOL_INFO_T *info)
283 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
285 if (p_fs->used_clusters == (UINT32) ~0)
286 p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb);
288 info->FatType = p_fs->vol_type;
289 info->ClusterSize = p_fs->cluster_size;
290 info->NumClusters = p_fs->num_clusters - 2;
291 info->UsedClusters = p_fs->used_clusters;
292 info->FreeClusters = info->NumClusters - info->UsedClusters;
294 if (p_fs->dev_ejected)
300 INT32 ffsSyncVol(struct super_block *sb, INT32 do_sync)
302 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
304 fs_sync(sb, do_sync);
305 fs_set_vol_flags(sb, VOL_CLEAN);
307 if (p_fs->dev_ejected)
313 INT32 ffsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid)
315 INT32 ret, dentry, num_entries;
320 ENTRY_SET_CACHE_T *es=NULL;
321 struct super_block *sb = inode->i_sb;
322 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
324 PRINTK("ffsLookupFile entered\n");
326 ret = resolve_path(inode, path, &dir, &uni_name);
330 ret = get_num_entries_and_dos_name(sb, &dir, &uni_name, &num_entries, &dos_name);
334 dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries, &dos_name, TYPE_ALL);
338 fid->dir.dir = dir.dir;
339 fid->dir.size = dir.size;
340 fid->dir.flags = dir.flags;
344 fid->type = TYPE_DIR;
346 fid->hint_last_off = -1;
348 fid->attr = ATTR_SUBDIR;
351 fid->start_clu = p_fs->root_dir;
353 if (p_fs->vol_type == EXFAT) {
354 es = get_entry_set_in_dir(sb, &dir, dentry, ES_2_ENTRIES, &ep);
359 ep = get_entry_in_dir(sb, &dir, dentry, NULL);
365 fid->type = p_fs->fs_func->get_entry_type(ep);
367 fid->hint_last_off = -1;
368 fid->attr = p_fs->fs_func->get_entry_attr(ep);
370 fid->size = p_fs->fs_func->get_entry_size(ep2);
371 if ((fid->type == TYPE_FILE) && (fid->size == 0)) {
372 fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
373 fid->start_clu = CLUSTER_32(~0);
375 fid->flags = p_fs->fs_func->get_entry_flag(ep2);
376 fid->start_clu = p_fs->fs_func->get_entry_clu0(ep2);
379 if (p_fs->vol_type == EXFAT)
380 release_entry_set(es);
383 if (p_fs->dev_ejected)
386 PRINTK("ffsLookupFile exited successfully\n");
391 INT32 ffsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid)
396 struct super_block *sb = inode->i_sb;
397 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
399 ret = resolve_path(inode, path, &dir, &uni_name);
403 fs_set_vol_flags(sb, VOL_DIRTY);
405 ret = create_file(inode, &dir, &uni_name, mode, fid);
407 #if (DELAYED_SYNC == 0)
409 fs_set_vol_flags(sb, VOL_CLEAN);
412 if (p_fs->dev_ejected)
418 INT32 ffsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount)
420 INT32 offset, sec_offset, clu_offset;
421 UINT32 clu, LogSector;
422 UINT64 oneblkread, read_bytes;
423 struct buffer_head *tmp_bh = NULL;
424 struct super_block *sb = inode->i_sb;
425 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
426 BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
428 if (fid->type != TYPE_FILE)
429 return FFS_PERMISSIONERR;
431 if (fid->rwoffset > fid->size)
432 fid->rwoffset = fid->size;
434 if (count > (fid->size - fid->rwoffset))
435 count = fid->size - fid->rwoffset;
446 clu_offset = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits);
447 clu = fid->start_clu;
449 if (fid->flags == 0x03) {
452 if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
453 (clu_offset >= fid->hint_last_off)) {
454 clu_offset -= fid->hint_last_off;
455 clu = fid->hint_last_clu;
458 while (clu_offset > 0) {
459 if (FAT_read(sb, clu, &clu) == -1)
466 fid->hint_last_off = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits);
467 fid->hint_last_clu = clu;
469 offset = (INT32)(fid->rwoffset & (p_fs->cluster_size-1));
470 sec_offset = offset >> p_bd->sector_size_bits;
471 offset &= p_bd->sector_size_mask;
473 LogSector = START_SECTOR(clu) + sec_offset;
475 oneblkread = (UINT64)(p_bd->sector_size - offset);
476 if (oneblkread > count)
479 if ((offset == 0) && (oneblkread == p_bd->sector_size)) {
480 if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS)
482 MEMCPY(((INT8 *) buffer)+read_bytes, ((INT8 *) tmp_bh->b_data), (INT32) oneblkread);
484 if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS)
486 MEMCPY(((INT8 *) buffer)+read_bytes, ((INT8 *) tmp_bh->b_data)+offset, (INT32) oneblkread);
489 read_bytes += oneblkread;
490 fid->rwoffset += oneblkread;
496 *rcount = read_bytes;
498 if (p_fs->dev_ejected)
504 INT32 ffsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount)
506 INT32 modified = FALSE, offset, sec_offset, clu_offset;
507 INT32 num_clusters, num_alloc, num_alloced = (INT32) ~0;
508 UINT32 clu, last_clu, LogSector, sector;
509 UINT64 oneblkwrite, write_bytes;
513 ENTRY_SET_CACHE_T *es = NULL;
514 struct buffer_head *tmp_bh = NULL;
515 struct super_block *sb = inode->i_sb;
516 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
517 BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
519 if (fid->type != TYPE_FILE)
520 return FFS_PERMISSIONERR;
522 if (fid->rwoffset > fid->size)
523 fid->rwoffset = fid->size;
531 fs_set_vol_flags(sb, VOL_DIRTY);
536 num_clusters = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1;
541 clu_offset = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits);
542 clu = last_clu = fid->start_clu;
544 if (fid->flags == 0x03) {
545 if ((clu_offset > 0) && (clu != CLUSTER_32(~0))) {
546 last_clu += clu_offset - 1;
548 if (clu_offset == num_clusters)
549 clu = CLUSTER_32(~0);
554 if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
555 (clu_offset >= fid->hint_last_off)) {
556 clu_offset -= fid->hint_last_off;
557 clu = fid->hint_last_clu;
560 while ((clu_offset > 0) && (clu != CLUSTER_32(~0))) {
562 if (FAT_read(sb, clu, &clu) == -1)
569 if (clu == CLUSTER_32(~0)) {
570 num_alloc = (INT32)((count-1) >> p_fs->cluster_size_bits) + 1;
571 new_clu.dir = (last_clu == CLUSTER_32(~0)) ? CLUSTER_32(~0) : last_clu+1;
573 new_clu.flags = fid->flags;
575 num_alloced = p_fs->fs_func->alloc_cluster(sb, num_alloc, &new_clu);
576 if (num_alloced == 0)
579 if (last_clu == CLUSTER_32(~0)) {
580 if (new_clu.flags == 0x01)
582 fid->start_clu = new_clu.dir;
585 if (new_clu.flags != fid->flags) {
586 exfat_chain_cont_cluster(sb, fid->start_clu, num_clusters);
590 if (new_clu.flags == 0x01)
591 FAT_write(sb, last_clu, new_clu.dir);
594 num_clusters += num_alloced;
598 fid->hint_last_off = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits);
599 fid->hint_last_clu = clu;
601 offset = (INT32)(fid->rwoffset & (p_fs->cluster_size-1));
602 sec_offset = offset >> p_bd->sector_size_bits;
603 offset &= p_bd->sector_size_mask;
605 LogSector = START_SECTOR(clu) + sec_offset;
607 oneblkwrite = (UINT64)(p_bd->sector_size - offset);
608 if (oneblkwrite > count)
611 if ((offset == 0) && (oneblkwrite == p_bd->sector_size)) {
612 if (sector_read(sb, LogSector, &tmp_bh, 0) != FFS_SUCCESS)
614 MEMCPY(((INT8 *) tmp_bh->b_data), ((INT8 *) buffer)+write_bytes, (INT32) oneblkwrite);
615 if (sector_write(sb, LogSector, tmp_bh, 0) != FFS_SUCCESS) {
620 if ((offset > 0) || ((fid->rwoffset+oneblkwrite) < fid->size)) {
621 if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS)
624 if (sector_read(sb, LogSector, &tmp_bh, 0) != FFS_SUCCESS)
628 MEMCPY(((INT8 *) tmp_bh->b_data)+offset, ((INT8 *) buffer)+write_bytes, (INT32) oneblkwrite);
629 if (sector_write(sb, LogSector, tmp_bh, 0) != FFS_SUCCESS) {
635 count -= oneblkwrite;
636 write_bytes += oneblkwrite;
637 fid->rwoffset += oneblkwrite;
639 fid->attr |= ATTR_ARCHIVE;
641 if (fid->size < fid->rwoffset) {
642 fid->size = fid->rwoffset;
649 if (p_fs->vol_type == EXFAT) {
650 es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
655 ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
661 p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY);
662 p_fs->fs_func->set_entry_attr(ep, fid->attr);
664 if (p_fs->vol_type != EXFAT)
665 buf_modify(sb, sector);
668 if (p_fs->fs_func->get_entry_flag(ep2) != fid->flags)
669 p_fs->fs_func->set_entry_flag(ep2, fid->flags);
671 if (p_fs->fs_func->get_entry_size(ep2) != fid->size)
672 p_fs->fs_func->set_entry_size(ep2, fid->size);
674 if (p_fs->fs_func->get_entry_clu0(ep2) != fid->start_clu)
675 p_fs->fs_func->set_entry_clu0(ep2, fid->start_clu);
677 if (p_fs->vol_type != EXFAT)
678 buf_modify(sb, sector);
681 if (p_fs->vol_type == EXFAT) {
682 update_dir_checksum_with_entry_set(sb, es);
683 release_entry_set(es);
686 #if (DELAYED_SYNC == 0)
688 fs_set_vol_flags(sb, VOL_CLEAN);
693 *wcount = write_bytes;
695 if (num_alloced == 0)
698 if (p_fs->dev_ejected)
704 INT32 ffsTruncateFile(struct inode *inode, UINT64 new_size)
707 UINT32 last_clu = CLUSTER_32(0), sector;
711 struct super_block *sb = inode->i_sb;
712 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
713 FILE_ID_T *fid = &(EXFAT_I(inode)->fid);
714 ENTRY_SET_CACHE_T *es=NULL;
716 if (fid->type != TYPE_FILE)
717 return FFS_PERMISSIONERR;
719 if (fid->size <= new_size)
722 fs_set_vol_flags(sb, VOL_DIRTY);
724 clu.dir = fid->start_clu;
725 clu.size = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1;
726 clu.flags = fid->flags;
729 num_clusters = (INT32)((new_size-1) >> p_fs->cluster_size_bits) + 1;
731 if (clu.flags == 0x03) {
732 clu.dir += num_clusters;
734 while (num_clusters > 0) {
736 if (FAT_read(sb, clu.dir, &(clu.dir)) == -1)
742 clu.size -= num_clusters;
745 fid->size = new_size;
746 fid->attr |= ATTR_ARCHIVE;
748 fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
749 fid->start_clu = CLUSTER_32(~0);
752 if (p_fs->vol_type == EXFAT) {
753 es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
758 ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
764 p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY);
765 p_fs->fs_func->set_entry_attr(ep, fid->attr);
767 p_fs->fs_func->set_entry_size(ep2, new_size);
769 p_fs->fs_func->set_entry_flag(ep2, 0x01);
770 p_fs->fs_func->set_entry_clu0(ep2, CLUSTER_32(0));
773 if (p_fs->vol_type != EXFAT)
774 buf_modify(sb, sector);
776 update_dir_checksum_with_entry_set(sb, es);
777 release_entry_set(es);
780 if (last_clu != CLUSTER_32(0)) {
781 if (fid->flags == 0x01)
782 FAT_write(sb, last_clu, CLUSTER_32(~0));
785 p_fs->fs_func->free_cluster(sb, &clu, 0);
787 fid->hint_last_off = -1;
788 if (fid->rwoffset > fid->size) {
789 fid->rwoffset = fid->size;
792 #if (DELAYED_SYNC == 0)
794 fs_set_vol_flags(sb, VOL_CLEAN);
797 if (p_fs->dev_ejected)
803 INT32 ffsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry)
807 CHAIN_T olddir, newdir;
811 struct super_block *sb = old_parent_inode->i_sb;
812 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
813 UINT8 *new_path = (UINT8 *) new_dentry->d_name.name;
814 struct inode *new_inode = new_dentry->d_inode;
816 FILE_ID_T *new_fid = NULL;
819 if ((new_path == NULL) || (STRLEN(new_path) == 0))
822 olddir.dir = fid->dir.dir;
823 olddir.size = fid->dir.size;
824 olddir.flags = fid->dir.flags;
828 if (p_fs->vol_type != EXFAT) {
829 if ((olddir.dir != p_fs->root_dir) && (dentry < 2))
830 return FFS_PERMISSIONERR;
833 ep = get_entry_in_dir(sb, &olddir, dentry, NULL);
837 if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY)
838 return FFS_PERMISSIONERR;
844 new_fid = &EXFAT_I(new_inode)->fid;
845 p_dir = &(new_fid->dir);
846 new_entry = new_fid->entry;
847 ep = get_entry_in_dir(sb, p_dir, new_entry, NULL);
851 entry_type = p_fs->fs_func->get_entry_type(ep);
853 if (entry_type == TYPE_DIR) {
855 new_clu.dir = new_fid->start_clu;
856 new_clu.size = (INT32)((new_fid->size-1) >> p_fs->cluster_size_bits) + 1;
857 new_clu.flags = new_fid->flags;
859 if (!is_dir_empty(sb, &new_clu))
860 return FFS_FILEEXIST;
864 ret = resolve_path(new_parent_inode, new_path, &newdir, &uni_name);
868 fs_set_vol_flags(sb, VOL_DIRTY);
870 if (olddir.dir == newdir.dir)
871 ret = rename_file(new_parent_inode, &olddir, dentry, &uni_name, fid);
873 ret = move_file(new_parent_inode, &olddir, dentry, &newdir, &uni_name, fid);
875 if ((ret == FFS_SUCCESS) && new_inode) {
876 ep = get_entry_in_dir(sb, p_dir, new_entry, NULL);
880 num_entries = p_fs->fs_func->count_ext_entries(sb, p_dir, new_entry, ep);
883 p_fs->fs_func->delete_dir_entry(sb, p_dir, new_entry, 0, num_entries+1);
886 #if (DELAYED_SYNC == 0)
888 fs_set_vol_flags(sb, VOL_CLEAN);
891 if (p_fs->dev_ejected)
897 INT32 ffsRemoveFile(struct inode *inode, FILE_ID_T *fid)
900 CHAIN_T dir, clu_to_free;
902 struct super_block *sb = inode->i_sb;
903 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
905 dir.dir = fid->dir.dir;
906 dir.size = fid->dir.size;
907 dir.flags = fid->dir.flags;
911 ep = get_entry_in_dir(sb, &dir, dentry, NULL);
915 if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY)
916 return FFS_PERMISSIONERR;
918 fs_set_vol_flags(sb, VOL_DIRTY);
920 remove_file(inode, &dir, dentry);
922 clu_to_free.dir = fid->start_clu;
923 clu_to_free.size = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1;
924 clu_to_free.flags = fid->flags;
926 p_fs->fs_func->free_cluster(sb, &clu_to_free, 0);
928 #if (DELAYED_SYNC == 0)
930 fs_set_vol_flags(sb, VOL_CLEAN);
933 if (p_fs->dev_ejected)
939 INT32 ffsSetAttr(struct inode *inode, UINT32 attr)
943 struct super_block *sb = inode->i_sb;
944 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
945 FILE_ID_T *fid = &(EXFAT_I(inode)->fid);
946 UINT8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0;
947 ENTRY_SET_CACHE_T *es = NULL;
949 if (fid->attr == attr) {
950 if (p_fs->dev_ejected)
956 if ((fid->dir.dir == p_fs->root_dir) &&
957 (fid->entry == -1)) {
958 if (p_fs->dev_ejected)
964 if (p_fs->vol_type == EXFAT) {
965 es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
969 ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
974 type = p_fs->fs_func->get_entry_type(ep);
976 if (((type == TYPE_FILE) && (attr & ATTR_SUBDIR)) ||
977 ((type == TYPE_DIR) && (!(attr & ATTR_SUBDIR)))) {
979 if (p_fs->dev_ejected)
984 if (p_fs->vol_type == EXFAT)
985 release_entry_set(es);
989 fs_set_vol_flags(sb, VOL_DIRTY);
992 p_fs->fs_func->set_entry_attr(ep, attr);
994 if (p_fs->vol_type != EXFAT)
995 buf_modify(sb, sector);
997 update_dir_checksum_with_entry_set(sb, es);
998 release_entry_set(es);
1001 #if (DELAYED_SYNC == 0)
1003 fs_set_vol_flags(sb, VOL_CLEAN);
1006 if (p_fs->dev_ejected)
1007 return FFS_MEDIAERR;
1012 INT32 ffsGetStat(struct inode *inode, DIR_ENTRY_T *info)
1017 UNI_NAME_T uni_name;
1020 struct super_block *sb = inode->i_sb;
1021 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1022 FILE_ID_T *fid = &(EXFAT_I(inode)->fid);
1023 ENTRY_SET_CACHE_T *es=NULL;
1024 UINT8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0;
1026 PRINTK("ffsGetStat entered\n");
1029 if ((fid->dir.dir == p_fs->root_dir) &&
1030 (fid->entry == -1)) {
1031 info->Attr = ATTR_SUBDIR;
1032 MEMSET((INT8 *) &info->CreateTimestamp, 0, sizeof(DATE_TIME_T));
1033 MEMSET((INT8 *) &info->ModifyTimestamp, 0, sizeof(DATE_TIME_T));
1034 MEMSET((INT8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T));
1035 STRCPY(info->ShortName, ".");
1036 STRCPY(info->Name, ".");
1038 dir.dir = p_fs->root_dir;
1041 if (p_fs->root_dir == CLUSTER_32(0))
1042 info->Size = p_fs->dentries_in_root << DENTRY_SIZE_BITS;
1044 info->Size = count_num_clusters(sb, &dir) << p_fs->cluster_size_bits;
1046 count = count_dos_name_entries(sb, &dir, TYPE_DIR);
1048 return FFS_MEDIAERR;
1049 info->NumSubdirs = count;
1051 if (p_fs->dev_ejected)
1052 return FFS_MEDIAERR;
1057 if (p_fs->vol_type == EXFAT) {
1058 es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_2_ENTRIES, &ep);
1060 return FFS_MEDIAERR;
1063 ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
1065 return FFS_MEDIAERR;
1067 buf_lock(sb, sector);
1070 info->Attr = p_fs->fs_func->get_entry_attr(ep);
1072 p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE);
1073 info->CreateTimestamp.Year = tm.year;
1074 info->CreateTimestamp.Month = tm.mon;
1075 info->CreateTimestamp.Day = tm.day;
1076 info->CreateTimestamp.Hour = tm.hour;
1077 info->CreateTimestamp.Minute = tm.min;
1078 info->CreateTimestamp.Second = tm.sec;
1079 info->CreateTimestamp.MilliSecond = 0;
1081 p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY);
1082 info->ModifyTimestamp.Year = tm.year;
1083 info->ModifyTimestamp.Month = tm.mon;
1084 info->ModifyTimestamp.Day = tm.day;
1085 info->ModifyTimestamp.Hour = tm.hour;
1086 info->ModifyTimestamp.Minute = tm.min;
1087 info->ModifyTimestamp.Second = tm.sec;
1088 info->ModifyTimestamp.MilliSecond = 0;
1090 MEMSET((INT8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T));
1092 *(uni_name.name) = 0x0;
1093 p_fs->fs_func->get_uni_name_from_ext_entry(sb, &(fid->dir), fid->entry, uni_name.name);
1094 if (*(uni_name.name) == 0x0)
1095 get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x1);
1096 nls_uniname_to_cstring(sb, info->Name, &uni_name);
1098 if (p_fs->vol_type == EXFAT) {
1099 info->NumSubdirs = 2;
1101 buf_unlock(sb, sector);
1102 get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x0);
1103 nls_uniname_to_cstring(sb, info->ShortName, &uni_name);
1104 info->NumSubdirs = 0;
1107 info->Size = p_fs->fs_func->get_entry_size(ep2);
1109 if (p_fs->vol_type == EXFAT)
1110 release_entry_set(es);
1113 dir.dir = fid->start_clu;
1116 if (info->Size == 0)
1117 info->Size = (UINT64) count_num_clusters(sb, &dir) << p_fs->cluster_size_bits;
1119 count = count_dos_name_entries(sb, &dir, TYPE_DIR);
1121 return FFS_MEDIAERR;
1122 info->NumSubdirs += count;
1125 if (p_fs->dev_ejected)
1126 return FFS_MEDIAERR;
1128 PRINTK("ffsGetStat exited successfully\n");
1132 INT32 ffsSetStat(struct inode *inode, DIR_ENTRY_T *info)
1137 ENTRY_SET_CACHE_T *es=NULL;
1138 struct super_block *sb = inode->i_sb;
1139 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1140 FILE_ID_T *fid = &(EXFAT_I(inode)->fid);
1141 UINT8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0;
1144 if ((fid->dir.dir == p_fs->root_dir) &&
1145 (fid->entry == -1)) {
1146 if (p_fs->dev_ejected)
1147 return FFS_MEDIAERR;
1152 fs_set_vol_flags(sb, VOL_DIRTY);
1154 if (p_fs->vol_type == EXFAT) {
1155 es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
1157 return FFS_MEDIAERR;
1160 ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
1162 return FFS_MEDIAERR;
1167 p_fs->fs_func->set_entry_attr(ep, info->Attr);
1169 tm.sec = info->CreateTimestamp.Second;
1170 tm.min = info->CreateTimestamp.Minute;
1171 tm.hour = info->CreateTimestamp.Hour;
1172 tm.day = info->CreateTimestamp.Day;
1173 tm.mon = info->CreateTimestamp.Month;
1174 tm.year = info->CreateTimestamp.Year;
1175 p_fs->fs_func->set_entry_time(ep, &tm, TM_CREATE);
1177 tm.sec = info->ModifyTimestamp.Second;
1178 tm.min = info->ModifyTimestamp.Minute;
1179 tm.hour = info->ModifyTimestamp.Hour;
1180 tm.day = info->ModifyTimestamp.Day;
1181 tm.mon = info->ModifyTimestamp.Month;
1182 tm.year = info->ModifyTimestamp.Year;
1183 p_fs->fs_func->set_entry_time(ep, &tm, TM_MODIFY);
1186 p_fs->fs_func->set_entry_size(ep2, info->Size);
1188 if (p_fs->vol_type != EXFAT) {
1189 buf_modify(sb, sector);
1191 update_dir_checksum_with_entry_set(sb, es);
1192 release_entry_set(es);
1195 if (p_fs->dev_ejected)
1196 return FFS_MEDIAERR;
1201 INT32 ffsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu)
1203 INT32 num_clusters, num_alloced, modified = FALSE;
1204 UINT32 last_clu, sector;
1207 ENTRY_SET_CACHE_T *es = NULL;
1208 struct super_block *sb = inode->i_sb;
1209 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1210 FILE_ID_T *fid = &(EXFAT_I(inode)->fid);
1212 fid->rwoffset = (INT64)(clu_offset) << p_fs->cluster_size_bits;
1214 if (EXFAT_I(inode)->mmu_private == 0)
1217 num_clusters = (INT32)((EXFAT_I(inode)->mmu_private-1) >> p_fs->cluster_size_bits) + 1;
1219 *clu = last_clu = fid->start_clu;
1221 if (fid->flags == 0x03) {
1222 if ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) {
1223 last_clu += clu_offset - 1;
1225 if (clu_offset == num_clusters)
1226 *clu = CLUSTER_32(~0);
1231 if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
1232 (clu_offset >= fid->hint_last_off)) {
1233 clu_offset -= fid->hint_last_off;
1234 *clu = fid->hint_last_clu;
1237 while ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) {
1239 if (FAT_read(sb, *clu, clu) == -1)
1240 return FFS_MEDIAERR;
1245 if (*clu == CLUSTER_32(~0)) {
1246 fs_set_vol_flags(sb, VOL_DIRTY);
1248 new_clu.dir = (last_clu == CLUSTER_32(~0)) ? CLUSTER_32(~0) : last_clu+1;
1250 new_clu.flags = fid->flags;
1252 num_alloced = p_fs->fs_func->alloc_cluster(sb, 1, &new_clu);
1253 if (num_alloced < 1)
1256 if (last_clu == CLUSTER_32(~0)) {
1257 if (new_clu.flags == 0x01)
1259 fid->start_clu = new_clu.dir;
1262 if (new_clu.flags != fid->flags) {
1263 exfat_chain_cont_cluster(sb, fid->start_clu, num_clusters);
1267 if (new_clu.flags == 0x01)
1268 FAT_write(sb, last_clu, new_clu.dir);
1271 num_clusters += num_alloced;
1274 if (p_fs->vol_type == EXFAT) {
1275 es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
1277 return FFS_MEDIAERR;
1282 if (p_fs->vol_type != EXFAT) {
1283 ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or);
1285 return FFS_MEDIAERR;
1288 if (p_fs->fs_func->get_entry_flag(ep) != fid->flags)
1289 p_fs->fs_func->set_entry_flag(ep, fid->flags);
1291 if (p_fs->fs_func->get_entry_clu0(ep) != fid->start_clu)
1292 p_fs->fs_func->set_entry_clu0(ep, fid->start_clu);
1294 if (p_fs->vol_type != EXFAT)
1295 buf_modify(sb, sector);
1298 if (p_fs->vol_type == EXFAT) {
1299 update_dir_checksum_with_entry_set(sb, es);
1300 release_entry_set(es);
1303 inode->i_blocks += num_alloced << (p_fs->cluster_size_bits - 9);
1306 fid->hint_last_off = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits);
1307 fid->hint_last_clu = *clu;
1309 if (p_fs->dev_ejected)
1310 return FFS_MEDIAERR;
1315 INT32 ffsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid)
1319 UNI_NAME_T uni_name;
1320 struct super_block *sb = inode->i_sb;
1321 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1323 PRINTK("ffsCreateDir entered\n");
1325 ret = resolve_path(inode, path, &dir, &uni_name);
1329 fs_set_vol_flags(sb, VOL_DIRTY);
1331 ret = create_dir(inode, &dir, &uni_name, fid);
1333 #if (DELAYED_SYNC == 0)
1335 fs_set_vol_flags(sb, VOL_CLEAN);
1338 if (p_fs->dev_ejected)
1339 return FFS_MEDIAERR;
1344 INT32 ffsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry)
1346 INT32 i, dentry, clu_offset;
1347 INT32 dentries_per_clu, dentries_per_clu_bits = 0;
1348 UINT32 type, sector;
1350 UNI_NAME_T uni_name;
1353 struct super_block *sb = inode->i_sb;
1354 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1355 FILE_ID_T *fid = &(EXFAT_I(inode)->fid);
1357 if (fid->type != TYPE_DIR)
1358 return FFS_PERMISSIONERR;
1360 if (fid->entry == -1) {
1361 dir.dir = p_fs->root_dir;
1364 dir.dir = fid->start_clu;
1365 dir.size = (INT32)(fid->size >> p_fs->cluster_size_bits);
1366 dir.flags = fid->flags;
1369 dentry = (INT32) fid->rwoffset;
1371 if (dir.dir == CLUSTER_32(0)) {
1372 dentries_per_clu = p_fs->dentries_in_root;
1374 if (dentry == dentries_per_clu) {
1375 clu.dir = CLUSTER_32(~0);
1378 clu.size = dir.size;
1379 clu.flags = dir.flags;
1382 dentries_per_clu = p_fs->dentries_per_clu;
1383 dentries_per_clu_bits = my_log2(dentries_per_clu);
1385 clu_offset = dentry >> dentries_per_clu_bits;
1387 clu.size = dir.size;
1388 clu.flags = dir.flags;
1390 if (clu.flags == 0x03) {
1391 clu.dir += clu_offset;
1392 clu.size -= clu_offset;
1394 if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
1395 (clu_offset >= fid->hint_last_off)) {
1396 clu_offset -= fid->hint_last_off;
1397 clu.dir = fid->hint_last_clu;
1400 while (clu_offset > 0) {
1401 if (FAT_read(sb, clu.dir, &(clu.dir)) == -1)
1402 return FFS_MEDIAERR;
1409 while (clu.dir != CLUSTER_32(~0)) {
1410 if (p_fs->dev_ejected)
1413 if (dir.dir == CLUSTER_32(0))
1414 i = dentry % dentries_per_clu;
1416 i = dentry & (dentries_per_clu-1);
1418 for ( ; i < dentries_per_clu; i++, dentry++) {
1419 ep = get_entry_in_dir(sb, &clu, i, §or);
1421 return FFS_MEDIAERR;
1423 type = p_fs->fs_func->get_entry_type(ep);
1425 if (type == TYPE_UNUSED)
1428 if ((type != TYPE_FILE) && (type != TYPE_DIR))
1431 buf_lock(sb, sector);
1432 dir_entry->Attr = p_fs->fs_func->get_entry_attr(ep);
1434 p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE);
1435 dir_entry->CreateTimestamp.Year = tm.year;
1436 dir_entry->CreateTimestamp.Month = tm.mon;
1437 dir_entry->CreateTimestamp.Day = tm.day;
1438 dir_entry->CreateTimestamp.Hour = tm.hour;
1439 dir_entry->CreateTimestamp.Minute = tm.min;
1440 dir_entry->CreateTimestamp.Second = tm.sec;
1441 dir_entry->CreateTimestamp.MilliSecond = 0;
1443 p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY);
1444 dir_entry->ModifyTimestamp.Year = tm.year;
1445 dir_entry->ModifyTimestamp.Month = tm.mon;
1446 dir_entry->ModifyTimestamp.Day = tm.day;
1447 dir_entry->ModifyTimestamp.Hour = tm.hour;
1448 dir_entry->ModifyTimestamp.Minute = tm.min;
1449 dir_entry->ModifyTimestamp.Second = tm.sec;
1450 dir_entry->ModifyTimestamp.MilliSecond = 0;
1452 MEMSET((INT8 *) &dir_entry->AccessTimestamp, 0, sizeof(DATE_TIME_T));
1454 *(uni_name.name) = 0x0;
1455 p_fs->fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry, uni_name.name);
1456 if (*(uni_name.name) == 0x0)
1457 get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x1);
1458 nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name);
1459 buf_unlock(sb, sector);
1461 if (p_fs->vol_type == EXFAT) {
1462 ep = get_entry_in_dir(sb, &clu, i+1, NULL);
1464 return FFS_MEDIAERR;
1466 get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x0);
1467 nls_uniname_to_cstring(sb, dir_entry->ShortName, &uni_name);
1470 dir_entry->Size = p_fs->fs_func->get_entry_size(ep);
1472 if (dir.dir == CLUSTER_32(0)) {
1474 fid->hint_last_off = dentry >> dentries_per_clu_bits;
1475 fid->hint_last_clu = clu.dir;
1478 fid->rwoffset = (INT64) ++dentry;
1480 if (p_fs->dev_ejected)
1481 return FFS_MEDIAERR;
1486 if (dir.dir == CLUSTER_32(0))
1489 if (clu.flags == 0x03) {
1490 if ((--clu.size) > 0)
1493 clu.dir = CLUSTER_32(~0);
1495 if (FAT_read(sb, clu.dir, &(clu.dir)) == -1)
1496 return FFS_MEDIAERR;
1500 *(dir_entry->Name) = '\0';
1502 fid->rwoffset = (INT64) ++dentry;
1504 if (p_fs->dev_ejected)
1505 return FFS_MEDIAERR;
1510 INT32 ffsRemoveDir(struct inode *inode, FILE_ID_T *fid)
1513 CHAIN_T dir, clu_to_free;
1514 struct super_block *sb = inode->i_sb;
1515 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1517 dir.dir = fid->dir.dir;
1518 dir.size = fid->dir.size;
1519 dir.flags = fid->dir.flags;
1521 dentry = fid->entry;
1523 if (p_fs->vol_type != EXFAT) {
1524 if ((dir.dir != p_fs->root_dir) && (dentry < 2))
1525 return FFS_PERMISSIONERR;
1528 clu_to_free.dir = fid->start_clu;
1529 clu_to_free.size = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1;
1530 clu_to_free.flags = fid->flags;
1532 if (!is_dir_empty(sb, &clu_to_free))
1533 return FFS_FILEEXIST;
1535 fs_set_vol_flags(sb, VOL_DIRTY);
1537 remove_file(inode, &dir, dentry);
1539 p_fs->fs_func->free_cluster(sb, &clu_to_free, 1);
1541 #if (DELAYED_SYNC == 0)
1543 fs_set_vol_flags(sb, VOL_CLEAN);
1546 if (p_fs->dev_ejected)
1547 return FFS_MEDIAERR;
1554 if (sizeof(DENTRY_T) != DENTRY_SIZE) {
1555 return FFS_ALIGNMENTERR;
1558 if (sizeof(DOS_DENTRY_T) != DENTRY_SIZE) {
1559 return FFS_ALIGNMENTERR;
1562 if (sizeof(EXT_DENTRY_T) != DENTRY_SIZE) {
1563 return FFS_ALIGNMENTERR;
1566 if (sizeof(FILE_DENTRY_T) != DENTRY_SIZE) {
1567 return FFS_ALIGNMENTERR;
1570 if (sizeof(STRM_DENTRY_T) != DENTRY_SIZE) {
1571 return FFS_ALIGNMENTERR;
1574 if (sizeof(NAME_DENTRY_T) != DENTRY_SIZE) {
1575 return FFS_ALIGNMENTERR;
1578 if (sizeof(BMAP_DENTRY_T) != DENTRY_SIZE) {
1579 return FFS_ALIGNMENTERR;
1582 if (sizeof(CASE_DENTRY_T) != DENTRY_SIZE) {
1583 return FFS_ALIGNMENTERR;
1586 if (sizeof(VOLM_DENTRY_T) != DENTRY_SIZE) {
1587 return FFS_ALIGNMENTERR;
1593 INT32 fs_shutdown(void)
1598 void fs_set_vol_flags(struct super_block *sb, UINT32 new_flag)
1600 PBR_SECTOR_T *p_pbr;
1602 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1604 if (p_fs->vol_flag == new_flag)
1607 p_fs->vol_flag = new_flag;
1609 if (p_fs->vol_type == EXFAT) {
1610 if (p_fs->pbr_bh == NULL) {
1611 if (sector_read(sb, p_fs->PBR_sector, &(p_fs->pbr_bh), 1) != FFS_SUCCESS)
1615 p_pbr = (PBR_SECTOR_T *) p_fs->pbr_bh->b_data;
1616 p_bpb = (BPBEX_T *) p_pbr->bpb;
1617 SET16(p_bpb->vol_flags, (UINT16) new_flag);
1619 if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh)))
1620 sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1);
1622 sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0);
1626 void fs_sync(struct super_block *sb, INT32 do_sync)
1632 void fs_error(struct super_block *sb)
1634 struct exfat_mount_options *opts = &EXFAT_SB(sb)->options;
1636 if (opts->errors == EXFAT_ERRORS_PANIC)
1637 panic("EXFAT: fs panic from previous error\n");
1638 else if ((opts->errors == EXFAT_ERRORS_RO) && !(sb->s_flags & MS_RDONLY)) {
1639 sb->s_flags |= MS_RDONLY;
1640 printk(KERN_ERR "EXFAT: Filesystem has been set read-only\n");
1644 INT32 clear_cluster(struct super_block *sb, UINT32 clu)
1647 INT32 ret = FFS_SUCCESS;
1648 struct buffer_head *tmp_bh = NULL;
1649 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1650 BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
1652 if (clu == CLUSTER_32(0)) {
1653 s = p_fs->root_start_sector;
1654 n = p_fs->data_start_sector;
1656 s = START_SECTOR(clu);
1657 n = s + p_fs->sectors_per_clu;
1660 for ( ; s < n; s++) {
1661 if ((ret = sector_read(sb, s, &tmp_bh, 0)) != FFS_SUCCESS)
1664 MEMSET((INT8 *) tmp_bh->b_data, 0x0, p_bd->sector_size);
1665 if ((ret = sector_write(sb, s, tmp_bh, 0)) !=FFS_SUCCESS)
1673 INT32 fat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain)
1675 INT32 i, num_clusters = 0;
1676 UINT32 new_clu, last_clu = CLUSTER_32(~0), read_clu;
1677 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1679 new_clu = p_chain->dir;
1680 if (new_clu == CLUSTER_32(~0))
1681 new_clu = p_fs->clu_srch_ptr;
1682 else if (new_clu >= p_fs->num_clusters)
1687 p_chain->dir = CLUSTER_32(~0);
1689 for (i = 2; i < p_fs->num_clusters; i++) {
1690 if (FAT_read(sb, new_clu, &read_clu) != 0)
1693 if (read_clu == CLUSTER_32(0)) {
1694 FAT_write(sb, new_clu, CLUSTER_32(~0));
1697 if (p_chain->dir == CLUSTER_32(~0))
1698 p_chain->dir = new_clu;
1700 FAT_write(sb, last_clu, new_clu);
1704 if ((--num_alloc) == 0) {
1705 p_fs->clu_srch_ptr = new_clu;
1706 if (p_fs->used_clusters != (UINT32) ~0)
1707 p_fs->used_clusters += num_clusters;
1709 return(num_clusters);
1712 if ((++new_clu) >= p_fs->num_clusters)
1716 p_fs->clu_srch_ptr = new_clu;
1717 if (p_fs->used_clusters != (UINT32) ~0)
1718 p_fs->used_clusters += num_clusters;
1720 return(num_clusters);
1723 INT32 exfat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain)
1725 INT32 num_clusters = 0;
1726 UINT32 hint_clu, new_clu, last_clu = CLUSTER_32(~0);
1727 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1729 hint_clu = p_chain->dir;
1730 if (hint_clu == CLUSTER_32(~0)) {
1731 hint_clu = test_alloc_bitmap(sb, p_fs->clu_srch_ptr-2);
1732 if (hint_clu == CLUSTER_32(~0))
1734 } else if (hint_clu >= p_fs->num_clusters) {
1736 p_chain->flags = 0x01;
1741 p_chain->dir = CLUSTER_32(~0);
1743 while ((new_clu = test_alloc_bitmap(sb, hint_clu-2)) != CLUSTER_32(~0)) {
1744 if (new_clu != hint_clu) {
1745 if (p_chain->flags == 0x03) {
1746 exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters);
1747 p_chain->flags = 0x01;
1751 if (set_alloc_bitmap(sb, new_clu-2) != FFS_SUCCESS)
1756 if (p_chain->flags == 0x01)
1757 FAT_write(sb, new_clu, CLUSTER_32(~0));
1759 if (p_chain->dir == CLUSTER_32(~0)) {
1760 p_chain->dir = new_clu;
1762 if (p_chain->flags == 0x01)
1763 FAT_write(sb, last_clu, new_clu);
1767 if ((--num_alloc) == 0) {
1768 p_fs->clu_srch_ptr = hint_clu;
1769 if (p_fs->used_clusters != (UINT32) ~0)
1770 p_fs->used_clusters += num_clusters;
1772 p_chain->size += num_clusters;
1773 return(num_clusters);
1776 hint_clu = new_clu + 1;
1777 if (hint_clu >= p_fs->num_clusters) {
1780 if (p_chain->flags == 0x03) {
1781 exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters);
1782 p_chain->flags = 0x01;
1787 p_fs->clu_srch_ptr = hint_clu;
1788 if (p_fs->used_clusters != (UINT32) ~0)
1789 p_fs->used_clusters += num_clusters;
1791 p_chain->size += num_clusters;
1792 return(num_clusters);
1795 void fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse)
1797 INT32 num_clusters = 0;
1799 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1805 if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
1813 if (p_fs->dev_ejected)
1817 sector = START_SECTOR(clu);
1818 for (i = 0; i < p_fs->sectors_per_clu; i++) {
1819 buf_release(sb, sector+i);
1824 if (FAT_read(sb, clu, &clu) == -1)
1827 FAT_write(sb, prev, CLUSTER_32(0));
1830 } while (clu != CLUSTER_32(~0));
1832 if (p_fs->used_clusters != (UINT32) ~0)
1833 p_fs->used_clusters -= num_clusters;
1836 void exfat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse)
1838 INT32 num_clusters = 0;
1840 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1846 if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
1853 if (p_chain->flags == 0x03) {
1857 sector = START_SECTOR(clu);
1858 for (i = 0; i < p_fs->sectors_per_clu; i++) {
1859 buf_release(sb, sector+i);
1863 if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS)
1868 } while (num_clusters < p_chain->size);
1871 if (p_fs->dev_ejected)
1875 sector = START_SECTOR(clu);
1876 for (i = 0; i < p_fs->sectors_per_clu; i++) {
1877 buf_release(sb, sector+i);
1881 if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS)
1884 if (FAT_read(sb, clu, &clu) == -1)
1887 } while (clu != CLUSTER_32(~0));
1890 if (p_fs->used_clusters != (UINT32) ~0)
1891 p_fs->used_clusters -= num_clusters;
1894 UINT32 find_last_cluster(struct super_block *sb, CHAIN_T *p_chain)
1897 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1901 if (p_chain->flags == 0x03) {
1902 clu += p_chain->size - 1;
1904 while((FAT_read(sb, clu, &next) == 0) && (next != CLUSTER_32(~0))) {
1905 if (p_fs->dev_ejected)
1914 INT32 count_num_clusters(struct super_block *sb, CHAIN_T *p_chain)
1918 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1920 if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
1925 if (p_chain->flags == 0x03) {
1926 count = p_chain->size;
1928 for (i = 2; i < p_fs->num_clusters; i++) {
1930 if (FAT_read(sb, clu, &clu) != 0)
1932 if (clu == CLUSTER_32(~0))
1940 INT32 fat_count_used_clusters(struct super_block *sb)
1944 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1946 for (i = 2; i < p_fs->num_clusters; i++) {
1947 if (FAT_read(sb, i, &clu) != 0)
1949 if (clu != CLUSTER_32(0))
1956 INT32 exfat_count_used_clusters(struct super_block *sb)
1958 INT32 i, map_i, map_b, count = 0;
1960 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1961 BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
1965 for (i = 2; i < p_fs->num_clusters; i += 8) {
1966 k = *(((UINT8 *) p_fs->vol_amap[map_i]->b_data) + map_b);
1967 count += used_bit[k];
1969 if ((++map_b) >= p_bd->sector_size) {
1978 void exfat_chain_cont_cluster(struct super_block *sb, UINT32 chain, INT32 len)
1984 FAT_write(sb, chain, chain+1);
1988 FAT_write(sb, chain, CLUSTER_32(~0));
1991 INT32 load_alloc_bitmap(struct super_block *sb)
1995 UINT32 type, sector;
1998 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1999 BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
2001 clu.dir = p_fs->root_dir;
2004 while (clu.dir != CLUSTER_32(~0)) {
2005 if (p_fs->dev_ejected)
2008 for (i = 0; i < p_fs->dentries_per_clu; i++) {
2009 ep = (BMAP_DENTRY_T *) get_entry_in_dir(sb, &clu, i, NULL);
2011 return FFS_MEDIAERR;
2013 type = p_fs->fs_func->get_entry_type((DENTRY_T *) ep);
2015 if (type == TYPE_UNUSED)
2017 if (type != TYPE_BITMAP)
2020 if (ep->flags == 0x0) {
2021 p_fs->map_clu = GET32_A(ep->start_clu);
2022 map_size = (UINT32) GET64_A(ep->size);
2024 p_fs->map_sectors = ((map_size-1) >> p_bd->sector_size_bits) + 1;
2026 p_fs->vol_amap = (struct buffer_head **) MALLOC(sizeof(struct buffer_head *) * p_fs->map_sectors);
2027 if (p_fs->vol_amap == NULL)
2028 return FFS_MEMORYERR;
2030 sector = START_SECTOR(p_fs->map_clu);
2032 for (j = 0; j < p_fs->map_sectors; j++) {
2033 p_fs->vol_amap[j] = NULL;
2034 ret = sector_read(sb, sector+j, &(p_fs->vol_amap[j]), 1);
2035 if (ret != FFS_SUCCESS) {
2038 brelse(p_fs->vol_amap[i++]);
2040 FREE(p_fs->vol_amap);
2041 p_fs->vol_amap = NULL;
2046 p_fs->pbr_bh = NULL;
2051 if (FAT_read(sb, clu.dir, &(clu.dir)) != 0)
2052 return FFS_MEDIAERR;
2055 return FFS_FORMATERR;
2058 void free_alloc_bitmap(struct super_block *sb)
2061 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2063 brelse(p_fs->pbr_bh);
2065 for (i = 0; i < p_fs->map_sectors; i++) {
2066 __brelse(p_fs->vol_amap[i]);
2069 FREE(p_fs->vol_amap);
2070 p_fs->vol_amap = NULL;
2073 INT32 set_alloc_bitmap(struct super_block *sb, UINT32 clu)
2077 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2078 BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
2080 i = clu >> (p_bd->sector_size_bits + 3);
2081 b = clu & ((p_bd->sector_size << 3) - 1);
2083 sector = START_SECTOR(p_fs->map_clu) + i;
2085 Bitmap_set((UINT8 *) p_fs->vol_amap[i]->b_data, b);
2087 return (sector_write(sb, sector, p_fs->vol_amap[i], 0));
2090 INT32 clr_alloc_bitmap(struct super_block *sb, UINT32 clu)
2094 #if EXFAT_CONFIG_DISCARD
2095 struct exfat_sb_info *sbi = EXFAT_SB(sb);
2096 struct exfat_mount_options *opts = &sbi->options;
2099 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2100 BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
2102 i = clu >> (p_bd->sector_size_bits + 3);
2103 b = clu & ((p_bd->sector_size << 3) - 1);
2105 sector = START_SECTOR(p_fs->map_clu) + i;
2107 Bitmap_clear((UINT8 *) p_fs->vol_amap[i]->b_data, b);
2109 return (sector_write(sb, sector, p_fs->vol_amap[i], 0));
2111 #if EXFAT_CONFIG_DISCARD
2112 if (opts->discard) {
2113 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
2114 ret = sb_issue_discard(sb, START_SECTOR(clu), (1 << p_fs->sectors_per_clu_bits));
2116 ret = sb_issue_discard(sb, START_SECTOR(clu), (1 << p_fs->sectors_per_clu_bits), GFP_NOFS, 0);
2118 if (ret == EOPNOTSUPP) {
2119 printk(KERN_WARNING "discard not supported by device, disabling");
2126 UINT32 test_alloc_bitmap(struct super_block *sb, UINT32 clu)
2128 INT32 i, map_i, map_b;
2129 UINT32 clu_base, clu_free;
2131 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2132 BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
2134 clu_base = (clu & ~(0x7)) + 2;
2135 clu_mask = (1 << (clu - clu_base + 2)) - 1;
2137 map_i = clu >> (p_bd->sector_size_bits + 3);
2138 map_b = (clu >> 3) & p_bd->sector_size_mask;
2140 for (i = 2; i < p_fs->num_clusters; i += 8) {
2141 k = *(((UINT8 *) p_fs->vol_amap[map_i]->b_data) + map_b);
2147 clu_free = clu_base + free_bit[k];
2148 if (clu_free < p_fs->num_clusters)
2153 if (((++map_b) >= p_bd->sector_size) || (clu_base >= p_fs->num_clusters)) {
2154 if ((++map_i) >= p_fs->map_sectors) {
2162 return(CLUSTER_32(~0));
2165 void sync_alloc_bitmap(struct super_block *sb)
2168 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2170 if (p_fs->vol_amap == NULL)
2173 for (i = 0; i < p_fs->map_sectors; i++) {
2174 sync_dirty_buffer(p_fs->vol_amap[i]);
2178 INT32 __load_upcase_table(struct super_block *sb, UINT32 sector, UINT32 num_sectors, UINT32 utbl_checksum)
2180 INT32 i, ret = FFS_ERROR;
2182 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2183 BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
2184 struct buffer_head *tmp_bh = NULL;
2189 UINT16 **upcase_table;
2191 UINT32 checksum = 0;
2193 upcase_table = p_fs->vol_utbl = (UINT16 **) MALLOC(UTBL_COL_COUNT * sizeof(UINT16 *));
2194 if(upcase_table == NULL)
2195 return FFS_MEMORYERR;
2196 MEMSET(upcase_table, 0, UTBL_COL_COUNT * sizeof(UINT16 *));
2198 num_sectors += sector;
2200 while(sector < num_sectors) {
2201 ret = sector_read(sb, sector, &tmp_bh, 1);
2202 if (ret != FFS_SUCCESS) {
2203 PRINTK("sector read (0x%X)fail\n", sector);
2208 for(i = 0; i < p_bd->sector_size && index <= 0xFFFF; i += 2) {
2209 uni = GET16(((UINT8 *) tmp_bh->b_data)+i);
2211 checksum = ((checksum & 1) ? 0x80000000 : 0 ) + (checksum >> 1) + *(((UINT8 *) tmp_bh->b_data)+i);
2212 checksum = ((checksum & 1) ? 0x80000000 : 0 ) + (checksum >> 1) + *(((UINT8 *) tmp_bh->b_data)+(i+1));
2215 PRINTK("skip from 0x%X ", index);
2217 PRINTK("to 0x%X (amount of 0x%X)\n", index, uni);
2219 } else if(uni == index)
2221 else if(uni == 0xFFFF)
2224 UINT16 col_index = get_col_index(index);
2226 if(upcase_table[col_index]== NULL) {
2227 PRINTK("alloc = 0x%X\n", col_index);
2228 upcase_table[col_index] = (UINT16 *) MALLOC(UTBL_ROW_COUNT * sizeof(UINT16));
2229 if(upcase_table[col_index] == NULL) {
2230 ret = FFS_MEMORYERR;
2234 for(j = 0 ; j < UTBL_ROW_COUNT ; j++)
2235 upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j;
2238 upcase_table[col_index][get_row_index(index)] = uni;
2243 if(index >= 0xFFFF && utbl_checksum == checksum) {
2252 free_upcase_table(sb);
2256 INT32 __load_default_upcase_table(struct super_block *sb)
2258 INT32 i, ret = FFS_ERROR;
2260 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2265 UINT16 **upcase_table;
2267 upcase_table = p_fs->vol_utbl = (UINT16 **) MALLOC(UTBL_COL_COUNT * sizeof(UINT16 *));
2268 if(upcase_table == NULL)
2269 return FFS_MEMORYERR;
2270 MEMSET(upcase_table, 0, UTBL_COL_COUNT * sizeof(UINT16 *));
2272 for(i = 0; index <= 0xFFFF && i < NUM_UPCASE*2; i += 2) {
2273 uni = GET16(uni_upcase + i);
2275 PRINTK("skip from 0x%X ", index);
2277 PRINTK("to 0x%X (amount of 0x%X)\n", index, uni);
2279 } else if(uni == index)
2281 else if(uni == 0xFFFF)
2284 UINT16 col_index = get_col_index(index);
2286 if(upcase_table[col_index]== NULL) {
2287 PRINTK("alloc = 0x%X\n", col_index);
2288 upcase_table[col_index] = (UINT16 *) MALLOC(UTBL_ROW_COUNT * sizeof(UINT16));
2289 if(upcase_table[col_index] == NULL) {
2290 ret = FFS_MEMORYERR;
2294 for(j = 0 ; j < UTBL_ROW_COUNT ; j++)
2295 upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j;
2298 upcase_table[col_index][get_row_index(index)] = uni;
2307 free_upcase_table(sb);
2311 INT32 load_upcase_table(struct super_block *sb)
2314 UINT32 tbl_clu, tbl_size;
2315 UINT32 type, sector, num_sectors;
2318 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2319 BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
2321 clu.dir = p_fs->root_dir;
2324 if (p_fs->dev_ejected)
2325 return FFS_MEDIAERR;
2327 while (clu.dir != CLUSTER_32(~0)) {
2328 for (i = 0; i < p_fs->dentries_per_clu; i++) {
2329 ep = (CASE_DENTRY_T *) get_entry_in_dir(sb, &clu, i, NULL);
2331 return FFS_MEDIAERR;
2333 type = p_fs->fs_func->get_entry_type((DENTRY_T *) ep);
2335 if (type == TYPE_UNUSED)
2337 if (type != TYPE_UPCASE)
2340 tbl_clu = GET32_A(ep->start_clu);
2341 tbl_size = (UINT32) GET64_A(ep->size);
2343 sector = START_SECTOR(tbl_clu);
2344 num_sectors = ((tbl_size-1) >> p_bd->sector_size_bits) + 1;
2345 if(__load_upcase_table(sb, sector, num_sectors, GET32_A(ep->checksum)) != FFS_SUCCESS)
2350 if (FAT_read(sb, clu.dir, &(clu.dir)) != 0)
2351 return FFS_MEDIAERR;
2353 return __load_default_upcase_table(sb);
2356 void free_upcase_table(struct super_block *sb)
2359 FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2360 UINT16 **upcase_table;
2362 upcase_table = p_fs->vol_utbl;
2363 for(i = 0 ; i < UTBL_COL_COUNT ; i ++)
2364 FREE(upcase_table[i]);
2366 FREE(p_fs->vol_utbl);
2368 p_fs->vol_utbl = NULL;
2371 UINT32 fat_get_entry_type(DENTRY_T *p_entry)
2373 DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2375 if (*(ep->name) == 0x0)
2378 else if (*(ep->name) == 0xE5)
2379 return TYPE_DELETED;
2381 else if (ep->attr == ATTR_EXTEND)
2384 else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_VOLUME)
2387 else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_SUBDIR)
2393 UINT32 exfat_get_entry_type(DENTRY_T *p_entry)
2395 FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
2397 if (ep->type == 0x0) {
2399 } else if (ep->type < 0x80) {
2400 return TYPE_DELETED;
2401 } else if (ep->type == 0x80) {
2402 return TYPE_INVALID;
2403 } else if (ep->type < 0xA0) {
2404 if (ep->type == 0x81) {
2406 } else if (ep->type == 0x82) {
2408 } else if (ep->type == 0x83) {
2410 } else if (ep->type == 0x85) {
2411 if (GET16_A(ep->attr) & ATTR_SUBDIR)
2416 return TYPE_CRITICAL_PRI;
2417 } else if (ep->type < 0xC0) {
2418 if (ep->type == 0xA0) {
2420 } else if (ep->type == 0xA1) {
2421 return TYPE_PADDING;
2422 } else if (ep->type == 0xA2) {
2425 return TYPE_BENIGN_PRI;
2426 } else if (ep->type < 0xE0) {
2427 if (ep->type == 0xC0) {
2429 } else if (ep->type == 0xC1) {
2431 } else if (ep->type == 0xC2) {
2434 return TYPE_CRITICAL_SEC;
2437 return TYPE_BENIGN_SEC;
2440 void fat_set_entry_type(DENTRY_T *p_entry, UINT32 type)
2442 DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2444 if (type == TYPE_UNUSED)
2447 else if (type == TYPE_DELETED)
2450 else if (type == TYPE_EXTEND)
2451 ep->attr = ATTR_EXTEND;
2453 else if (type == TYPE_DIR)
2454 ep->attr = ATTR_SUBDIR;
2456 else if (type == TYPE_FILE)
2457 ep->attr = ATTR_ARCHIVE;
2459 else if (type == TYPE_SYMLINK)
2460 ep->attr = ATTR_ARCHIVE | ATTR_SYMLINK;
2463 void exfat_set_entry_type(DENTRY_T *p_entry, UINT32 type)
2465 FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
2467 if (type == TYPE_UNUSED) {
2469 } else if (type == TYPE_DELETED) {
2471 } else if (type == TYPE_STREAM) {
2473 } else if (type == TYPE_EXTEND) {
2475 } else if (type == TYPE_BITMAP) {
2477 } else if (type == TYPE_UPCASE) {
2479 } else if (type == TYPE_VOLUME) {
2481 } else if (type == TYPE_DIR) {
2483 SET16_A(ep->attr, ATTR_SUBDIR);
2484 } else if (type == TYPE_FILE) {
2486 SET16_A(ep->attr, ATTR_ARCHIVE);
2487 } else if (type == TYPE_SYMLINK) {
2489 SET16_A(ep->attr, ATTR_ARCHIVE | ATTR_SYMLINK);
2493 UINT32 fat_get_entry_attr(DENTRY_T *p_entry)
2495 DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2496 return((UINT32) ep->attr);
2499 UINT32 exfat_get_entry_attr(DENTRY_T *p_entry)
2501 FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
2502 return((UINT32) GET16_A(ep->attr));
2505 void fat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr)
2507 DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2508 ep->attr = (UINT8) attr;
2511 void exfat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr)
2513 FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
2514 SET16_A(ep->attr, (UINT16) attr);
2517 UINT8 fat_get_entry_flag(DENTRY_T *p_entry)
2522 UINT8 exfat_get_entry_flag(DENTRY_T *p_entry)
2524 STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
2528 void fat_set_entry_flag(DENTRY_T *p_entry, UINT8 flags)
2532 void exfat_set_entry_flag(DENTRY_T *p_entry, UINT8 flags)
2534 STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
2538 UINT32 fat_get_entry_clu0(DENTRY_T *p_entry)
2540 DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2541 return((GET32_A(ep->start_clu_hi) << 16) | GET16_A(ep->start_clu_lo));
2544 UINT32 exfat_get_entry_clu0(DENTRY_T *p_entry)
2546 STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
2547 return(GET32_A(ep->start_clu));
2550 void fat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu)
2552 DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2553 SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu));
2554 SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16));
2557 void exfat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu)
2559 STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
2560 SET32_A(ep->start_clu, start_clu);
2563 UINT64 fat_get_entry_size(DENTRY_T *p_entry)
2565 DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2566 return((UINT64) GET32_A(ep->size));
2569 UINT64 exfat_get_entry_size(DENTRY_T *p_entry)
2571 STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
2572 return(GET64_A(ep->valid_size));
2575 void fat_set_entry_size(DENTRY_T *p_entry, UINT64 size)
2577 DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2578 SET32_A(ep->size, (UINT32) size);
2581 void exfat_set_entry_size(DENTRY_T *p_entry, UINT64 size)
2583 STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
2584 SET64_A(ep->valid_size, size);
2585 SET64_A(ep->size, size);
2588 void fat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode)
2590 UINT16 t = 0x00, d = 0x21;
2591 DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2595 t = GET16_A(ep->create_time);
2596 d = GET16_A(ep->create_date);
2599 t = GET16_A(ep->modify_time);
2600 d = GET16_A(ep->modify_date);
2604 tp->sec = (t & 0x001F) << 1;
2605 tp->min = (t >> 5) & 0x003F;
2606 tp->hour = (t >> 11);
2607 tp->day = (d & 0x001F);
2608 tp->mon = (d >> 5) & 0x000F;
2609 tp->year = (d >> 9);
2612 void exfat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode)
2614 UINT16 t = 0x00, d = 0x21;
2615 FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
2619 t = GET16_A(ep->create_time);
2620 d = GET16_A(ep->create_date);
2623 t = GET16_A(ep->modify_time);
2624 d = GET16_A(ep->modify_date);
2627 t = GET16_A(ep->access_time);
2628 d = GET16_A(ep->access_date);
2632 tp->sec = (t & 0x001F) << 1;
2633 tp->min = (t >> 5) & 0x003F;
2634 tp->hour = (t >> 11);
2635 tp->day = (d & 0x001F);
2636 tp->mon = (d >> 5) & 0x000F;
2637 tp->year = (d >> 9);
2640 void fat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode)
2643 DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2645 t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1);
2646 d = (tp->year << 9) | (tp->mon << 5) | tp->day;
2650 SET16_A(ep->create_time, t);
2651 SET16_A(ep->create_date, d);
2654 SET16_A(ep->modify_time, t);
2655 SET16_A(ep->modify_date, d);
2660 void exfat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode)
2663 FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
2665 t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1);
2666 d = (tp->year << 9) | (tp->mon << 5) | tp->day;
2670 SET16_A(ep->create_time, t);
2671 SET16_A(ep->create_date, d);
2674 SET16_A(ep->modify_time, t);
2675 SET16_A(ep->modify_date, d);
2678 SET16_A(ep->access_time, t);
2679 SET16_A(ep->access_date, d);
2684 INT32 fat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type,
2685 UINT32 start_clu, UINT64 size)
2688 DOS_DENTRY_T *dos_ep;
2690 dos_ep = (DOS_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or);
2692 return FFS_MEDIAERR;
2694 init_dos_entry(dos_ep, type, start_clu);
2695 buf_modify(sb, sector);
2700 INT32 exfat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type,
2701 UINT32 start_clu, UINT64 size)
2705 FILE_DENTRY_T *file_ep;
2706 STRM_DENTRY_T *strm_ep;
2708 flags = (type == TYPE_FILE) ? 0x01 : 0x03;
2710 file_ep = (FILE_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or);
2712 return FFS_MEDIAERR;
2714 strm_ep = (STRM_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry+1, §or);
2716 return FFS_MEDIAERR;
2718 init_file_entry(file_ep, type);
2719 buf_modify(sb, sector);
2721 init_strm_entry(strm_ep, flags, start_clu, size);
2722 buf_modify(sb, sector);
2727 INT32 fat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries,
2728 UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname)
2733 UINT16 *uniname = p_uniname->name;
2734 DOS_DENTRY_T *dos_ep;
2735 EXT_DENTRY_T *ext_ep;
2737 dos_ep = (DOS_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or);
2739 return FFS_MEDIAERR;
2741 dos_ep->lcase = p_dosname->name_case;
2742 MEMCPY(dos_ep->name, p_dosname->name, DOS_NAME_LENGTH);
2743 buf_modify(sb, sector);
2745 if ((--num_entries) > 0) {
2746 chksum = calc_checksum_1byte((void *) dos_ep->name, DOS_NAME_LENGTH, 0);
2748 for (i = 1; i < num_entries; i++) {
2749 ext_ep = (EXT_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry-i, §or);
2751 return FFS_MEDIAERR;
2753 init_ext_entry(ext_ep, i, chksum, uniname);
2754 buf_modify(sb, sector);
2758 ext_ep = (EXT_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry-i, §or);
2760 return FFS_MEDIAERR;
2762 init_ext_entry(ext_ep, i+0x40, chksum, uniname);
2763 buf_modify(sb, sector);
2769 INT32 exfat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries,
2770 UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname)
2774 UINT16 *uniname = p_uniname->name;
2775 FILE_DENTRY_T *file_ep;
2776 STRM_DENTRY_T *strm_ep;
2777 NAME_DENTRY_T *name_ep;
2779 file_ep = (FILE_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or);
2781 return FFS_MEDIAERR;
2783 file_ep->num_ext = (UINT8)(num_entries - 1);
2784 buf_modify(sb, sector);
2786 strm_ep = (STRM_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry+1, §or);
2788 return FFS_MEDIAERR;
2790 strm_ep->name_len = p_uniname->name_len;
2791 SET16_A(strm_ep->name_hash, p_uniname->name_hash);
2792 buf_modify(sb, sector);
2794 for (i = 2; i < num_entries; i++) {
2795 name_ep = (NAME_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry+i, §or);
2797 return FFS_MEDIAERR;
2799 init_name_entry(name_ep, uniname);
2800 buf_modify(sb, sector);
2804 update_dir_checksum(sb, p_dir, entry);