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 /************************************************************************/
30 /* PROJECT : exFAT & FAT12/16/32 File System */
32 /* PURPOSE : exFAT File Manager */
34 /*----------------------------------------------------------------------*/
37 /*----------------------------------------------------------------------*/
38 /* REVISION HISTORY (Ver 0.9) */
40 /* - 2010.11.15 [Joosun Hahn] : first writing */
42 /************************************************************************/
44 #include <linux/version.h>
46 #include "exfat_config.h"
47 #include "exfat_global.h"
48 #include "exfat_data.h"
49 #include "exfat_oal.h"
51 #include "exfat_blkdev.h"
52 #include "exfat_cache.h"
53 #include "exfat_nls.h"
54 #include "exfat_api.h"
55 #include "exfat_super.h"
58 #include <linux/blkdev.h>
60 /*----------------------------------------------------------------------*/
61 /* Constant & Macro Definitions */
62 /*----------------------------------------------------------------------*/
64 #define THERE_IS_MBR 0 /* if there is no MBR (e.g. memory card),
65 set this macro to 0 */
67 #if (THERE_IS_MBR == 1)
68 #include "exfat_part.h"
71 #define DELAYED_SYNC 0
73 #define ELAPSED_TIME 0
75 #if (ELAPSED_TIME == 1)
76 #include <linux/time.h>
78 static UINT32 __t1
, __t2
;
79 static UINT32
get_current_msec(void)
83 return (UINT32
)(tm
.tv_sec
*1000000 + tm
.tv_usec
);
85 #define TIME_START() do {__t1 = get_current_msec(); } while (0)
86 #define TIME_END() do {__t2 = get_current_msec(); } while (0)
87 #define PRINT_TIME(n) do {printk("[EXFAT] Elapsed time %d = %d (usec)\n", n, (__t2 - __t1)); } while (0)
94 static void __set_sb_dirty(struct super_block
*sb
)
96 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
99 struct exfat_sb_info
*sbi
= EXFAT_SB(sb
);
104 /*----------------------------------------------------------------------*/
105 /* Global Variable Definitions */
106 /*----------------------------------------------------------------------*/
108 extern UINT8 uni_upcase
[];
110 /*----------------------------------------------------------------------*/
111 /* Local Variable Definitions */
112 /*----------------------------------------------------------------------*/
114 static UINT8 name_buf
[MAX_PATH_LENGTH
*MAX_CHARSET_SIZE
];
116 static INT8
*reserved_names
[] = {
117 "AUX ", "CON ", "NUL ", "PRN ",
118 "COM1 ", "COM2 ", "COM3 ", "COM4 ",
119 "COM5 ", "COM6 ", "COM7 ", "COM8 ", "COM9 ",
120 "LPT1 ", "LPT2 ", "LPT3 ", "LPT4 ",
121 "LPT5 ", "LPT6 ", "LPT7 ", "LPT8 ", "LPT9 ",
125 static UINT8 free_bit
[] = {
126 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 0 ~ 19 */
127 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, /* 20 ~ 39 */
128 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 40 ~ 59 */
129 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 60 ~ 79 */
130 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, /* 80 ~ 99 */
131 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, /* 100 ~ 119 */
132 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 120 ~ 139 */
133 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, /* 140 ~ 159 */
134 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 160 ~ 179 */
135 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, /* 180 ~ 199 */
136 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 200 ~ 219 */
137 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 220 ~ 239 */
138 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 240 ~ 254 */
141 static UINT8 used_bit
[] = {
142 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, /* 0 ~ 19 */
143 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, /* 20 ~ 39 */
144 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, /* 40 ~ 59 */
145 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 60 ~ 79 */
146 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, /* 80 ~ 99 */
147 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, /* 100 ~ 119 */
148 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, /* 120 ~ 139 */
149 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 140 ~ 159 */
150 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, /* 160 ~ 179 */
151 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, /* 180 ~ 199 */
152 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, /* 200 ~ 219 */
153 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 220 ~ 239 */
154 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /* 240 ~ 255 */
157 /*======================================================================*/
158 /* Global Function Definitions */
159 /*======================================================================*/
161 /* ffsInit : roll back to the initial state of the file system */
175 } /* end of ffsInit */
177 /* ffsShutdown : make free all memory-alloced global buffers */
178 INT32
ffsShutdown(void)
185 ret
= bdev_shutdown();
190 } /* end of ffsShutdown */
192 /* ffsMountVol : mount the file system volume */
193 INT32
ffsMountVol(struct super_block
*sb
, INT32 drv
)
196 #if (THERE_IS_MBR == 1)
201 struct buffer_head
*tmp_bh
= NULL
;
202 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
203 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
205 PRINTK("[EXFAT] trying to mount...\n");
208 p_fs
->dev_ejected
= FALSE
;
210 /* open the block device */
214 if (p_bd
->sector_size
< sb
->s_blocksize
)
216 if (p_bd
->sector_size
> sb
->s_blocksize
)
217 sb_set_blocksize(sb
, p_bd
->sector_size
);
220 if (sector_read(sb
, 0, &tmp_bh
, 1) != FFS_SUCCESS
)
223 #if (THERE_IS_MBR == 1)
224 if (buf
[0] != 0xEB) {
226 p_mbr
= (MBR_SECTOR_T
*) tmp_bh
->b_data
;
228 /* check the validity of MBR */
229 if (GET16_A(p_mbr
->signature
) != MBR_SIGNATURE
) {
232 return FFS_FORMATERR
;
235 p_pte
= (PART_ENTRY_T
*) p_mbr
->partition
+ 0;
236 p_fs
->PBR_sector
= GET32(p_pte
->start_sector
);
237 p_fs
->num_sectors
= GET32(p_pte
->num_sectors
);
239 if (p_fs
->num_sectors
== 0) {
246 if (sector_read(sb
, p_fs
->PBR_sector
, &tmp_bh
, 1) != FFS_SUCCESS
) {
253 p_fs
->PBR_sector
= 0;
254 #if (THERE_IS_MBR == 1)
258 p_pbr
= (PBR_SECTOR_T
*) tmp_bh
->b_data
;
260 /* check the validity of PBR */
261 if (GET16_A(p_pbr
->signature
) != PBR_SIGNATURE
) {
264 return FFS_FORMATERR
;
268 for (i
= 0; i
< 53; i
++)
273 if (GET16(p_pbr
->bpb
+11)) /* num_fat_sectors */
274 ret
= fat16_mount(sb
, p_pbr
);
276 ret
= fat32_mount(sb
, p_pbr
);
278 ret
= exfat_mount(sb
, p_pbr
);
288 if (p_fs
->vol_type
== EXFAT
) {
289 ret
= load_alloc_bitmap(sb
);
294 ret
= load_upcase_table(sb
);
296 free_alloc_bitmap(sb
);
302 if (p_fs
->dev_ejected
) {
303 if (p_fs
->vol_type
== EXFAT
) {
304 free_upcase_table(sb
);
305 free_alloc_bitmap(sb
);
311 PRINTK("[EXFAT] mounted successfully\n");
313 } /* end of ffsMountVol */
315 /* ffsUmountVol : umount the file system volume */
316 INT32
ffsUmountVol(struct super_block
*sb
)
318 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
320 PRINTK("[EXFAT] trying to unmount...\n");
323 fs_set_vol_flags(sb
, VOL_CLEAN
);
325 if (p_fs
->vol_type
== EXFAT
) {
326 free_upcase_table(sb
);
327 free_alloc_bitmap(sb
);
333 /* close the block device */
336 if (p_fs
->dev_ejected
) {
337 PRINTK( "[EXFAT] unmounted with media errors. "
338 "device's already ejected.\n");
342 PRINTK("[EXFAT] unmounted successfully\n");
344 } /* end of ffsUmountVol */
346 /* ffsGetVolInfo : get the information of a file system volume */
347 INT32
ffsGetVolInfo(struct super_block
*sb
, VOL_INFO_T
*info
)
349 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
351 if (p_fs
->used_clusters
== (UINT32
) ~0)
352 p_fs
->used_clusters
= p_fs
->fs_func
->count_used_clusters(sb
);
354 info
->FatType
= p_fs
->vol_type
;
355 info
->ClusterSize
= p_fs
->cluster_size
;
356 info
->NumClusters
= p_fs
->num_clusters
- 2; /* clu 0 & 1 */
357 info
->UsedClusters
= p_fs
->used_clusters
;
358 info
->FreeClusters
= info
->NumClusters
- info
->UsedClusters
;
360 if (p_fs
->dev_ejected
)
364 } /* end of ffsGetVolInfo */
366 /* ffsSyncVol : synchronize all file system volumes */
367 INT32
ffsSyncVol(struct super_block
*sb
, INT32 do_sync
)
369 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
371 /* synchronize the file system */
372 fs_sync(sb
, do_sync
);
373 fs_set_vol_flags(sb
, VOL_CLEAN
);
375 if (p_fs
->dev_ejected
)
379 } /* end of ffsSyncVol */
381 /*----------------------------------------------------------------------*/
382 /* File Operation Functions */
383 /*----------------------------------------------------------------------*/
385 /* ffsLookupFile : lookup a file */
386 INT32
ffsLookupFile(struct inode
*inode
, UINT8
*path
, FILE_ID_T
*fid
)
388 INT32 ret
, dentry
, num_entries
;
393 ENTRY_SET_CACHE_T
*es
=NULL
;
394 struct super_block
*sb
= inode
->i_sb
;
395 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
397 PRINTK("ffsLookupFile entered\n");
399 /* check the validity of directory name in the given pathname */
400 ret
= resolve_path(inode
, path
, &dir
, &uni_name
);
404 ret
= get_num_entries_and_dos_name(sb
, &dir
, &uni_name
, &num_entries
, &dos_name
);
408 /* search the file name for directories */
409 dentry
= p_fs
->fs_func
->find_dir_entry(sb
, &dir
, &uni_name
, num_entries
, &dos_name
, TYPE_ALL
);
413 fid
->dir
.dir
= dir
.dir
;
414 fid
->dir
.size
= dir
.size
;
415 fid
->dir
.flags
= dir
.flags
;
419 fid
->type
= TYPE_DIR
;
421 fid
->hint_last_off
= -1;
423 fid
->attr
= ATTR_SUBDIR
;
426 fid
->start_clu
= p_fs
->root_dir
;
428 if (p_fs
->vol_type
== EXFAT
) {
429 es
= get_entry_set_in_dir(sb
, &dir
, dentry
, ES_2_ENTRIES
, &ep
);
434 ep
= get_entry_in_dir(sb
, &dir
, dentry
, NULL
);
440 fid
->type
= p_fs
->fs_func
->get_entry_type(ep
);
442 fid
->hint_last_off
= -1;
443 fid
->attr
= p_fs
->fs_func
->get_entry_attr(ep
);
445 fid
->size
= p_fs
->fs_func
->get_entry_size(ep2
);
446 if ((fid
->type
== TYPE_FILE
) && (fid
->size
== 0)) {
447 fid
->flags
= (p_fs
->vol_type
== EXFAT
) ? 0x03 : 0x01;
448 fid
->start_clu
= CLUSTER_32(~0);
450 fid
->flags
= p_fs
->fs_func
->get_entry_flag(ep2
);
451 fid
->start_clu
= p_fs
->fs_func
->get_entry_clu0(ep2
);
454 if (p_fs
->vol_type
== EXFAT
)
455 release_entry_set(es
);
458 if (p_fs
->dev_ejected
)
461 PRINTK("ffsLookupFile exited successfully\n");
464 } /* end of ffsLookupFile */
466 /* ffsCreateFile : create a file */
467 INT32
ffsCreateFile(struct inode
*inode
, UINT8
*path
, UINT8 mode
, FILE_ID_T
*fid
)
469 INT32 ret
/*, dentry*/;
472 struct super_block
*sb
= inode
->i_sb
;
473 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
475 /* check the validity of directory name in the given pathname */
476 ret
= resolve_path(inode
, path
, &dir
, &uni_name
);
480 fs_set_vol_flags(sb
, VOL_DIRTY
);
482 /* create a new file */
483 ret
= create_file(inode
, &dir
, &uni_name
, mode
, fid
);
485 #if (DELAYED_SYNC == 0)
487 fs_set_vol_flags(sb
, VOL_CLEAN
);
490 if (p_fs
->dev_ejected
)
494 } /* end of ffsCreateFile */
496 /* ffsReadFile : read data from a opened file */
497 INT32
ffsReadFile(struct inode
*inode
, FILE_ID_T
*fid
, void *buffer
, UINT64 count
, UINT64
*rcount
)
499 INT32 offset
, sec_offset
, clu_offset
;
500 UINT32 clu
, LogSector
;
501 UINT64 oneblkread
, read_bytes
;
502 struct buffer_head
*tmp_bh
= NULL
;
503 struct super_block
*sb
= inode
->i_sb
;
504 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
505 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
507 /* check if the given file ID is opened */
508 if (fid
->type
!= TYPE_FILE
)
509 return FFS_PERMISSIONERR
;
511 if (fid
->rwoffset
> fid
->size
)
512 fid
->rwoffset
= fid
->size
;
514 if (count
> (fid
->size
- fid
->rwoffset
))
515 count
= fid
->size
- fid
->rwoffset
;
526 clu_offset
= (INT32
)(fid
->rwoffset
>> p_fs
->cluster_size_bits
);
527 clu
= fid
->start_clu
;
529 if (fid
->flags
== 0x03) {
532 /* hint information */
533 if ((clu_offset
> 0) && (fid
->hint_last_off
> 0) &&
534 (clu_offset
>= fid
->hint_last_off
)) {
535 clu_offset
-= fid
->hint_last_off
;
536 clu
= fid
->hint_last_clu
;
539 while (clu_offset
> 0) {
540 /* clu = FAT_read(sb, clu); */
541 if (FAT_read(sb
, clu
, &clu
) == -1)
548 /* hint information */
549 fid
->hint_last_off
= (INT32
)(fid
->rwoffset
>> p_fs
->cluster_size_bits
);
550 fid
->hint_last_clu
= clu
;
552 offset
= (INT32
)(fid
->rwoffset
& (p_fs
->cluster_size
-1)); /* byte offset in cluster */
553 sec_offset
= offset
>> p_bd
->sector_size_bits
; /* sector offset in cluster */
554 offset
&= p_bd
->sector_size_mask
; /* byte offset in sector */
556 LogSector
= START_SECTOR(clu
) + sec_offset
;
558 oneblkread
= (UINT64
)(p_bd
->sector_size
- offset
);
559 if (oneblkread
> count
)
562 if ((offset
== 0) && (oneblkread
== p_bd
->sector_size
)) {
563 if (sector_read(sb
, LogSector
, &tmp_bh
, 1) != FFS_SUCCESS
)
565 MEMCPY(((INT8
*) buffer
)+read_bytes
, ((INT8
*) tmp_bh
->b_data
), (INT32
) oneblkread
);
567 if (sector_read(sb
, LogSector
, &tmp_bh
, 1) != FFS_SUCCESS
)
569 MEMCPY(((INT8
*) buffer
)+read_bytes
, ((INT8
*) tmp_bh
->b_data
)+offset
, (INT32
) oneblkread
);
572 read_bytes
+= oneblkread
;
573 fid
->rwoffset
+= oneblkread
;
578 /* set the size of read bytes */
580 *rcount
= read_bytes
;
582 if (p_fs
->dev_ejected
)
586 } /* end of ffsReadFile */
588 /* ffsWriteFile : write data into a opened file */
589 INT32
ffsWriteFile(struct inode
*inode
, FILE_ID_T
*fid
, void *buffer
, UINT64 count
, UINT64
*wcount
)
591 INT32 modified
= FALSE
, offset
, sec_offset
, clu_offset
;
592 INT32 num_clusters
, num_alloc
, num_alloced
= (INT32
) ~0;
593 UINT32 clu
, last_clu
, LogSector
, sector
= 0;
594 UINT64 oneblkwrite
, write_bytes
;
598 ENTRY_SET_CACHE_T
*es
= NULL
;
599 struct buffer_head
*tmp_bh
= NULL
;
600 struct super_block
*sb
= inode
->i_sb
;
601 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
602 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
604 /* check if the given file ID is opened */
605 if (fid
->type
!= TYPE_FILE
)
606 return FFS_PERMISSIONERR
;
608 if (fid
->rwoffset
> fid
->size
)
609 fid
->rwoffset
= fid
->size
;
617 fs_set_vol_flags(sb
, VOL_DIRTY
);
622 num_clusters
= (INT32
)((fid
->size
-1) >> p_fs
->cluster_size_bits
) + 1;
627 clu_offset
= (INT32
)(fid
->rwoffset
>> p_fs
->cluster_size_bits
);
628 clu
= last_clu
= fid
->start_clu
;
630 if (fid
->flags
== 0x03) {
631 if ((clu_offset
> 0) && (clu
!= CLUSTER_32(~0))) {
632 last_clu
+= clu_offset
- 1;
634 if (clu_offset
== num_clusters
)
635 clu
= CLUSTER_32(~0);
640 /* hint information */
641 if ((clu_offset
> 0) && (fid
->hint_last_off
> 0) &&
642 (clu_offset
>= fid
->hint_last_off
)) {
643 clu_offset
-= fid
->hint_last_off
;
644 clu
= fid
->hint_last_clu
;
647 while ((clu_offset
> 0) && (clu
!= CLUSTER_32(~0))) {
649 /* clu = FAT_read(sb, clu); */
650 if (FAT_read(sb
, clu
, &clu
) == -1)
657 if (clu
== CLUSTER_32(~0)) {
658 num_alloc
= (INT32
)((count
-1) >> p_fs
->cluster_size_bits
) + 1;
659 new_clu
.dir
= (last_clu
== CLUSTER_32(~0)) ? CLUSTER_32(~0) : last_clu
+1;
661 new_clu
.flags
= fid
->flags
;
663 /* (1) allocate a chain of clusters */
664 num_alloced
= p_fs
->fs_func
->alloc_cluster(sb
, num_alloc
, &new_clu
);
665 if (num_alloced
== 0)
668 /* (2) append to the FAT chain */
669 if (last_clu
== CLUSTER_32(~0)) {
670 if (new_clu
.flags
== 0x01)
672 fid
->start_clu
= new_clu
.dir
;
675 if (new_clu
.flags
!= fid
->flags
) {
676 exfat_chain_cont_cluster(sb
, fid
->start_clu
, num_clusters
);
680 if (new_clu
.flags
== 0x01)
681 FAT_write(sb
, last_clu
, new_clu
.dir
);
684 num_clusters
+= num_alloced
;
688 /* hint information */
689 fid
->hint_last_off
= (INT32
)(fid
->rwoffset
>> p_fs
->cluster_size_bits
);
690 fid
->hint_last_clu
= clu
;
692 offset
= (INT32
)(fid
->rwoffset
& (p_fs
->cluster_size
-1)); /* byte offset in cluster */
693 sec_offset
= offset
>> p_bd
->sector_size_bits
; /* sector offset in cluster */
694 offset
&= p_bd
->sector_size_mask
; /* byte offset in sector */
696 LogSector
= START_SECTOR(clu
) + sec_offset
;
698 oneblkwrite
= (UINT64
)(p_bd
->sector_size
- offset
);
699 if (oneblkwrite
> count
)
702 if ((offset
== 0) && (oneblkwrite
== p_bd
->sector_size
)) {
703 if (sector_read(sb
, LogSector
, &tmp_bh
, 0) != FFS_SUCCESS
)
705 MEMCPY(((INT8
*) tmp_bh
->b_data
), ((INT8
*) buffer
)+write_bytes
, (INT32
) oneblkwrite
);
706 if (sector_write(sb
, LogSector
, tmp_bh
, 0) != FFS_SUCCESS
) {
711 if ((offset
> 0) || ((fid
->rwoffset
+oneblkwrite
) < fid
->size
)) {
712 if (sector_read(sb
, LogSector
, &tmp_bh
, 1) != FFS_SUCCESS
)
715 if (sector_read(sb
, LogSector
, &tmp_bh
, 0) != FFS_SUCCESS
)
719 MEMCPY(((INT8
*) tmp_bh
->b_data
)+offset
, ((INT8
*) buffer
)+write_bytes
, (INT32
) oneblkwrite
);
720 if (sector_write(sb
, LogSector
, tmp_bh
, 0) != FFS_SUCCESS
) {
726 count
-= oneblkwrite
;
727 write_bytes
+= oneblkwrite
;
728 fid
->rwoffset
+= oneblkwrite
;
730 fid
->attr
|= ATTR_ARCHIVE
;
732 if (fid
->size
< fid
->rwoffset
) {
733 fid
->size
= fid
->rwoffset
;
740 /* (3) update the direcoty entry */
741 if (p_fs
->vol_type
== EXFAT
) {
742 es
= get_entry_set_in_dir(sb
, &(fid
->dir
), fid
->entry
, ES_ALL_ENTRIES
, &ep
);
747 ep
= get_entry_in_dir(sb
, &(fid
->dir
), fid
->entry
, §or
);
753 p_fs
->fs_func
->set_entry_time(ep
, tm_current(&tm
), TM_MODIFY
);
754 p_fs
->fs_func
->set_entry_attr(ep
, fid
->attr
);
756 if (p_fs
->vol_type
!= EXFAT
)
757 buf_modify(sb
, sector
);
760 if (p_fs
->fs_func
->get_entry_flag(ep2
) != fid
->flags
)
761 p_fs
->fs_func
->set_entry_flag(ep2
, fid
->flags
);
763 if (p_fs
->fs_func
->get_entry_size(ep2
) != fid
->size
)
764 p_fs
->fs_func
->set_entry_size(ep2
, fid
->size
);
766 if (p_fs
->fs_func
->get_entry_clu0(ep2
) != fid
->start_clu
)
767 p_fs
->fs_func
->set_entry_clu0(ep2
, fid
->start_clu
);
769 if (p_fs
->vol_type
!= EXFAT
)
770 buf_modify(sb
, sector
);
773 if (p_fs
->vol_type
== EXFAT
) {
774 update_dir_checksum_with_entry_set(sb
, es
);
775 release_entry_set(es
);
778 #if (DELAYED_SYNC == 0)
780 fs_set_vol_flags(sb
, VOL_CLEAN
);
784 /* set the size of written bytes */
786 *wcount
= write_bytes
;
788 if (num_alloced
== 0)
791 if (p_fs
->dev_ejected
)
795 } /* end of ffsWriteFile */
797 /* ffsTruncateFile : resize the file length */
798 INT32
ffsTruncateFile(struct inode
*inode
, UINT64 old_size
, UINT64 new_size
)
801 UINT32 last_clu
= CLUSTER_32(0), sector
= 0;
805 struct super_block
*sb
= inode
->i_sb
;
806 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
807 FILE_ID_T
*fid
= &(EXFAT_I(inode
)->fid
);
808 ENTRY_SET_CACHE_T
*es
=NULL
;
810 /* check if the given file ID is opened */
811 if (fid
->type
!= TYPE_FILE
)
812 return FFS_PERMISSIONERR
;
814 if (fid
->size
!= old_size
) {
815 printk(KERN_ERR
"[EXFAT] truncate : can't skip it because of "
816 "size-mismatch(old:%lld->fid:%lld).\n"
817 ,old_size
, fid
->size
);
820 if (old_size
<= new_size
)
823 fs_set_vol_flags(sb
, VOL_DIRTY
);
825 clu
.dir
= fid
->start_clu
;
826 clu
.size
= (INT32
)((old_size
-1) >> p_fs
->cluster_size_bits
) + 1;
827 clu
.flags
= fid
->flags
;
830 num_clusters
= (INT32
)((new_size
-1) >> p_fs
->cluster_size_bits
) + 1;
832 if (clu
.flags
== 0x03) {
833 clu
.dir
+= num_clusters
;
835 while (num_clusters
> 0) {
837 if (FAT_read(sb
, clu
.dir
, &(clu
.dir
)) == -1)
843 clu
.size
-= num_clusters
;
846 fid
->size
= new_size
;
847 fid
->attr
|= ATTR_ARCHIVE
;
849 fid
->flags
= (p_fs
->vol_type
== EXFAT
) ? 0x03 : 0x01;
850 fid
->start_clu
= CLUSTER_32(~0);
853 /* (1) update the directory entry */
854 if (p_fs
->vol_type
== EXFAT
) {
855 es
= get_entry_set_in_dir(sb
, &(fid
->dir
), fid
->entry
, ES_ALL_ENTRIES
, &ep
);
860 ep
= get_entry_in_dir(sb
, &(fid
->dir
), fid
->entry
, §or
);
866 p_fs
->fs_func
->set_entry_time(ep
, tm_current(&tm
), TM_MODIFY
);
867 p_fs
->fs_func
->set_entry_attr(ep
, fid
->attr
);
869 p_fs
->fs_func
->set_entry_size(ep2
, new_size
);
871 p_fs
->fs_func
->set_entry_flag(ep2
, 0x01);
872 p_fs
->fs_func
->set_entry_clu0(ep2
, CLUSTER_32(0));
875 if (p_fs
->vol_type
!= EXFAT
)
876 buf_modify(sb
, sector
);
878 update_dir_checksum_with_entry_set(sb
, es
);
879 release_entry_set(es
);
882 /* (2) cut off from the FAT chain */
883 if (last_clu
!= CLUSTER_32(0)) {
884 if (fid
->flags
== 0x01)
885 FAT_write(sb
, last_clu
, CLUSTER_32(~0));
888 /* (3) free the clusters */
889 p_fs
->fs_func
->free_cluster(sb
, &clu
, 0);
891 /* hint information */
892 fid
->hint_last_off
= -1;
893 if (fid
->rwoffset
> fid
->size
) {
894 fid
->rwoffset
= fid
->size
;
897 #if (DELAYED_SYNC == 0)
899 fs_set_vol_flags(sb
, VOL_CLEAN
);
902 if (p_fs
->dev_ejected
)
906 } /* end of ffsTruncateFile */
908 static void update_parent_info( FILE_ID_T
*fid
, struct inode
*parent_inode
)
910 FS_INFO_T
*p_fs
= &(EXFAT_SB(parent_inode
->i_sb
)->fs_info
);
911 FILE_ID_T
*parent_fid
= &(EXFAT_I(parent_inode
)->fid
);
913 if (unlikely((parent_fid
->flags
!= fid
->dir
.flags
)
914 || (parent_fid
->size
!= (fid
->dir
.size
<<p_fs
->cluster_size_bits
))
915 || (parent_fid
->start_clu
!= fid
->dir
.dir
))) {
917 fid
->dir
.dir
= parent_fid
->start_clu
;
918 fid
->dir
.flags
= parent_fid
->flags
;
919 fid
->dir
.size
= ((parent_fid
->size
+ (p_fs
->cluster_size
-1))
920 >> p_fs
->cluster_size_bits
);
924 /* ffsMoveFile : move(rename) a old file into a new file */
925 INT32
ffsMoveFile(struct inode
*old_parent_inode
, FILE_ID_T
*fid
, struct inode
*new_parent_inode
, struct dentry
*new_dentry
)
929 CHAIN_T olddir
, newdir
;
933 struct super_block
*sb
= old_parent_inode
->i_sb
;
934 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
935 UINT8
*new_path
= (UINT8
*) new_dentry
->d_name
.name
;
936 struct inode
*new_inode
= new_dentry
->d_inode
;
938 FILE_ID_T
*new_fid
= NULL
;
941 /* check the validity of pointer parameters */
942 if ((new_path
== NULL
) || (*new_path
== '\0'))
945 update_parent_info(fid
, old_parent_inode
);
947 olddir
.dir
= fid
->dir
.dir
;
948 olddir
.size
= fid
->dir
.size
;
949 olddir
.flags
= fid
->dir
.flags
;
953 /* check if the old file is "." or ".." */
954 if (p_fs
->vol_type
!= EXFAT
) {
955 if ((olddir
.dir
!= p_fs
->root_dir
) && (dentry
< 2))
956 return FFS_PERMISSIONERR
;
959 ep
= get_entry_in_dir(sb
, &olddir
, dentry
, NULL
);
963 if (p_fs
->fs_func
->get_entry_attr(ep
) & ATTR_READONLY
)
964 return FFS_PERMISSIONERR
;
966 /* check whether new dir is existing directory and empty */
971 new_fid
= &EXFAT_I(new_inode
)->fid
;
973 update_parent_info(new_fid
, new_parent_inode
);
975 p_dir
= &(new_fid
->dir
);
976 new_entry
= new_fid
->entry
;
977 ep
= get_entry_in_dir(sb
, p_dir
, new_entry
, NULL
);
981 entry_type
= p_fs
->fs_func
->get_entry_type(ep
);
983 if (entry_type
== TYPE_DIR
) {
985 new_clu
.dir
= new_fid
->start_clu
;
986 new_clu
.size
= (INT32
)((new_fid
->size
-1) >> p_fs
->cluster_size_bits
) + 1;
987 new_clu
.flags
= new_fid
->flags
;
989 if (!is_dir_empty(sb
, &new_clu
))
990 return FFS_FILEEXIST
;
994 /* check the validity of directory name in the given new pathname */
995 ret
= resolve_path(new_parent_inode
, new_path
, &newdir
, &uni_name
);
999 fs_set_vol_flags(sb
, VOL_DIRTY
);
1001 if (olddir
.dir
== newdir
.dir
)
1002 ret
= rename_file(new_parent_inode
, &olddir
, dentry
, &uni_name
, fid
);
1004 ret
= move_file(new_parent_inode
, &olddir
, dentry
, &newdir
, &uni_name
, fid
);
1006 if ((ret
== FFS_SUCCESS
) && new_inode
) {
1007 /* delete entries of new_dir */
1008 ep
= get_entry_in_dir(sb
, p_dir
, new_entry
, NULL
);
1012 num_entries
= p_fs
->fs_func
->count_ext_entries(sb
, p_dir
, new_entry
, ep
);
1013 if (num_entries
< 0)
1015 p_fs
->fs_func
->delete_dir_entry(sb
, p_dir
, new_entry
, 0, num_entries
+1);
1018 #if (DELAYED_SYNC == 0)
1020 fs_set_vol_flags(sb
, VOL_CLEAN
);
1023 if (p_fs
->dev_ejected
)
1024 return FFS_MEDIAERR
;
1027 } /* end of ffsMoveFile */
1029 /* ffsRemoveFile : remove a file */
1030 INT32
ffsRemoveFile(struct inode
*inode
, FILE_ID_T
*fid
)
1033 CHAIN_T dir
, clu_to_free
;
1035 struct super_block
*sb
= inode
->i_sb
;
1036 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1038 dir
.dir
= fid
->dir
.dir
;
1039 dir
.size
= fid
->dir
.size
;
1040 dir
.flags
= fid
->dir
.flags
;
1042 dentry
= fid
->entry
;
1044 ep
= get_entry_in_dir(sb
, &dir
, dentry
, NULL
);
1046 return FFS_MEDIAERR
;
1048 if (p_fs
->fs_func
->get_entry_attr(ep
) & ATTR_READONLY
)
1049 return FFS_PERMISSIONERR
;
1051 fs_set_vol_flags(sb
, VOL_DIRTY
);
1053 /* (1) update the directory entry */
1054 remove_file(inode
, &dir
, dentry
);
1056 clu_to_free
.dir
= fid
->start_clu
;
1057 clu_to_free
.size
= (INT32
)((fid
->size
-1) >> p_fs
->cluster_size_bits
) + 1;
1058 clu_to_free
.flags
= fid
->flags
;
1060 /* (2) free the clusters */
1061 p_fs
->fs_func
->free_cluster(sb
, &clu_to_free
, 0);
1064 fid
->start_clu
= CLUSTER_32(~0);
1065 fid
->flags
= (p_fs
->vol_type
== EXFAT
)? 0x03: 0x01;
1067 #if (DELAYED_SYNC == 0)
1069 fs_set_vol_flags(sb
, VOL_CLEAN
);
1072 if (p_fs
->dev_ejected
)
1073 return FFS_MEDIAERR
;
1076 } /* end of ffsRemoveFile */
1078 /* ffsSetAttr : set the attribute of a given file */
1079 INT32
ffsSetAttr(struct inode
*inode
, UINT32 attr
)
1081 UINT32 type
, sector
= 0;
1083 struct super_block
*sb
= inode
->i_sb
;
1084 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1085 FILE_ID_T
*fid
= &(EXFAT_I(inode
)->fid
);
1086 UINT8 is_dir
= (fid
->type
== TYPE_DIR
) ? 1 : 0;
1087 ENTRY_SET_CACHE_T
*es
= NULL
;
1089 if (fid
->attr
== attr
) {
1090 if (p_fs
->dev_ejected
)
1091 return FFS_MEDIAERR
;
1096 if ((fid
->dir
.dir
== p_fs
->root_dir
) &&
1097 (fid
->entry
== -1)) {
1098 if (p_fs
->dev_ejected
)
1099 return FFS_MEDIAERR
;
1104 /* get the directory entry of given file */
1105 if (p_fs
->vol_type
== EXFAT
) {
1106 es
= get_entry_set_in_dir(sb
, &(fid
->dir
), fid
->entry
, ES_ALL_ENTRIES
, &ep
);
1108 return FFS_MEDIAERR
;
1110 ep
= get_entry_in_dir(sb
, &(fid
->dir
), fid
->entry
, §or
);
1112 return FFS_MEDIAERR
;
1115 type
= p_fs
->fs_func
->get_entry_type(ep
);
1117 if (((type
== TYPE_FILE
) && (attr
& ATTR_SUBDIR
)) ||
1118 ((type
== TYPE_DIR
) && (!(attr
& ATTR_SUBDIR
)))) {
1120 if (p_fs
->dev_ejected
)
1125 if (p_fs
->vol_type
== EXFAT
)
1126 release_entry_set(es
);
1130 fs_set_vol_flags(sb
, VOL_DIRTY
);
1132 /* set the file attribute */
1134 p_fs
->fs_func
->set_entry_attr(ep
, attr
);
1136 if (p_fs
->vol_type
!= EXFAT
)
1137 buf_modify(sb
, sector
);
1139 update_dir_checksum_with_entry_set(sb
, es
);
1140 release_entry_set(es
);
1143 #if (DELAYED_SYNC == 0)
1145 fs_set_vol_flags(sb
, VOL_CLEAN
);
1148 if (p_fs
->dev_ejected
)
1149 return FFS_MEDIAERR
;
1152 } /* end of ffsSetAttr */
1154 /* ffsGetStat : get the information of a given file */
1155 INT32
ffsGetStat(struct inode
*inode
, DIR_ENTRY_T
*info
)
1160 UNI_NAME_T uni_name
;
1163 struct super_block
*sb
= inode
->i_sb
;
1164 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1165 FILE_ID_T
*fid
= &(EXFAT_I(inode
)->fid
);
1166 ENTRY_SET_CACHE_T
*es
=NULL
;
1167 UINT8 is_dir
= (fid
->type
== TYPE_DIR
) ? 1 : 0;
1169 PRINTK("ffsGetStat entered\n");
1172 if ((fid
->dir
.dir
== p_fs
->root_dir
) &&
1173 (fid
->entry
== -1)) {
1174 info
->Attr
= ATTR_SUBDIR
;
1175 MEMSET((INT8
*) &info
->CreateTimestamp
, 0, sizeof(DATE_TIME_T
));
1176 MEMSET((INT8
*) &info
->ModifyTimestamp
, 0, sizeof(DATE_TIME_T
));
1177 MEMSET((INT8
*) &info
->AccessTimestamp
, 0, sizeof(DATE_TIME_T
));
1178 STRCPY(info
->ShortName
, ".");
1179 STRCPY(info
->Name
, ".");
1181 dir
.dir
= p_fs
->root_dir
;
1184 if (p_fs
->root_dir
== CLUSTER_32(0)) /* FAT16 root_dir */
1185 info
->Size
= p_fs
->dentries_in_root
<< DENTRY_SIZE_BITS
;
1187 info
->Size
= count_num_clusters(sb
, &dir
) << p_fs
->cluster_size_bits
;
1189 count
= count_dos_name_entries(sb
, &dir
, TYPE_DIR
);
1191 return FFS_MEDIAERR
;
1192 info
->NumSubdirs
= count
;
1194 if (p_fs
->dev_ejected
)
1195 return FFS_MEDIAERR
;
1200 /* get the directory entry of given file or directory */
1201 if (p_fs
->vol_type
== EXFAT
) {
1202 es
= get_entry_set_in_dir(sb
, &(fid
->dir
), fid
->entry
, ES_2_ENTRIES
, &ep
);
1204 return FFS_MEDIAERR
;
1207 ep
= get_entry_in_dir(sb
, &(fid
->dir
), fid
->entry
, §or
);
1209 return FFS_MEDIAERR
;
1211 buf_lock(sb
, sector
);
1214 /* set FILE_INFO structure using the acquired DENTRY_T */
1215 info
->Attr
= p_fs
->fs_func
->get_entry_attr(ep
);
1217 p_fs
->fs_func
->get_entry_time(ep
, &tm
, TM_CREATE
);
1218 info
->CreateTimestamp
.Year
= tm
.year
;
1219 info
->CreateTimestamp
.Month
= tm
.mon
;
1220 info
->CreateTimestamp
.Day
= tm
.day
;
1221 info
->CreateTimestamp
.Hour
= tm
.hour
;
1222 info
->CreateTimestamp
.Minute
= tm
.min
;
1223 info
->CreateTimestamp
.Second
= tm
.sec
;
1224 info
->CreateTimestamp
.MilliSecond
= 0;
1226 p_fs
->fs_func
->get_entry_time(ep
, &tm
, TM_MODIFY
);
1227 info
->ModifyTimestamp
.Year
= tm
.year
;
1228 info
->ModifyTimestamp
.Month
= tm
.mon
;
1229 info
->ModifyTimestamp
.Day
= tm
.day
;
1230 info
->ModifyTimestamp
.Hour
= tm
.hour
;
1231 info
->ModifyTimestamp
.Minute
= tm
.min
;
1232 info
->ModifyTimestamp
.Second
= tm
.sec
;
1233 info
->ModifyTimestamp
.MilliSecond
= 0;
1235 MEMSET((INT8
*) &info
->AccessTimestamp
, 0, sizeof(DATE_TIME_T
));
1237 *(uni_name
.name
) = 0x0;
1238 /* XXX this is very bad for exfat cuz name is already included in es.
1239 API should be revised */
1240 p_fs
->fs_func
->get_uni_name_from_ext_entry(sb
, &(fid
->dir
), fid
->entry
, uni_name
.name
);
1241 if (*(uni_name
.name
) == 0x0)
1242 get_uni_name_from_dos_entry(sb
, (DOS_DENTRY_T
*) ep
, &uni_name
, 0x1);
1243 nls_uniname_to_cstring(sb
, info
->Name
, &uni_name
);
1245 if (p_fs
->vol_type
== EXFAT
) {
1246 info
->NumSubdirs
= 2;
1248 buf_unlock(sb
, sector
);
1249 get_uni_name_from_dos_entry(sb
, (DOS_DENTRY_T
*) ep
, &uni_name
, 0x0);
1250 nls_uniname_to_cstring(sb
, info
->ShortName
, &uni_name
);
1251 info
->NumSubdirs
= 0;
1254 info
->Size
= p_fs
->fs_func
->get_entry_size(ep2
);
1256 if (p_fs
->vol_type
== EXFAT
)
1257 release_entry_set(es
);
1260 dir
.dir
= fid
->start_clu
;
1263 if (info
->Size
== 0)
1264 info
->Size
= (UINT64
) count_num_clusters(sb
, &dir
) << p_fs
->cluster_size_bits
;
1266 count
= count_dos_name_entries(sb
, &dir
, TYPE_DIR
);
1268 return FFS_MEDIAERR
;
1269 info
->NumSubdirs
+= count
;
1272 if (p_fs
->dev_ejected
)
1273 return FFS_MEDIAERR
;
1275 PRINTK("ffsGetStat exited successfully\n");
1277 } /* end of ffsGetStat */
1279 /* ffsSetStat : set the information of a given file */
1280 INT32
ffsSetStat(struct inode
*inode
, DIR_ENTRY_T
*info
)
1285 ENTRY_SET_CACHE_T
*es
=NULL
;
1286 struct super_block
*sb
= inode
->i_sb
;
1287 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1288 FILE_ID_T
*fid
= &(EXFAT_I(inode
)->fid
);
1289 UINT8 is_dir
= (fid
->type
== TYPE_DIR
) ? 1 : 0;
1292 if ((fid
->dir
.dir
== p_fs
->root_dir
) &&
1293 (fid
->entry
== -1)) {
1294 if (p_fs
->dev_ejected
)
1295 return FFS_MEDIAERR
;
1300 fs_set_vol_flags(sb
, VOL_DIRTY
);
1302 /* get the directory entry of given file or directory */
1303 if (p_fs
->vol_type
== EXFAT
) {
1304 es
= get_entry_set_in_dir(sb
, &(fid
->dir
), fid
->entry
, ES_ALL_ENTRIES
, &ep
);
1306 return FFS_MEDIAERR
;
1309 /* for other than exfat */
1310 ep
= get_entry_in_dir(sb
, &(fid
->dir
), fid
->entry
, §or
);
1312 return FFS_MEDIAERR
;
1317 p_fs
->fs_func
->set_entry_attr(ep
, info
->Attr
);
1319 /* set FILE_INFO structure using the acquired DENTRY_T */
1320 tm
.sec
= info
->CreateTimestamp
.Second
;
1321 tm
.min
= info
->CreateTimestamp
.Minute
;
1322 tm
.hour
= info
->CreateTimestamp
.Hour
;
1323 tm
.day
= info
->CreateTimestamp
.Day
;
1324 tm
.mon
= info
->CreateTimestamp
.Month
;
1325 tm
.year
= info
->CreateTimestamp
.Year
;
1326 p_fs
->fs_func
->set_entry_time(ep
, &tm
, TM_CREATE
);
1328 tm
.sec
= info
->ModifyTimestamp
.Second
;
1329 tm
.min
= info
->ModifyTimestamp
.Minute
;
1330 tm
.hour
= info
->ModifyTimestamp
.Hour
;
1331 tm
.day
= info
->ModifyTimestamp
.Day
;
1332 tm
.mon
= info
->ModifyTimestamp
.Month
;
1333 tm
.year
= info
->ModifyTimestamp
.Year
;
1334 p_fs
->fs_func
->set_entry_time(ep
, &tm
, TM_MODIFY
);
1337 p_fs
->fs_func
->set_entry_size(ep2
, info
->Size
);
1339 if (p_fs
->vol_type
!= EXFAT
) {
1340 buf_modify(sb
, sector
);
1342 update_dir_checksum_with_entry_set(sb
, es
);
1343 release_entry_set(es
);
1346 if (p_fs
->dev_ejected
)
1347 return FFS_MEDIAERR
;
1350 } /* end of ffsSetStat */
1352 INT32
ffsMapCluster(struct inode
*inode
, INT32 clu_offset
, UINT32
*clu
)
1354 INT32 num_clusters
, num_alloced
, modified
= FALSE
;
1355 UINT32 last_clu
, sector
= 0;
1358 ENTRY_SET_CACHE_T
*es
= NULL
;
1359 struct super_block
*sb
= inode
->i_sb
;
1360 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1361 FILE_ID_T
*fid
= &(EXFAT_I(inode
)->fid
);
1363 fid
->rwoffset
= (INT64
)(clu_offset
) << p_fs
->cluster_size_bits
;
1365 if (EXFAT_I(inode
)->mmu_private
== 0)
1368 num_clusters
= (INT32
)((EXFAT_I(inode
)->mmu_private
-1) >> p_fs
->cluster_size_bits
) + 1;
1370 *clu
= last_clu
= fid
->start_clu
;
1372 if (fid
->flags
== 0x03) {
1373 if ((clu_offset
> 0) && (*clu
!= CLUSTER_32(~0))) {
1374 last_clu
+= clu_offset
- 1;
1376 if (clu_offset
== num_clusters
)
1377 *clu
= CLUSTER_32(~0);
1382 /* hint information */
1383 if ((clu_offset
> 0) && (fid
->hint_last_off
> 0) &&
1384 (clu_offset
>= fid
->hint_last_off
)) {
1385 clu_offset
-= fid
->hint_last_off
;
1386 *clu
= fid
->hint_last_clu
;
1389 while ((clu_offset
> 0) && (*clu
!= CLUSTER_32(~0))) {
1391 if (FAT_read(sb
, *clu
, clu
) == -1)
1392 return FFS_MEDIAERR
;
1397 if (*clu
== CLUSTER_32(~0)) {
1398 fs_set_vol_flags(sb
, VOL_DIRTY
);
1400 new_clu
.dir
= (last_clu
== CLUSTER_32(~0)) ? CLUSTER_32(~0) : last_clu
+1;
1402 new_clu
.flags
= fid
->flags
;
1404 /* (1) allocate a cluster */
1405 num_alloced
= p_fs
->fs_func
->alloc_cluster(sb
, 1, &new_clu
);
1406 if (num_alloced
< 1)
1409 /* (2) append to the FAT chain */
1410 if (last_clu
== CLUSTER_32(~0)) {
1411 if (new_clu
.flags
== 0x01)
1413 fid
->start_clu
= new_clu
.dir
;
1416 if (new_clu
.flags
!= fid
->flags
) {
1417 exfat_chain_cont_cluster(sb
, fid
->start_clu
, num_clusters
);
1421 if (new_clu
.flags
== 0x01)
1422 FAT_write(sb
, last_clu
, new_clu
.dir
);
1427 if (p_fs
->vol_type
== EXFAT
) {
1428 es
= get_entry_set_in_dir(sb
, &(fid
->dir
), fid
->entry
, ES_ALL_ENTRIES
, &ep
);
1430 return FFS_MEDIAERR
;
1431 /* get stream entry */
1435 /* (3) update directory entry */
1437 if (p_fs
->vol_type
!= EXFAT
) {
1438 ep
= get_entry_in_dir(sb
, &(fid
->dir
), fid
->entry
, §or
);
1440 return FFS_MEDIAERR
;
1443 if (p_fs
->fs_func
->get_entry_flag(ep
) != fid
->flags
)
1444 p_fs
->fs_func
->set_entry_flag(ep
, fid
->flags
);
1446 if (p_fs
->fs_func
->get_entry_clu0(ep
) != fid
->start_clu
)
1447 p_fs
->fs_func
->set_entry_clu0(ep
, fid
->start_clu
);
1449 if (p_fs
->vol_type
!= EXFAT
)
1450 buf_modify(sb
, sector
);
1453 if (p_fs
->vol_type
== EXFAT
) {
1454 update_dir_checksum_with_entry_set(sb
, es
);
1455 release_entry_set(es
);
1458 /* add number of new blocks to inode */
1459 inode
->i_blocks
+= num_alloced
<< (p_fs
->cluster_size_bits
- 9);
1462 /* hint information */
1463 fid
->hint_last_off
= (INT32
)(fid
->rwoffset
>> p_fs
->cluster_size_bits
);
1464 fid
->hint_last_clu
= *clu
;
1466 if (p_fs
->dev_ejected
)
1467 return FFS_MEDIAERR
;
1470 } /* end of ffsMapCluster */
1472 /*----------------------------------------------------------------------*/
1473 /* Directory Operation Functions */
1474 /*----------------------------------------------------------------------*/
1476 /* ffsCreateDir : create(make) a directory */
1477 INT32
ffsCreateDir(struct inode
*inode
, UINT8
*path
, FILE_ID_T
*fid
)
1479 INT32 ret
/*, dentry*/;
1481 UNI_NAME_T uni_name
;
1482 struct super_block
*sb
= inode
->i_sb
;
1483 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1485 PRINTK("ffsCreateDir entered\n");
1487 /* check the validity of directory name in the given old pathname */
1488 ret
= resolve_path(inode
, path
, &dir
, &uni_name
);
1492 fs_set_vol_flags(sb
, VOL_DIRTY
);
1494 ret
= create_dir(inode
, &dir
, &uni_name
, fid
);
1496 #if (DELAYED_SYNC == 0)
1498 fs_set_vol_flags(sb
, VOL_CLEAN
);
1501 if (p_fs
->dev_ejected
)
1502 return FFS_MEDIAERR
;
1505 } /* end of ffsCreateDir */
1507 /* ffsReadDir : read a directory entry from the opened directory */
1508 INT32
ffsReadDir(struct inode
*inode
, DIR_ENTRY_T
*dir_entry
)
1510 INT32 i
, dentry
, clu_offset
;
1511 INT32 dentries_per_clu
, dentries_per_clu_bits
= 0;
1512 UINT32 type
, sector
;
1514 UNI_NAME_T uni_name
;
1517 struct super_block
*sb
= inode
->i_sb
;
1518 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1519 FILE_ID_T
*fid
= &(EXFAT_I(inode
)->fid
);
1521 /* check if the given file ID is opened */
1522 if (fid
->type
!= TYPE_DIR
)
1523 return FFS_PERMISSIONERR
;
1525 if (fid
->entry
== -1) {
1526 dir
.dir
= p_fs
->root_dir
;
1529 dir
.dir
= fid
->start_clu
;
1530 dir
.size
= (INT32
)(fid
->size
>> p_fs
->cluster_size_bits
);
1531 dir
.flags
= fid
->flags
;
1534 dentry
= (INT32
) fid
->rwoffset
;
1536 if (dir
.dir
== CLUSTER_32(0)) { /* FAT16 root_dir */
1537 dentries_per_clu
= p_fs
->dentries_in_root
;
1539 if (dentry
== dentries_per_clu
) {
1540 clu
.dir
= CLUSTER_32(~0);
1543 clu
.size
= dir
.size
;
1544 clu
.flags
= dir
.flags
;
1547 dentries_per_clu
= p_fs
->dentries_per_clu
;
1548 dentries_per_clu_bits
= my_log2(dentries_per_clu
);
1550 clu_offset
= dentry
>> dentries_per_clu_bits
;
1552 clu
.size
= dir
.size
;
1553 clu
.flags
= dir
.flags
;
1555 if (clu
.flags
== 0x03) {
1556 clu
.dir
+= clu_offset
;
1557 clu
.size
-= clu_offset
;
1559 /* hint_information */
1560 if ((clu_offset
> 0) && (fid
->hint_last_off
> 0) &&
1561 (clu_offset
>= fid
->hint_last_off
)) {
1562 clu_offset
-= fid
->hint_last_off
;
1563 clu
.dir
= fid
->hint_last_clu
;
1566 while (clu_offset
> 0) {
1567 /* clu.dir = FAT_read(sb, clu.dir); */
1568 if (FAT_read(sb
, clu
.dir
, &(clu
.dir
)) == -1)
1569 return FFS_MEDIAERR
;
1576 while (clu
.dir
!= CLUSTER_32(~0)) {
1577 if (p_fs
->dev_ejected
)
1580 if (dir
.dir
== CLUSTER_32(0)) /* FAT16 root_dir */
1581 i
= dentry
% dentries_per_clu
;
1583 i
= dentry
& (dentries_per_clu
-1);
1585 for ( ; i
< dentries_per_clu
; i
++, dentry
++) {
1586 ep
= get_entry_in_dir(sb
, &clu
, i
, §or
);
1588 return FFS_MEDIAERR
;
1590 type
= p_fs
->fs_func
->get_entry_type(ep
);
1592 if (type
== TYPE_UNUSED
)
1595 if ((type
!= TYPE_FILE
) && (type
!= TYPE_DIR
))
1598 buf_lock(sb
, sector
);
1599 dir_entry
->Attr
= p_fs
->fs_func
->get_entry_attr(ep
);
1601 p_fs
->fs_func
->get_entry_time(ep
, &tm
, TM_CREATE
);
1602 dir_entry
->CreateTimestamp
.Year
= tm
.year
;
1603 dir_entry
->CreateTimestamp
.Month
= tm
.mon
;
1604 dir_entry
->CreateTimestamp
.Day
= tm
.day
;
1605 dir_entry
->CreateTimestamp
.Hour
= tm
.hour
;
1606 dir_entry
->CreateTimestamp
.Minute
= tm
.min
;
1607 dir_entry
->CreateTimestamp
.Second
= tm
.sec
;
1608 dir_entry
->CreateTimestamp
.MilliSecond
= 0;
1610 p_fs
->fs_func
->get_entry_time(ep
, &tm
, TM_MODIFY
);
1611 dir_entry
->ModifyTimestamp
.Year
= tm
.year
;
1612 dir_entry
->ModifyTimestamp
.Month
= tm
.mon
;
1613 dir_entry
->ModifyTimestamp
.Day
= tm
.day
;
1614 dir_entry
->ModifyTimestamp
.Hour
= tm
.hour
;
1615 dir_entry
->ModifyTimestamp
.Minute
= tm
.min
;
1616 dir_entry
->ModifyTimestamp
.Second
= tm
.sec
;
1617 dir_entry
->ModifyTimestamp
.MilliSecond
= 0;
1619 MEMSET((INT8
*) &dir_entry
->AccessTimestamp
, 0, sizeof(DATE_TIME_T
));
1621 *(uni_name
.name
) = 0x0;
1622 p_fs
->fs_func
->get_uni_name_from_ext_entry(sb
, &dir
, dentry
, uni_name
.name
);
1623 if (*(uni_name
.name
) == 0x0)
1624 get_uni_name_from_dos_entry(sb
, (DOS_DENTRY_T
*) ep
, &uni_name
, 0x1);
1625 nls_uniname_to_cstring(sb
, dir_entry
->Name
, &uni_name
);
1626 buf_unlock(sb
, sector
);
1628 if (p_fs
->vol_type
== EXFAT
) {
1629 ep
= get_entry_in_dir(sb
, &clu
, i
+1, NULL
);
1631 return FFS_MEDIAERR
;
1633 get_uni_name_from_dos_entry(sb
, (DOS_DENTRY_T
*) ep
, &uni_name
, 0x0);
1634 nls_uniname_to_cstring(sb
, dir_entry
->ShortName
, &uni_name
);
1637 dir_entry
->Size
= p_fs
->fs_func
->get_entry_size(ep
);
1639 /* hint information */
1640 if (dir
.dir
== CLUSTER_32(0)) { /* FAT16 root_dir */
1642 fid
->hint_last_off
= dentry
>> dentries_per_clu_bits
;
1643 fid
->hint_last_clu
= clu
.dir
;
1646 fid
->rwoffset
= (INT64
) ++dentry
;
1648 if (p_fs
->dev_ejected
)
1649 return FFS_MEDIAERR
;
1654 if (dir
.dir
== CLUSTER_32(0))
1655 break; /* FAT16 root_dir */
1657 if (clu
.flags
== 0x03) {
1658 if ((--clu
.size
) > 0)
1661 clu
.dir
= CLUSTER_32(~0);
1663 /* clu.dir = FAT_read(sb, clu.dir); */
1664 if (FAT_read(sb
, clu
.dir
, &(clu
.dir
)) == -1)
1665 return FFS_MEDIAERR
;
1669 *(dir_entry
->Name
) = '\0';
1671 fid
->rwoffset
= (INT64
) ++dentry
;
1673 if (p_fs
->dev_ejected
)
1674 return FFS_MEDIAERR
;
1677 } /* end of ffsReadDir */
1679 /* ffsRemoveDir : remove a directory */
1680 INT32
ffsRemoveDir(struct inode
*inode
, FILE_ID_T
*fid
)
1683 CHAIN_T dir
, clu_to_free
;
1684 struct super_block
*sb
= inode
->i_sb
;
1685 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1687 dir
.dir
= fid
->dir
.dir
;
1688 dir
.size
= fid
->dir
.size
;
1689 dir
.flags
= fid
->dir
.flags
;
1691 dentry
= fid
->entry
;
1693 /* check if the file is "." or ".." */
1694 if (p_fs
->vol_type
!= EXFAT
) {
1695 if ((dir
.dir
!= p_fs
->root_dir
) && (dentry
< 2))
1696 return FFS_PERMISSIONERR
;
1699 clu_to_free
.dir
= fid
->start_clu
;
1700 clu_to_free
.size
= (INT32
)((fid
->size
-1) >> p_fs
->cluster_size_bits
) + 1;
1701 clu_to_free
.flags
= fid
->flags
;
1703 if (!is_dir_empty(sb
, &clu_to_free
))
1704 return FFS_FILEEXIST
;
1706 fs_set_vol_flags(sb
, VOL_DIRTY
);
1708 /* (1) update the directory entry */
1709 remove_file(inode
, &dir
, dentry
);
1711 /* (2) free the clusters */
1712 p_fs
->fs_func
->free_cluster(sb
, &clu_to_free
, 1);
1715 fid
->start_clu
= CLUSTER_32(~0);
1716 fid
->flags
= (p_fs
->vol_type
== EXFAT
)? 0x03: 0x01;
1718 #if (DELAYED_SYNC == 0)
1720 fs_set_vol_flags(sb
, VOL_CLEAN
);
1723 if (p_fs
->dev_ejected
)
1724 return FFS_MEDIAERR
;
1727 } /* end of ffsRemoveDir */
1729 /*======================================================================*/
1730 /* Local Function Definitions */
1731 /*======================================================================*/
1734 * File System Management Functions
1739 /* critical check for system requirement on size of DENTRY_T structure */
1740 if (sizeof(DENTRY_T
) != DENTRY_SIZE
) {
1741 return FFS_ALIGNMENTERR
;
1744 if (sizeof(DOS_DENTRY_T
) != DENTRY_SIZE
) {
1745 return FFS_ALIGNMENTERR
;
1748 if (sizeof(EXT_DENTRY_T
) != DENTRY_SIZE
) {
1749 return FFS_ALIGNMENTERR
;
1752 if (sizeof(FILE_DENTRY_T
) != DENTRY_SIZE
) {
1753 return FFS_ALIGNMENTERR
;
1756 if (sizeof(STRM_DENTRY_T
) != DENTRY_SIZE
) {
1757 return FFS_ALIGNMENTERR
;
1760 if (sizeof(NAME_DENTRY_T
) != DENTRY_SIZE
) {
1761 return FFS_ALIGNMENTERR
;
1764 if (sizeof(BMAP_DENTRY_T
) != DENTRY_SIZE
) {
1765 return FFS_ALIGNMENTERR
;
1768 if (sizeof(CASE_DENTRY_T
) != DENTRY_SIZE
) {
1769 return FFS_ALIGNMENTERR
;
1772 if (sizeof(VOLM_DENTRY_T
) != DENTRY_SIZE
) {
1773 return FFS_ALIGNMENTERR
;
1777 } /* end of fs_init */
1779 INT32
fs_shutdown(void)
1782 } /* end of fs_shutdown */
1784 void fs_set_vol_flags(struct super_block
*sb
, UINT32 new_flag
)
1786 PBR_SECTOR_T
*p_pbr
;
1788 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1790 if (p_fs
->vol_flag
== new_flag
)
1793 p_fs
->vol_flag
= new_flag
;
1795 if (p_fs
->vol_type
== EXFAT
) {
1796 if (p_fs
->pbr_bh
== NULL
) {
1797 if (sector_read(sb
, p_fs
->PBR_sector
, &(p_fs
->pbr_bh
), 1) != FFS_SUCCESS
)
1801 p_pbr
= (PBR_SECTOR_T
*) p_fs
->pbr_bh
->b_data
;
1802 p_bpb
= (BPBEX_T
*) p_pbr
->bpb
;
1803 SET16(p_bpb
->vol_flags
, (UINT16
) new_flag
);
1806 what can we do here? (cuz fs_set_vol_flags() is void) */
1807 if ((new_flag
== VOL_DIRTY
) && (!buffer_dirty(p_fs
->pbr_bh
)))
1808 sector_write(sb
, p_fs
->PBR_sector
, p_fs
->pbr_bh
, 1);
1810 sector_write(sb
, p_fs
->PBR_sector
, p_fs
->pbr_bh
, 0);
1812 } /* end of fs_set_vol_flags */
1814 void fs_sync(struct super_block
*sb
, INT32 do_sync
)
1818 } /* end of fs_sync */
1820 void fs_error(struct super_block
*sb
)
1822 struct exfat_mount_options
*opts
= &EXFAT_SB(sb
)->options
;
1824 if (opts
->errors
== EXFAT_ERRORS_PANIC
)
1825 panic("[EXFAT] Filesystem panic from previous error\n");
1826 else if ((opts
->errors
== EXFAT_ERRORS_RO
) && !(sb
->s_flags
& MS_RDONLY
)) {
1827 sb
->s_flags
|= MS_RDONLY
;
1828 printk(KERN_ERR
"[EXFAT] Filesystem has been set read-only\n");
1833 * Cluster Management Functions
1836 INT32
clear_cluster(struct super_block
*sb
, UINT32 clu
)
1839 INT32 ret
= FFS_SUCCESS
;
1840 struct buffer_head
*tmp_bh
= NULL
;
1841 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1842 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
1844 if (clu
== CLUSTER_32(0)) { /* FAT16 root_dir */
1845 s
= p_fs
->root_start_sector
;
1846 n
= p_fs
->data_start_sector
;
1848 s
= START_SECTOR(clu
);
1849 n
= s
+ p_fs
->sectors_per_clu
;
1852 for ( ; s
< n
; s
++) {
1853 if ((ret
= sector_read(sb
, s
, &tmp_bh
, 0)) != FFS_SUCCESS
)
1856 MEMSET((INT8
*) tmp_bh
->b_data
, 0x0, p_bd
->sector_size
);
1857 if ((ret
= sector_write(sb
, s
, tmp_bh
, 0)) !=FFS_SUCCESS
)
1863 } /* end of clear_cluster */
1865 INT32
fat_alloc_cluster(struct super_block
*sb
, INT32 num_alloc
, CHAIN_T
*p_chain
)
1867 INT32 i
, num_clusters
= 0;
1868 UINT32 new_clu
, last_clu
= CLUSTER_32(~0), read_clu
;
1869 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1871 new_clu
= p_chain
->dir
;
1872 if (new_clu
== CLUSTER_32(~0))
1873 new_clu
= p_fs
->clu_srch_ptr
;
1874 else if (new_clu
>= p_fs
->num_clusters
)
1879 p_chain
->dir
= CLUSTER_32(~0);
1881 for (i
= 2; i
< p_fs
->num_clusters
; i
++) {
1882 if (FAT_read(sb
, new_clu
, &read_clu
) != 0)
1885 if (read_clu
== CLUSTER_32(0)) {
1886 FAT_write(sb
, new_clu
, CLUSTER_32(~0));
1889 if (p_chain
->dir
== CLUSTER_32(~0))
1890 p_chain
->dir
= new_clu
;
1892 FAT_write(sb
, last_clu
, new_clu
);
1896 if ((--num_alloc
) == 0) {
1897 p_fs
->clu_srch_ptr
= new_clu
;
1898 if (p_fs
->used_clusters
!= (UINT32
) ~0)
1899 p_fs
->used_clusters
+= num_clusters
;
1901 return(num_clusters
);
1904 if ((++new_clu
) >= p_fs
->num_clusters
)
1908 p_fs
->clu_srch_ptr
= new_clu
;
1909 if (p_fs
->used_clusters
!= (UINT32
) ~0)
1910 p_fs
->used_clusters
+= num_clusters
;
1912 return(num_clusters
);
1913 } /* end of fat_alloc_cluster */
1915 INT32
exfat_alloc_cluster(struct super_block
*sb
, INT32 num_alloc
, CHAIN_T
*p_chain
)
1917 INT32 num_clusters
= 0;
1918 UINT32 hint_clu
, new_clu
, last_clu
= CLUSTER_32(~0);
1919 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1921 hint_clu
= p_chain
->dir
;
1922 if (hint_clu
== CLUSTER_32(~0)) {
1923 hint_clu
= test_alloc_bitmap(sb
, p_fs
->clu_srch_ptr
-2);
1924 if (hint_clu
== CLUSTER_32(~0))
1926 } else if (hint_clu
>= p_fs
->num_clusters
) {
1928 p_chain
->flags
= 0x01;
1933 p_chain
->dir
= CLUSTER_32(~0);
1935 while ((new_clu
= test_alloc_bitmap(sb
, hint_clu
-2)) != CLUSTER_32(~0)) {
1936 if (new_clu
!= hint_clu
) {
1937 if (p_chain
->flags
== 0x03) {
1938 exfat_chain_cont_cluster(sb
, p_chain
->dir
, num_clusters
);
1939 p_chain
->flags
= 0x01;
1943 if (set_alloc_bitmap(sb
, new_clu
-2) != FFS_SUCCESS
)
1948 if (p_chain
->flags
== 0x01)
1949 FAT_write(sb
, new_clu
, CLUSTER_32(~0));
1951 if (p_chain
->dir
== CLUSTER_32(~0)) {
1952 p_chain
->dir
= new_clu
;
1954 if (p_chain
->flags
== 0x01)
1955 FAT_write(sb
, last_clu
, new_clu
);
1959 if ((--num_alloc
) == 0) {
1960 p_fs
->clu_srch_ptr
= hint_clu
;
1961 if (p_fs
->used_clusters
!= (UINT32
) ~0)
1962 p_fs
->used_clusters
+= num_clusters
;
1964 p_chain
->size
+= num_clusters
;
1965 return(num_clusters
);
1968 hint_clu
= new_clu
+ 1;
1969 if (hint_clu
>= p_fs
->num_clusters
) {
1972 if (p_chain
->flags
== 0x03) {
1973 exfat_chain_cont_cluster(sb
, p_chain
->dir
, num_clusters
);
1974 p_chain
->flags
= 0x01;
1979 p_fs
->clu_srch_ptr
= hint_clu
;
1980 if (p_fs
->used_clusters
!= (UINT32
) ~0)
1981 p_fs
->used_clusters
+= num_clusters
;
1983 p_chain
->size
+= num_clusters
;
1984 return(num_clusters
);
1985 } /* end of exfat_alloc_cluster */
1987 void fat_free_cluster(struct super_block
*sb
, CHAIN_T
*p_chain
, INT32 do_relse
)
1989 INT32 num_clusters
= 0;
1991 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
1995 if ((p_chain
->dir
== CLUSTER_32(0)) || (p_chain
->dir
== CLUSTER_32(~0)))
2000 if (p_chain
->size
<= 0)
2004 if (p_fs
->dev_ejected
)
2008 sector
= START_SECTOR(clu
);
2009 for (i
= 0; i
< p_fs
->sectors_per_clu
; i
++) {
2010 buf_release(sb
, sector
+i
);
2015 if (FAT_read(sb
, clu
, &clu
) == -1)
2018 FAT_write(sb
, prev
, CLUSTER_32(0));
2021 } while (clu
!= CLUSTER_32(~0));
2023 if (p_fs
->used_clusters
!= (UINT32
) ~0)
2024 p_fs
->used_clusters
-= num_clusters
;
2025 } /* end of fat_free_cluster */
2027 void exfat_free_cluster(struct super_block
*sb
, CHAIN_T
*p_chain
, INT32 do_relse
)
2029 INT32 num_clusters
= 0;
2031 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2035 if ((p_chain
->dir
== CLUSTER_32(0)) || (p_chain
->dir
== CLUSTER_32(~0)))
2038 if (p_chain
->size
<= 0) {
2039 printk(KERN_ERR
"[EXFAT] free_cluster : skip free-req clu:%u, "
2040 "because of zero-size truncation\n"
2048 if (p_chain
->flags
== 0x03) {
2051 sector
= START_SECTOR(clu
);
2052 for (i
= 0; i
< p_fs
->sectors_per_clu
; i
++) {
2053 buf_release(sb
, sector
+i
);
2057 if (clr_alloc_bitmap(sb
, clu
-2) != FFS_SUCCESS
)
2062 } while (num_clusters
< p_chain
->size
);
2065 if (p_fs
->dev_ejected
)
2069 sector
= START_SECTOR(clu
);
2070 for (i
= 0; i
< p_fs
->sectors_per_clu
; i
++) {
2071 buf_release(sb
, sector
+i
);
2075 if (clr_alloc_bitmap(sb
, clu
-2) != FFS_SUCCESS
)
2078 if (FAT_read(sb
, clu
, &clu
) == -1)
2081 } while ((clu
!= CLUSTER_32(0)) && (clu
!= CLUSTER_32(~0)));
2084 if (p_fs
->used_clusters
!= (UINT32
) ~0)
2085 p_fs
->used_clusters
-= num_clusters
;
2086 } /* end of exfat_free_cluster */
2088 UINT32
find_last_cluster(struct super_block
*sb
, CHAIN_T
*p_chain
)
2091 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2095 if (p_chain
->flags
== 0x03) {
2096 clu
+= p_chain
->size
- 1;
2098 while((FAT_read(sb
, clu
, &next
) == 0) && (next
!= CLUSTER_32(~0))) {
2099 if (p_fs
->dev_ejected
)
2106 } /* end of find_last_cluster */
2108 INT32
count_num_clusters(struct super_block
*sb
, CHAIN_T
*p_chain
)
2112 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2114 if ((p_chain
->dir
== CLUSTER_32(0)) || (p_chain
->dir
== CLUSTER_32(~0)))
2119 if (p_chain
->flags
== 0x03) {
2120 count
= p_chain
->size
;
2122 for (i
= 2; i
< p_fs
->num_clusters
; i
++) {
2124 if (FAT_read(sb
, clu
, &clu
) != 0)
2126 if (clu
== CLUSTER_32(~0))
2132 } /* end of count_num_clusters */
2134 INT32
fat_count_used_clusters(struct super_block
*sb
)
2138 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2140 for (i
= 2; i
< p_fs
->num_clusters
; i
++) {
2141 if (FAT_read(sb
, i
, &clu
) != 0)
2143 if (clu
!= CLUSTER_32(0))
2148 } /* end of fat_count_used_clusters */
2150 INT32
exfat_count_used_clusters(struct super_block
*sb
)
2152 INT32 i
, map_i
, map_b
, count
= 0;
2154 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2155 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
2159 for (i
= 2; i
< p_fs
->num_clusters
; i
+= 8) {
2160 k
= *(((UINT8
*) p_fs
->vol_amap
[map_i
]->b_data
) + map_b
);
2161 count
+= used_bit
[k
];
2163 if ((++map_b
) >= p_bd
->sector_size
) {
2170 } /* end of exfat_count_used_clusters */
2172 void exfat_chain_cont_cluster(struct super_block
*sb
, UINT32 chain
, INT32 len
)
2178 FAT_write(sb
, chain
, chain
+1);
2182 FAT_write(sb
, chain
, CLUSTER_32(~0));
2183 } /* end of exfat_chain_cont_cluster */
2186 * Allocation Bitmap Management Functions
2189 INT32
load_alloc_bitmap(struct super_block
*sb
)
2193 UINT32 type
, sector
;
2196 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2197 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
2199 clu
.dir
= p_fs
->root_dir
;
2202 while (clu
.dir
!= CLUSTER_32(~0)) {
2203 if (p_fs
->dev_ejected
)
2206 for (i
= 0; i
< p_fs
->dentries_per_clu
; i
++) {
2207 ep
= (BMAP_DENTRY_T
*) get_entry_in_dir(sb
, &clu
, i
, NULL
);
2209 return FFS_MEDIAERR
;
2211 type
= p_fs
->fs_func
->get_entry_type((DENTRY_T
*) ep
);
2213 if (type
== TYPE_UNUSED
)
2215 if (type
!= TYPE_BITMAP
)
2218 if (ep
->flags
== 0x0) {
2219 p_fs
->map_clu
= GET32_A(ep
->start_clu
);
2220 map_size
= (UINT32
) GET64_A(ep
->size
);
2222 p_fs
->map_sectors
= ((map_size
-1) >> p_bd
->sector_size_bits
) + 1;
2224 p_fs
->vol_amap
= (struct buffer_head
**) MALLOC(sizeof(struct buffer_head
*) * p_fs
->map_sectors
);
2225 if (p_fs
->vol_amap
== NULL
)
2226 return FFS_MEMORYERR
;
2228 sector
= START_SECTOR(p_fs
->map_clu
);
2230 for (j
= 0; j
< p_fs
->map_sectors
; j
++) {
2231 p_fs
->vol_amap
[j
] = NULL
;
2232 ret
= sector_read(sb
, sector
+j
, &(p_fs
->vol_amap
[j
]), 1);
2233 if (ret
!= FFS_SUCCESS
) {
2234 /* release all buffers and free vol_amap */
2237 brelse(p_fs
->vol_amap
[i
++]);
2239 FREE(p_fs
->vol_amap
);
2240 p_fs
->vol_amap
= NULL
;
2245 p_fs
->pbr_bh
= NULL
;
2250 if (FAT_read(sb
, clu
.dir
, &(clu
.dir
)) != 0)
2251 return FFS_MEDIAERR
;
2254 return FFS_FORMATERR
;
2255 } /* end of load_alloc_bitmap */
2257 void free_alloc_bitmap(struct super_block
*sb
)
2260 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2262 brelse(p_fs
->pbr_bh
);
2264 for (i
= 0; i
< p_fs
->map_sectors
; i
++) {
2265 __brelse(p_fs
->vol_amap
[i
]);
2268 FREE(p_fs
->vol_amap
);
2269 p_fs
->vol_amap
= NULL
;
2270 } /* end of free_alloc_bitmap */
2272 INT32
set_alloc_bitmap(struct super_block
*sb
, UINT32 clu
)
2276 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2277 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
2279 i
= clu
>> (p_bd
->sector_size_bits
+ 3);
2280 b
= clu
& ((p_bd
->sector_size
<< 3) - 1);
2282 sector
= START_SECTOR(p_fs
->map_clu
) + i
;
2284 Bitmap_set((UINT8
*) p_fs
->vol_amap
[i
]->b_data
, b
);
2286 return (sector_write(sb
, sector
, p_fs
->vol_amap
[i
], 0));
2287 } /* end of set_alloc_bitmap */
2289 INT32
clr_alloc_bitmap(struct super_block
*sb
, UINT32 clu
)
2293 #if EXFAT_CONFIG_DISCARD
2294 struct exfat_sb_info
*sbi
= EXFAT_SB(sb
);
2295 struct exfat_mount_options
*opts
= &sbi
->options
;
2297 #endif /* EXFAT_CONFIG_DISCARD */
2298 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2299 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
2301 i
= clu
>> (p_bd
->sector_size_bits
+ 3);
2302 b
= clu
& ((p_bd
->sector_size
<< 3) - 1);
2304 sector
= START_SECTOR(p_fs
->map_clu
) + i
;
2306 Bitmap_clear((UINT8
*) p_fs
->vol_amap
[i
]->b_data
, b
);
2308 return (sector_write(sb
, sector
, p_fs
->vol_amap
[i
], 0));
2310 #if EXFAT_CONFIG_DISCARD
2311 if (opts
->discard
) {
2312 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
2313 ret
= sb_issue_discard(sb
, START_SECTOR(clu
), (1 << p_fs
->sectors_per_clu_bits
));
2315 ret
= sb_issue_discard(sb
, START_SECTOR(clu
), (1 << p_fs
->sectors_per_clu_bits
), GFP_NOFS
, 0);
2317 if (ret
== -EOPNOTSUPP
) {
2318 printk(KERN_WARNING
"discard not supported by device, disabling");
2322 #endif /* EXFAT_CONFIG_DISCARD */
2323 } /* end of clr_alloc_bitmap */
2325 UINT32
test_alloc_bitmap(struct super_block
*sb
, UINT32 clu
)
2327 INT32 i
, map_i
, map_b
;
2328 UINT32 clu_base
, clu_free
;
2330 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2331 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
2333 clu_base
= (clu
& ~(0x7)) + 2;
2334 clu_mask
= (1 << (clu
- clu_base
+ 2)) - 1;
2336 map_i
= clu
>> (p_bd
->sector_size_bits
+ 3);
2337 map_b
= (clu
>> 3) & p_bd
->sector_size_mask
;
2339 for (i
= 2; i
< p_fs
->num_clusters
; i
+= 8) {
2340 k
= *(((UINT8
*) p_fs
->vol_amap
[map_i
]->b_data
) + map_b
);
2346 clu_free
= clu_base
+ free_bit
[k
];
2347 if (clu_free
< p_fs
->num_clusters
)
2352 if (((++map_b
) >= p_bd
->sector_size
) || (clu_base
>= p_fs
->num_clusters
)) {
2353 if ((++map_i
) >= p_fs
->map_sectors
) {
2361 return(CLUSTER_32(~0));
2362 } /* end of test_alloc_bitmap */
2364 void sync_alloc_bitmap(struct super_block
*sb
)
2367 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2369 if (p_fs
->vol_amap
== NULL
)
2372 for (i
= 0; i
< p_fs
->map_sectors
; i
++) {
2373 sync_dirty_buffer(p_fs
->vol_amap
[i
]);
2375 } /* end of sync_alloc_bitmap */
2378 * Upcase table Management Functions
2380 INT32
__load_upcase_table(struct super_block
*sb
, UINT32 sector
, UINT32 num_sectors
, UINT32 utbl_checksum
)
2382 INT32 i
, ret
= FFS_ERROR
;
2384 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2385 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
2386 struct buffer_head
*tmp_bh
= NULL
;
2391 UINT16
**upcase_table
;
2393 UINT32 checksum
= 0;
2395 upcase_table
= p_fs
->vol_utbl
= (UINT16
**) MALLOC(UTBL_COL_COUNT
* sizeof(UINT16
*));
2396 if(upcase_table
== NULL
)
2397 return FFS_MEMORYERR
;
2398 MEMSET(upcase_table
, 0, UTBL_COL_COUNT
* sizeof(UINT16
*));
2400 num_sectors
+= sector
;
2402 while(sector
< num_sectors
) {
2403 ret
= sector_read(sb
, sector
, &tmp_bh
, 1);
2404 if (ret
!= FFS_SUCCESS
) {
2405 PRINTK("sector read (0x%X)fail\n", sector
);
2410 for(i
= 0; i
< p_bd
->sector_size
&& index
<= 0xFFFF; i
+= 2) {
2411 uni
= GET16(((UINT8
*) tmp_bh
->b_data
)+i
);
2413 checksum
= ((checksum
& 1) ? 0x80000000 : 0 ) + (checksum
>> 1) + *(((UINT8
*) tmp_bh
->b_data
)+i
);
2414 checksum
= ((checksum
& 1) ? 0x80000000 : 0 ) + (checksum
>> 1) + *(((UINT8
*) tmp_bh
->b_data
)+(i
+1));
2417 PRINTK("skip from 0x%X ", index
);
2419 PRINTK("to 0x%X (amount of 0x%X)\n", index
, uni
);
2421 } else if(uni
== index
)
2423 else if(uni
== 0xFFFF)
2425 else { /* uni != index , uni != 0xFFFF */
2426 UINT16 col_index
= get_col_index(index
);
2428 if(upcase_table
[col_index
]== NULL
) {
2429 PRINTK("alloc = 0x%X\n", col_index
);
2430 upcase_table
[col_index
] = (UINT16
*) MALLOC(UTBL_ROW_COUNT
* sizeof(UINT16
));
2431 if(upcase_table
[col_index
] == NULL
) {
2432 ret
= FFS_MEMORYERR
;
2436 for(j
= 0 ; j
< UTBL_ROW_COUNT
; j
++)
2437 upcase_table
[col_index
][j
] = (col_index
<< LOW_INDEX_BIT
) | j
;
2440 upcase_table
[col_index
][get_row_index(index
)] = uni
;
2445 if(index
>= 0xFFFF && utbl_checksum
== checksum
) {
2454 free_upcase_table(sb
);
2458 INT32
__load_default_upcase_table(struct super_block
*sb
)
2460 INT32 i
, ret
= FFS_ERROR
;
2462 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2467 UINT16
**upcase_table
;
2469 upcase_table
= p_fs
->vol_utbl
= (UINT16
**) MALLOC(UTBL_COL_COUNT
* sizeof(UINT16
*));
2470 if(upcase_table
== NULL
)
2471 return FFS_MEMORYERR
;
2472 MEMSET(upcase_table
, 0, UTBL_COL_COUNT
* sizeof(UINT16
*));
2474 for(i
= 0; index
<= 0xFFFF && i
< NUM_UPCASE
*2; i
+= 2) {
2475 uni
= GET16(uni_upcase
+ i
);
2477 PRINTK("skip from 0x%X ", index
);
2479 PRINTK("to 0x%X (amount of 0x%X)\n", index
, uni
);
2481 } else if(uni
== index
)
2483 else if(uni
== 0xFFFF)
2485 else { /* uni != index , uni != 0xFFFF */
2486 UINT16 col_index
= get_col_index(index
);
2488 if(upcase_table
[col_index
]== NULL
) {
2489 PRINTK("alloc = 0x%X\n", col_index
);
2490 upcase_table
[col_index
] = (UINT16
*) MALLOC(UTBL_ROW_COUNT
* sizeof(UINT16
));
2491 if(upcase_table
[col_index
] == NULL
) {
2492 ret
= FFS_MEMORYERR
;
2496 for(j
= 0 ; j
< UTBL_ROW_COUNT
; j
++)
2497 upcase_table
[col_index
][j
] = (col_index
<< LOW_INDEX_BIT
) | j
;
2500 upcase_table
[col_index
][get_row_index(index
)] = uni
;
2509 /* FATAL error: default upcase table has error */
2510 free_upcase_table(sb
);
2514 INT32
load_upcase_table(struct super_block
*sb
)
2517 UINT32 tbl_clu
, tbl_size
;
2518 UINT32 type
, sector
, num_sectors
;
2521 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2522 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
2524 clu
.dir
= p_fs
->root_dir
;
2527 if (p_fs
->dev_ejected
)
2528 return FFS_MEDIAERR
;
2530 while (clu
.dir
!= CLUSTER_32(~0)) {
2531 for (i
= 0; i
< p_fs
->dentries_per_clu
; i
++) {
2532 ep
= (CASE_DENTRY_T
*) get_entry_in_dir(sb
, &clu
, i
, NULL
);
2534 return FFS_MEDIAERR
;
2536 type
= p_fs
->fs_func
->get_entry_type((DENTRY_T
*) ep
);
2538 if (type
== TYPE_UNUSED
)
2540 if (type
!= TYPE_UPCASE
)
2543 tbl_clu
= GET32_A(ep
->start_clu
);
2544 tbl_size
= (UINT32
) GET64_A(ep
->size
);
2546 sector
= START_SECTOR(tbl_clu
);
2547 num_sectors
= ((tbl_size
-1) >> p_bd
->sector_size_bits
) + 1;
2548 if(__load_upcase_table(sb
, sector
, num_sectors
, GET32_A(ep
->checksum
)) != FFS_SUCCESS
)
2553 if (FAT_read(sb
, clu
.dir
, &(clu
.dir
)) != 0)
2554 return FFS_MEDIAERR
;
2556 /* load default upcase table */
2557 return __load_default_upcase_table(sb
);
2558 } /* end of load_upcase_table */
2560 void free_upcase_table(struct super_block
*sb
)
2563 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
2564 UINT16
**upcase_table
;
2566 upcase_table
= p_fs
->vol_utbl
;
2567 for(i
= 0 ; i
< UTBL_COL_COUNT
; i
++)
2568 FREE(upcase_table
[i
]);
2570 FREE(p_fs
->vol_utbl
);
2572 p_fs
->vol_utbl
= NULL
;
2573 } /* end of free_upcase_table */
2576 * Directory Entry Management Functions
2579 UINT32
fat_get_entry_type(DENTRY_T
*p_entry
)
2581 DOS_DENTRY_T
*ep
= (DOS_DENTRY_T
*) p_entry
;
2583 if (*(ep
->name
) == 0x0)
2586 else if (*(ep
->name
) == 0xE5)
2587 return TYPE_DELETED
;
2589 else if (ep
->attr
== ATTR_EXTEND
)
2592 else if ((ep
->attr
& (ATTR_SUBDIR
|ATTR_VOLUME
)) == ATTR_VOLUME
)
2595 else if ((ep
->attr
& (ATTR_SUBDIR
|ATTR_VOLUME
)) == ATTR_SUBDIR
)
2599 } /* end of fat_get_entry_type */
2601 UINT32
exfat_get_entry_type(DENTRY_T
*p_entry
)
2603 FILE_DENTRY_T
*ep
= (FILE_DENTRY_T
*) p_entry
;
2605 if (ep
->type
== 0x0) {
2607 } else if (ep
->type
< 0x80) {
2608 return TYPE_DELETED
;
2609 } else if (ep
->type
== 0x80) {
2610 return TYPE_INVALID
;
2611 } else if (ep
->type
< 0xA0) {
2612 if (ep
->type
== 0x81) {
2614 } else if (ep
->type
== 0x82) {
2616 } else if (ep
->type
== 0x83) {
2618 } else if (ep
->type
== 0x85) {
2619 if (GET16_A(ep
->attr
) & ATTR_SUBDIR
)
2624 return TYPE_CRITICAL_PRI
;
2625 } else if (ep
->type
< 0xC0) {
2626 if (ep
->type
== 0xA0) {
2628 } else if (ep
->type
== 0xA1) {
2629 return TYPE_PADDING
;
2630 } else if (ep
->type
== 0xA2) {
2633 return TYPE_BENIGN_PRI
;
2634 } else if (ep
->type
< 0xE0) {
2635 if (ep
->type
== 0xC0) {
2637 } else if (ep
->type
== 0xC1) {
2639 } else if (ep
->type
== 0xC2) {
2642 return TYPE_CRITICAL_SEC
;
2645 return TYPE_BENIGN_SEC
;
2646 } /* end of exfat_get_entry_type */
2648 void fat_set_entry_type(DENTRY_T
*p_entry
, UINT32 type
)
2650 DOS_DENTRY_T
*ep
= (DOS_DENTRY_T
*) p_entry
;
2652 if (type
== TYPE_UNUSED
)
2655 else if (type
== TYPE_DELETED
)
2658 else if (type
== TYPE_EXTEND
)
2659 ep
->attr
= ATTR_EXTEND
;
2661 else if (type
== TYPE_DIR
)
2662 ep
->attr
= ATTR_SUBDIR
;
2664 else if (type
== TYPE_FILE
)
2665 ep
->attr
= ATTR_ARCHIVE
;
2667 else if (type
== TYPE_SYMLINK
)
2668 ep
->attr
= ATTR_ARCHIVE
| ATTR_SYMLINK
;
2669 } /* end of fat_set_entry_type */
2671 void exfat_set_entry_type(DENTRY_T
*p_entry
, UINT32 type
)
2673 FILE_DENTRY_T
*ep
= (FILE_DENTRY_T
*) p_entry
;
2675 if (type
== TYPE_UNUSED
) {
2677 } else if (type
== TYPE_DELETED
) {
2679 } else if (type
== TYPE_STREAM
) {
2681 } else if (type
== TYPE_EXTEND
) {
2683 } else if (type
== TYPE_BITMAP
) {
2685 } else if (type
== TYPE_UPCASE
) {
2687 } else if (type
== TYPE_VOLUME
) {
2689 } else if (type
== TYPE_DIR
) {
2691 SET16_A(ep
->attr
, ATTR_SUBDIR
);
2692 } else if (type
== TYPE_FILE
) {
2694 SET16_A(ep
->attr
, ATTR_ARCHIVE
);
2695 } else if (type
== TYPE_SYMLINK
) {
2697 SET16_A(ep
->attr
, ATTR_ARCHIVE
| ATTR_SYMLINK
);
2699 } /* end of exfat_set_entry_type */
2701 UINT32
fat_get_entry_attr(DENTRY_T
*p_entry
)
2703 DOS_DENTRY_T
*ep
= (DOS_DENTRY_T
*) p_entry
;
2704 return((UINT32
) ep
->attr
);
2705 } /* end of fat_get_entry_attr */
2707 UINT32
exfat_get_entry_attr(DENTRY_T
*p_entry
)
2709 FILE_DENTRY_T
*ep
= (FILE_DENTRY_T
*) p_entry
;
2710 return((UINT32
) GET16_A(ep
->attr
));
2711 } /* end of exfat_get_entry_attr */
2713 void fat_set_entry_attr(DENTRY_T
*p_entry
, UINT32 attr
)
2715 DOS_DENTRY_T
*ep
= (DOS_DENTRY_T
*) p_entry
;
2716 ep
->attr
= (UINT8
) attr
;
2717 } /* end of fat_set_entry_attr */
2719 void exfat_set_entry_attr(DENTRY_T
*p_entry
, UINT32 attr
)
2721 FILE_DENTRY_T
*ep
= (FILE_DENTRY_T
*) p_entry
;
2722 SET16_A(ep
->attr
, (UINT16
) attr
);
2723 } /* end of exfat_set_entry_attr */
2725 UINT8
fat_get_entry_flag(DENTRY_T
*p_entry
)
2728 } /* end of fat_get_entry_flag */
2730 UINT8
exfat_get_entry_flag(DENTRY_T
*p_entry
)
2732 STRM_DENTRY_T
*ep
= (STRM_DENTRY_T
*) p_entry
;
2734 } /* end of exfat_get_entry_flag */
2736 void fat_set_entry_flag(DENTRY_T
*p_entry
, UINT8 flags
)
2738 } /* end of fat_set_entry_flag */
2740 void exfat_set_entry_flag(DENTRY_T
*p_entry
, UINT8 flags
)
2742 STRM_DENTRY_T
*ep
= (STRM_DENTRY_T
*) p_entry
;
2744 } /* end of exfat_set_entry_flag */
2746 UINT32
fat_get_entry_clu0(DENTRY_T
*p_entry
)
2748 DOS_DENTRY_T
*ep
= (DOS_DENTRY_T
*) p_entry
;
2749 return((GET32_A(ep
->start_clu_hi
) << 16) | GET16_A(ep
->start_clu_lo
));
2750 } /* end of fat_get_entry_clu0 */
2752 UINT32
exfat_get_entry_clu0(DENTRY_T
*p_entry
)
2754 STRM_DENTRY_T
*ep
= (STRM_DENTRY_T
*) p_entry
;
2755 return(GET32_A(ep
->start_clu
));
2756 } /* end of exfat_get_entry_clu0 */
2758 void fat_set_entry_clu0(DENTRY_T
*p_entry
, UINT32 start_clu
)
2760 DOS_DENTRY_T
*ep
= (DOS_DENTRY_T
*) p_entry
;
2761 SET16_A(ep
->start_clu_lo
, CLUSTER_16(start_clu
));
2762 SET16_A(ep
->start_clu_hi
, CLUSTER_16(start_clu
>> 16));
2763 } /* end of fat_set_entry_clu0 */
2765 void exfat_set_entry_clu0(DENTRY_T
*p_entry
, UINT32 start_clu
)
2767 STRM_DENTRY_T
*ep
= (STRM_DENTRY_T
*) p_entry
;
2768 SET32_A(ep
->start_clu
, start_clu
);
2769 } /* end of exfat_set_entry_clu0 */
2771 UINT64
fat_get_entry_size(DENTRY_T
*p_entry
)
2773 DOS_DENTRY_T
*ep
= (DOS_DENTRY_T
*) p_entry
;
2774 return((UINT64
) GET32_A(ep
->size
));
2775 } /* end of fat_get_entry_size */
2777 UINT64
exfat_get_entry_size(DENTRY_T
*p_entry
)
2779 STRM_DENTRY_T
*ep
= (STRM_DENTRY_T
*) p_entry
;
2780 return(GET64_A(ep
->valid_size
));
2781 } /* end of exfat_get_entry_size */
2783 void fat_set_entry_size(DENTRY_T
*p_entry
, UINT64 size
)
2785 DOS_DENTRY_T
*ep
= (DOS_DENTRY_T
*) p_entry
;
2786 SET32_A(ep
->size
, (UINT32
) size
);
2787 } /* end of fat_set_entry_size */
2789 void exfat_set_entry_size(DENTRY_T
*p_entry
, UINT64 size
)
2791 STRM_DENTRY_T
*ep
= (STRM_DENTRY_T
*) p_entry
;
2792 SET64_A(ep
->valid_size
, size
);
2793 SET64_A(ep
->size
, size
);
2794 } /* end of exfat_set_entry_size */
2796 void fat_get_entry_time(DENTRY_T
*p_entry
, TIMESTAMP_T
*tp
, UINT8 mode
)
2798 UINT16 t
= 0x00, d
= 0x21;
2799 DOS_DENTRY_T
*ep
= (DOS_DENTRY_T
*) p_entry
;
2803 t
= GET16_A(ep
->create_time
);
2804 d
= GET16_A(ep
->create_date
);
2807 t
= GET16_A(ep
->modify_time
);
2808 d
= GET16_A(ep
->modify_date
);
2812 tp
->sec
= (t
& 0x001F) << 1;
2813 tp
->min
= (t
>> 5) & 0x003F;
2814 tp
->hour
= (t
>> 11);
2815 tp
->day
= (d
& 0x001F);
2816 tp
->mon
= (d
>> 5) & 0x000F;
2817 tp
->year
= (d
>> 9);
2818 } /* end of fat_get_entry_time */
2820 void exfat_get_entry_time(DENTRY_T
*p_entry
, TIMESTAMP_T
*tp
, UINT8 mode
)
2822 UINT16 t
= 0x00, d
= 0x21;
2823 FILE_DENTRY_T
*ep
= (FILE_DENTRY_T
*) p_entry
;
2827 t
= GET16_A(ep
->create_time
);
2828 d
= GET16_A(ep
->create_date
);
2831 t
= GET16_A(ep
->modify_time
);
2832 d
= GET16_A(ep
->modify_date
);
2835 t
= GET16_A(ep
->access_time
);
2836 d
= GET16_A(ep
->access_date
);
2840 tp
->sec
= (t
& 0x001F) << 1;
2841 tp
->min
= (t
>> 5) & 0x003F;
2842 tp
->hour
= (t
>> 11);
2843 tp
->day
= (d
& 0x001F);
2844 tp
->mon
= (d
>> 5) & 0x000F;
2845 tp
->year
= (d
>> 9);
2846 } /* end of exfat_get_entry_time */
2848 void fat_set_entry_time(DENTRY_T
*p_entry
, TIMESTAMP_T
*tp
, UINT8 mode
)
2851 DOS_DENTRY_T
*ep
= (DOS_DENTRY_T
*) p_entry
;
2853 t
= (tp
->hour
<< 11) | (tp
->min
<< 5) | (tp
->sec
>> 1);
2854 d
= (tp
->year
<< 9) | (tp
->mon
<< 5) | tp
->day
;
2858 SET16_A(ep
->create_time
, t
);
2859 SET16_A(ep
->create_date
, d
);
2862 SET16_A(ep
->modify_time
, t
);
2863 SET16_A(ep
->modify_date
, d
);
2866 } /* end of fat_set_entry_time */
2868 void exfat_set_entry_time(DENTRY_T
*p_entry
, TIMESTAMP_T
*tp
, UINT8 mode
)
2871 FILE_DENTRY_T
*ep
= (FILE_DENTRY_T
*) p_entry
;
2873 t
= (tp
->hour
<< 11) | (tp
->min
<< 5) | (tp
->sec
>> 1);
2874 d
= (tp
->year
<< 9) | (tp
->mon
<< 5) | tp
->day
;
2878 SET16_A(ep
->create_time
, t
);
2879 SET16_A(ep
->create_date
, d
);
2882 SET16_A(ep
->modify_time
, t
);
2883 SET16_A(ep
->modify_date
, d
);
2886 SET16_A(ep
->access_time
, t
);
2887 SET16_A(ep
->access_date
, d
);
2890 } /* end of exfat_set_entry_time */
2892 INT32
fat_init_dir_entry(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, UINT32 type
,
2893 UINT32 start_clu
, UINT64 size
)
2896 DOS_DENTRY_T
*dos_ep
;
2898 dos_ep
= (DOS_DENTRY_T
*) get_entry_in_dir(sb
, p_dir
, entry
, §or
);
2900 return FFS_MEDIAERR
;
2902 init_dos_entry(dos_ep
, type
, start_clu
);
2903 buf_modify(sb
, sector
);
2906 } /* end of fat_init_dir_entry */
2908 INT32
exfat_init_dir_entry(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, UINT32 type
,
2909 UINT32 start_clu
, UINT64 size
)
2913 FILE_DENTRY_T
*file_ep
;
2914 STRM_DENTRY_T
*strm_ep
;
2916 flags
= (type
== TYPE_FILE
) ? 0x01 : 0x03;
2918 /* we cannot use get_entry_set_in_dir here because file ep is not initialized yet */
2919 file_ep
= (FILE_DENTRY_T
*) get_entry_in_dir(sb
, p_dir
, entry
, §or
);
2921 return FFS_MEDIAERR
;
2923 strm_ep
= (STRM_DENTRY_T
*) get_entry_in_dir(sb
, p_dir
, entry
+1, §or
);
2925 return FFS_MEDIAERR
;
2927 init_file_entry(file_ep
, type
);
2928 buf_modify(sb
, sector
);
2930 init_strm_entry(strm_ep
, flags
, start_clu
, size
);
2931 buf_modify(sb
, sector
);
2934 } /* end of exfat_init_dir_entry */
2936 INT32
fat_init_ext_entry(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, INT32 num_entries
,
2937 UNI_NAME_T
*p_uniname
, DOS_NAME_T
*p_dosname
)
2942 UINT16
*uniname
= p_uniname
->name
;
2943 DOS_DENTRY_T
*dos_ep
;
2944 EXT_DENTRY_T
*ext_ep
;
2946 dos_ep
= (DOS_DENTRY_T
*) get_entry_in_dir(sb
, p_dir
, entry
, §or
);
2948 return FFS_MEDIAERR
;
2950 dos_ep
->lcase
= p_dosname
->name_case
;
2951 MEMCPY(dos_ep
->name
, p_dosname
->name
, DOS_NAME_LENGTH
);
2952 buf_modify(sb
, sector
);
2954 if ((--num_entries
) > 0) {
2955 chksum
= calc_checksum_1byte((void *) dos_ep
->name
, DOS_NAME_LENGTH
, 0);
2957 for (i
= 1; i
< num_entries
; i
++) {
2958 ext_ep
= (EXT_DENTRY_T
*) get_entry_in_dir(sb
, p_dir
, entry
-i
, §or
);
2960 return FFS_MEDIAERR
;
2962 init_ext_entry(ext_ep
, i
, chksum
, uniname
);
2963 buf_modify(sb
, sector
);
2967 ext_ep
= (EXT_DENTRY_T
*) get_entry_in_dir(sb
, p_dir
, entry
-i
, §or
);
2969 return FFS_MEDIAERR
;
2971 init_ext_entry(ext_ep
, i
+0x40, chksum
, uniname
);
2972 buf_modify(sb
, sector
);
2976 } /* end of fat_init_ext_entry */
2978 INT32
exfat_init_ext_entry(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, INT32 num_entries
,
2979 UNI_NAME_T
*p_uniname
, DOS_NAME_T
*p_dosname
)
2983 UINT16
*uniname
= p_uniname
->name
;
2984 FILE_DENTRY_T
*file_ep
;
2985 STRM_DENTRY_T
*strm_ep
;
2986 NAME_DENTRY_T
*name_ep
;
2988 file_ep
= (FILE_DENTRY_T
*) get_entry_in_dir(sb
, p_dir
, entry
, §or
);
2990 return FFS_MEDIAERR
;
2992 file_ep
->num_ext
= (UINT8
)(num_entries
- 1);
2993 buf_modify(sb
, sector
);
2995 strm_ep
= (STRM_DENTRY_T
*) get_entry_in_dir(sb
, p_dir
, entry
+1, §or
);
2997 return FFS_MEDIAERR
;
2999 strm_ep
->name_len
= p_uniname
->name_len
;
3000 SET16_A(strm_ep
->name_hash
, p_uniname
->name_hash
);
3001 buf_modify(sb
, sector
);
3003 for (i
= 2; i
< num_entries
; i
++) {
3004 name_ep
= (NAME_DENTRY_T
*) get_entry_in_dir(sb
, p_dir
, entry
+i
, §or
);
3006 return FFS_MEDIAERR
;
3008 init_name_entry(name_ep
, uniname
);
3009 buf_modify(sb
, sector
);
3013 update_dir_checksum(sb
, p_dir
, entry
);
3016 } /* end of exfat_init_ext_entry */
3018 void init_dos_entry(DOS_DENTRY_T
*ep
, UINT32 type
, UINT32 start_clu
)
3020 TIMESTAMP_T tm
, *tp
;
3022 fat_set_entry_type((DENTRY_T
*) ep
, type
);
3023 SET16_A(ep
->start_clu_lo
, CLUSTER_16(start_clu
));
3024 SET16_A(ep
->start_clu_hi
, CLUSTER_16(start_clu
>> 16));
3025 SET32_A(ep
->size
, 0);
3027 tp
= tm_current(&tm
);
3028 fat_set_entry_time((DENTRY_T
*) ep
, tp
, TM_CREATE
);
3029 fat_set_entry_time((DENTRY_T
*) ep
, tp
, TM_MODIFY
);
3030 SET16_A(ep
->access_date
, 0);
3031 ep
->create_time_ms
= 0;
3032 } /* end of init_dos_entry */
3034 void init_ext_entry(EXT_DENTRY_T
*ep
, INT32 order
, UINT8 chksum
, UINT16
*uniname
)
3039 fat_set_entry_type((DENTRY_T
*) ep
, TYPE_EXTEND
);
3040 ep
->order
= (UINT8
) order
;
3042 ep
->checksum
= chksum
;
3043 SET16_A(ep
->start_clu
, 0);
3045 for (i
= 0; i
< 10; i
+= 2) {
3047 SET16(ep
->unicode_0_4
+i
, *uniname
);
3048 if (*uniname
== 0x0)
3053 SET16(ep
->unicode_0_4
+i
, 0xFFFF);
3057 for (i
= 0; i
< 12; i
+= 2) {
3059 SET16_A(ep
->unicode_5_10
+i
, *uniname
);
3060 if (*uniname
== 0x0)
3065 SET16_A(ep
->unicode_5_10
+i
, 0xFFFF);
3069 for (i
= 0; i
< 4; i
+= 2) {
3071 SET16_A(ep
->unicode_11_12
+i
, *uniname
);
3072 if (*uniname
== 0x0)
3077 SET16_A(ep
->unicode_11_12
+i
, 0xFFFF);
3080 } /* end of init_ext_entry */
3082 void init_file_entry(FILE_DENTRY_T
*ep
, UINT32 type
)
3084 TIMESTAMP_T tm
, *tp
;
3086 exfat_set_entry_type((DENTRY_T
*) ep
, type
);
3088 tp
= tm_current(&tm
);
3089 exfat_set_entry_time((DENTRY_T
*) ep
, tp
, TM_CREATE
);
3090 exfat_set_entry_time((DENTRY_T
*) ep
, tp
, TM_MODIFY
);
3091 exfat_set_entry_time((DENTRY_T
*) ep
, tp
, TM_ACCESS
);
3092 ep
->create_time_ms
= 0;
3093 ep
->modify_time_ms
= 0;
3094 ep
->access_time_ms
= 0;
3095 } /* end of init_file_entry */
3097 void init_strm_entry(STRM_DENTRY_T
*ep
, UINT8 flags
, UINT32 start_clu
, UINT64 size
)
3099 exfat_set_entry_type((DENTRY_T
*) ep
, TYPE_STREAM
);
3101 SET32_A(ep
->start_clu
, start_clu
);
3102 SET64_A(ep
->valid_size
, size
);
3103 SET64_A(ep
->size
, size
);
3104 } /* end of init_strm_entry */
3106 void init_name_entry(NAME_DENTRY_T
*ep
, UINT16
*uniname
)
3110 exfat_set_entry_type((DENTRY_T
*) ep
, TYPE_EXTEND
);
3113 for (i
= 0; i
< 30; i
++, i
++) {
3114 SET16_A(ep
->unicode_0_14
+i
, *uniname
);
3115 if (*uniname
== 0x0)
3119 } /* end of init_name_entry */
3121 void fat_delete_dir_entry(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, INT32 order
, INT32 num_entries
)
3126 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3128 for (i
= num_entries
-1; i
>= order
; i
--) {
3129 ep
= get_entry_in_dir(sb
, p_dir
, entry
-i
, §or
);
3133 p_fs
->fs_func
->set_entry_type(ep
, TYPE_DELETED
);
3134 buf_modify(sb
, sector
);
3136 } /* end of fat_delete_dir_entry */
3138 void exfat_delete_dir_entry(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, INT32 order
, INT32 num_entries
)
3143 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3145 for (i
= order
; i
< num_entries
; i
++) {
3146 ep
= get_entry_in_dir(sb
, p_dir
, entry
+i
, §or
);
3150 p_fs
->fs_func
->set_entry_type(ep
, TYPE_DELETED
);
3151 buf_modify(sb
, sector
);
3153 } /* end of exfat_delete_dir_entry */
3155 void update_dir_checksum(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
)
3157 INT32 i
, num_entries
;
3160 FILE_DENTRY_T
*file_ep
;
3163 file_ep
= (FILE_DENTRY_T
*) get_entry_in_dir(sb
, p_dir
, entry
, §or
);
3167 buf_lock(sb
, sector
);
3169 num_entries
= (INT32
) file_ep
->num_ext
+ 1;
3170 chksum
= calc_checksum_2byte((void *) file_ep
, DENTRY_SIZE
, 0, CS_DIR_ENTRY
);
3172 for (i
= 1; i
< num_entries
; i
++) {
3173 ep
= get_entry_in_dir(sb
, p_dir
, entry
+i
, NULL
);
3175 buf_unlock(sb
, sector
);
3179 chksum
= calc_checksum_2byte((void *) ep
, DENTRY_SIZE
, chksum
, CS_DEFAULT
);
3182 SET16_A(file_ep
->checksum
, chksum
);
3183 buf_modify(sb
, sector
);
3184 buf_unlock(sb
, sector
);
3185 } /* end of update_dir_checksum */
3187 void update_dir_checksum_with_entry_set (struct super_block
*sb
, ENTRY_SET_CACHE_T
*es
)
3191 INT32 chksum_type
= CS_DIR_ENTRY
, i
;
3193 ep
= (DENTRY_T
*)&(es
->__buf
);
3194 for (i
=0; i
< es
->num_entries
; i
++) {
3195 PRINTK ("update_dir_checksum_with_entry_set ep %p\n", ep
);
3196 chksum
= calc_checksum_2byte((void *) ep
, DENTRY_SIZE
, chksum
, chksum_type
);
3198 chksum_type
= CS_DEFAULT
;
3201 ep
= (DENTRY_T
*)&(es
->__buf
);
3202 SET16_A(((FILE_DENTRY_T
*)ep
)->checksum
, chksum
);
3203 write_whole_entry_set(sb
, es
);
3206 static INT32
_walk_fat_chain (struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 byte_offset
, UINT32
*clu
)
3208 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3212 clu_offset
= byte_offset
>> p_fs
->cluster_size_bits
;
3213 cur_clu
= p_dir
->dir
;
3215 if (p_dir
->flags
== 0x03) {
3216 cur_clu
+= clu_offset
;
3218 while (clu_offset
> 0) {
3219 if (FAT_read(sb
, cur_clu
, &cur_clu
) == -1)
3220 return FFS_MEDIAERR
;
3229 INT32
find_location(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, UINT32
*sector
, INT32
*offset
)
3233 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3234 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
3236 off
= entry
<< DENTRY_SIZE_BITS
;
3238 if (p_dir
->dir
== CLUSTER_32(0)) { /* FAT16 root_dir */
3239 *offset
= off
& p_bd
->sector_size_mask
;
3240 *sector
= off
>> p_bd
->sector_size_bits
;
3241 *sector
+= p_fs
->root_start_sector
;
3243 ret
=_walk_fat_chain(sb
, p_dir
, off
, &clu
);
3244 if (ret
!= FFS_SUCCESS
)
3247 off
&= p_fs
->cluster_size
- 1; /* byte offset in cluster */
3249 *offset
= off
& p_bd
->sector_size_mask
; /* byte offset in sector */
3250 *sector
= off
>> p_bd
->sector_size_bits
; /* sector offset in cluster */
3251 *sector
+= START_SECTOR(clu
);
3254 } /* end of find_location */
3256 DENTRY_T
*get_entry_with_sector(struct super_block
*sb
, UINT32 sector
, INT32 offset
)
3260 buf
= buf_getblk(sb
, sector
);
3265 return((DENTRY_T
*)(buf
+ offset
));
3266 } /* end of get_entry_with_sector */
3268 DENTRY_T
*get_entry_in_dir(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, UINT32
*sector
)
3274 if (find_location(sb
, p_dir
, entry
, &sec
, &off
) != FFS_SUCCESS
)
3277 buf
= buf_getblk(sb
, sec
);
3284 return((DENTRY_T
*)(buf
+ off
));
3285 } /* end of get_entry_in_dir */
3288 /* returns a set of dentries for a file or dir.
3289 * Note that this is a copy (dump) of dentries so that user should call write_entry_set()
3290 * to apply changes made in this entry set to the real device.
3292 * sb+p_dir+entry: indicates a file/dir
3293 * type: specifies how many dentries should be included.
3295 * file_ep: will point the first dentry(= file dentry) on success
3297 * pointer of entry set on success,
3301 #define ES_MODE_STARTED 0
3302 #define ES_MODE_GET_FILE_ENTRY 1
3303 #define ES_MODE_GET_STRM_ENTRY 2
3304 #define ES_MODE_GET_NAME_ENTRY 3
3305 #define ES_MODE_GET_CRITICAL_SEC_ENTRY 4
3306 ENTRY_SET_CACHE_T
*get_entry_set_in_dir (struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, UINT32 type
, DENTRY_T
**file_ep
)
3308 INT32 off
, ret
, byte_offset
;
3310 UINT32 sec
, entry_type
;
3311 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3312 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
3313 ENTRY_SET_CACHE_T
*es
= NULL
;
3317 INT32 mode
= ES_MODE_STARTED
;
3319 PRINTK("get_entry_set_in_dir entered\n");
3320 PRINTK("p_dir dir %u flags %x size %d\n", p_dir
->dir
, p_dir
->flags
, p_dir
->size
);
3322 byte_offset
= entry
<< DENTRY_SIZE_BITS
;
3323 ret
=_walk_fat_chain(sb
, p_dir
, byte_offset
, &clu
);
3324 if (ret
!= FFS_SUCCESS
)
3328 byte_offset
&= p_fs
->cluster_size
- 1; /* byte offset in cluster */
3330 off
= byte_offset
& p_bd
->sector_size_mask
; /* byte offset in sector */
3331 sec
= byte_offset
>> p_bd
->sector_size_bits
; /* sector offset in cluster */
3332 sec
+= START_SECTOR(clu
);
3334 buf
= buf_getblk(sb
, sec
);
3339 ep
= (DENTRY_T
*)(buf
+ off
);
3340 entry_type
= p_fs
->fs_func
->get_entry_type(ep
);
3342 if ((entry_type
!= TYPE_FILE
)
3343 && (entry_type
!= TYPE_DIR
))
3346 if (type
== ES_ALL_ENTRIES
)
3347 num_entries
= ((FILE_DENTRY_T
*)ep
)->num_ext
+1;
3351 PRINTK("trying to malloc %x bytes for %d entries\n", offsetof(ENTRY_SET_CACHE_T
, __buf
) + (num_entries
) * sizeof(DENTRY_T
), num_entries
);
3352 es
= MALLOC(offsetof(ENTRY_SET_CACHE_T
, __buf
) + (num_entries
) * sizeof(DENTRY_T
));
3356 es
->num_entries
= num_entries
;
3359 es
->alloc_flag
= p_dir
->flags
;
3361 pos
= (DENTRY_T
*) &(es
->__buf
);
3363 while(num_entries
) {
3364 /* instead of copying whole sector, we will check every entry.
3365 * this will provide minimum stablity and consistancy.
3368 entry_type
= p_fs
->fs_func
->get_entry_type(ep
);
3370 if ((entry_type
== TYPE_UNUSED
) || (entry_type
== TYPE_DELETED
))
3374 case ES_MODE_STARTED
:
3375 if ((entry_type
== TYPE_FILE
) || (entry_type
== TYPE_DIR
))
3376 mode
= ES_MODE_GET_FILE_ENTRY
;
3380 case ES_MODE_GET_FILE_ENTRY
:
3381 if (entry_type
== TYPE_STREAM
)
3382 mode
= ES_MODE_GET_STRM_ENTRY
;
3386 case ES_MODE_GET_STRM_ENTRY
:
3387 if (entry_type
== TYPE_EXTEND
)
3388 mode
= ES_MODE_GET_NAME_ENTRY
;
3392 case ES_MODE_GET_NAME_ENTRY
:
3393 if (entry_type
== TYPE_EXTEND
)
3395 else if (entry_type
== TYPE_STREAM
)
3397 else if (entry_type
& TYPE_CRITICAL_SEC
)
3398 mode
= ES_MODE_GET_CRITICAL_SEC_ENTRY
;
3402 case ES_MODE_GET_CRITICAL_SEC_ENTRY
:
3403 if ((entry_type
== TYPE_EXTEND
) || (entry_type
== TYPE_STREAM
))
3405 else if ((entry_type
& TYPE_CRITICAL_SEC
) != TYPE_CRITICAL_SEC
)
3410 COPY_DENTRY(pos
, ep
);
3412 if (--num_entries
== 0)
3415 if (((off
+ DENTRY_SIZE
) & p_bd
->sector_size_mask
) < (off
& p_bd
->sector_size_mask
)) {
3416 /* get the next sector */
3417 if (IS_LAST_SECTOR_IN_CLUSTER(sec
)) {
3418 if (es
->alloc_flag
== 0x03) {
3421 if (FAT_read(sb
, clu
, &clu
) == -1)
3424 sec
= START_SECTOR(clu
);
3428 buf
= buf_getblk(sb
, sec
);
3432 ep
= (DENTRY_T
*)(buf
);
3441 *file_ep
= (DENTRY_T
*)&(es
->__buf
);
3443 PRINTK("es sec %u offset %d flags %d, num_entries %u buf ptr %p\n",
3444 es
->sector
, es
->offset
, es
->alloc_flag
, es
->num_entries
, &(es
->__buf
));
3445 PRINTK("get_entry_set_in_dir exited %p\n", es
);
3448 PRINTK("get_entry_set_in_dir exited NULL (es %p)\n", es
);
3453 void release_entry_set (ENTRY_SET_CACHE_T
*es
)
3455 PRINTK("release_entry_set %p\n", es
);
3460 static INT32
__write_partial_entries_in_entry_set (struct super_block
*sb
, ENTRY_SET_CACHE_T
*es
, UINT32 sec
, INT32 off
, UINT32 count
)
3462 INT32 num_entries
, buf_off
= (off
- es
->offset
);
3463 UINT32 remaining_byte_in_sector
, copy_entries
;
3464 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3465 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
3467 UINT8
*buf
, *esbuf
= (UINT8
*)&(es
->__buf
);
3469 PRINTK("__write_partial_entries_in_entry_set entered\n");
3470 PRINTK("es %p sec %u off %d count %d\n", es
, sec
, off
, count
);
3471 num_entries
= count
;
3473 while(num_entries
) {
3474 /* white per sector base */
3475 remaining_byte_in_sector
= (1 << p_bd
->sector_size_bits
) - off
;
3476 copy_entries
= MIN(remaining_byte_in_sector
>> DENTRY_SIZE_BITS
, num_entries
);
3477 buf
= buf_getblk(sb
, sec
);
3480 PRINTK("es->buf %p buf_off %u\n", esbuf
, buf_off
);
3481 PRINTK("copying %d entries from %p to sector %u\n", copy_entries
, (esbuf
+ buf_off
), sec
);
3482 MEMCPY(buf
+ off
, esbuf
+ buf_off
, copy_entries
<< DENTRY_SIZE_BITS
);
3483 buf_modify(sb
, sec
);
3484 num_entries
-= copy_entries
;
3487 /* get next sector */
3488 if (IS_LAST_SECTOR_IN_CLUSTER(sec
)) {
3489 clu
= GET_CLUSTER_FROM_SECTOR(sec
);
3490 if (es
->alloc_flag
== 0x03) {
3493 if (FAT_read(sb
, clu
, &clu
) == -1)
3496 sec
= START_SECTOR(clu
);
3501 buf_off
+= copy_entries
<< DENTRY_SIZE_BITS
;
3505 PRINTK("__write_partial_entries_in_entry_set exited successfully\n");
3508 PRINTK("__write_partial_entries_in_entry_set failed\n");
3512 /* write back all entries in entry set */
3513 INT32
write_whole_entry_set (struct super_block
*sb
, ENTRY_SET_CACHE_T
*es
)
3515 return (__write_partial_entries_in_entry_set(sb
, es
, es
->sector
,es
->offset
, es
->num_entries
));
3518 /* write back some entries in entry set */
3519 INT32
write_partial_entries_in_entry_set (struct super_block
*sb
, ENTRY_SET_CACHE_T
*es
, DENTRY_T
*ep
, UINT32 count
)
3521 INT32 ret
, byte_offset
, off
;
3523 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3524 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
3528 if (ep
+ count
> ((DENTRY_T
*)&(es
->__buf
)) + es
->num_entries
)
3531 dir
.dir
= GET_CLUSTER_FROM_SECTOR(es
->sector
);
3532 dir
.flags
= es
->alloc_flag
;
3533 dir
.size
= 0xffffffff; /* XXX */
3535 byte_offset
= (es
->sector
- START_SECTOR(dir
.dir
)) << p_bd
->sector_size_bits
;
3536 byte_offset
+= ((INT32
*)ep
- (INT32
*)&(es
->__buf
)) + es
->offset
;
3538 ret
=_walk_fat_chain(sb
, &dir
, byte_offset
, &clu
);
3539 if (ret
!= FFS_SUCCESS
)
3541 byte_offset
&= p_fs
->cluster_size
- 1; /* byte offset in cluster */
3542 off
= byte_offset
& p_bd
->sector_size_mask
; /* byte offset in sector */
3543 sec
= byte_offset
>> p_bd
->sector_size_bits
; /* sector offset in cluster */
3544 sec
+= START_SECTOR(clu
);
3545 return (__write_partial_entries_in_entry_set(sb
, es
, sec
, off
, count
));
3548 /* search EMPTY CONTINUOUS "num_entries" entries */
3549 INT32
search_deleted_or_unused_entry(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 num_entries
)
3551 INT32 i
, dentry
, num_empty
= 0;
3552 INT32 dentries_per_clu
;
3556 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3558 if (p_dir
->dir
== CLUSTER_32(0)) /* FAT16 root_dir */
3559 dentries_per_clu
= p_fs
->dentries_in_root
;
3561 dentries_per_clu
= p_fs
->dentries_per_clu
;
3563 if (p_fs
->hint_uentry
.dir
== p_dir
->dir
) {
3564 if (p_fs
->hint_uentry
.entry
== -1)
3567 clu
.dir
= p_fs
->hint_uentry
.clu
.dir
;
3568 clu
.size
= p_fs
->hint_uentry
.clu
.size
;
3569 clu
.flags
= p_fs
->hint_uentry
.clu
.flags
;
3571 dentry
= p_fs
->hint_uentry
.entry
;
3573 p_fs
->hint_uentry
.entry
= -1;
3575 clu
.dir
= p_dir
->dir
;
3576 clu
.size
= p_dir
->size
;
3577 clu
.flags
= p_dir
->flags
;
3582 while (clu
.dir
!= CLUSTER_32(~0)) {
3583 if (p_fs
->dev_ejected
)
3586 if (p_dir
->dir
== CLUSTER_32(0)) /* FAT16 root_dir */
3587 i
= dentry
% dentries_per_clu
;
3589 i
= dentry
& (dentries_per_clu
-1);
3591 for ( ; i
< dentries_per_clu
; i
++, dentry
++) {
3592 ep
= get_entry_in_dir(sb
, &clu
, i
, NULL
);
3596 type
= p_fs
->fs_func
->get_entry_type(ep
);
3598 if (type
== TYPE_UNUSED
) {
3600 if (p_fs
->hint_uentry
.entry
== -1) {
3601 p_fs
->hint_uentry
.dir
= p_dir
->dir
;
3602 p_fs
->hint_uentry
.entry
= dentry
;
3604 p_fs
->hint_uentry
.clu
.dir
= clu
.dir
;
3605 p_fs
->hint_uentry
.clu
.size
= clu
.size
;
3606 p_fs
->hint_uentry
.clu
.flags
= clu
.flags
;
3608 } else if (type
== TYPE_DELETED
) {
3614 if (num_empty
>= num_entries
) {
3615 p_fs
->hint_uentry
.dir
= CLUSTER_32(~0);
3616 p_fs
->hint_uentry
.entry
= -1;
3618 if (p_fs
->vol_type
== EXFAT
)
3619 return(dentry
- (num_entries
-1));
3625 if (p_dir
->dir
== CLUSTER_32(0))
3626 break; /* FAT16 root_dir */
3628 if (clu
.flags
== 0x03) {
3629 if ((--clu
.size
) > 0)
3632 clu
.dir
= CLUSTER_32(~0);
3634 if (FAT_read(sb
, clu
.dir
, &(clu
.dir
)) != 0)
3640 } /* end of search_deleted_or_unused_entry */
3642 INT32
find_empty_entry(struct inode
*inode
, CHAIN_T
*p_dir
, INT32 num_entries
)
3645 UINT32 last_clu
, sector
;
3648 DENTRY_T
*ep
= NULL
;
3649 struct super_block
*sb
= inode
->i_sb
;
3650 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3651 FILE_ID_T
*fid
= &(EXFAT_I(inode
)->fid
);
3653 if (p_dir
->dir
== CLUSTER_32(0)) /* FAT16 root_dir */
3654 return(search_deleted_or_unused_entry(sb
, p_dir
, num_entries
));
3656 while ((dentry
= search_deleted_or_unused_entry(sb
, p_dir
, num_entries
)) < 0) {
3657 if (p_fs
->dev_ejected
)
3660 if (p_fs
->vol_type
== EXFAT
) {
3661 if (p_dir
->dir
!= p_fs
->root_dir
) {
3662 size
= i_size_read(inode
);
3666 last_clu
= find_last_cluster(sb
, p_dir
);
3667 clu
.dir
= last_clu
+ 1;
3669 clu
.flags
= p_dir
->flags
;
3671 /* (1) allocate a cluster */
3672 ret
= p_fs
->fs_func
->alloc_cluster(sb
, 1, &clu
);
3676 if (clear_cluster(sb
, clu
.dir
) != FFS_SUCCESS
)
3679 /* (2) append to the FAT chain */
3680 if (clu
.flags
!= p_dir
->flags
) {
3681 exfat_chain_cont_cluster(sb
, p_dir
->dir
, p_dir
->size
);
3682 p_dir
->flags
= 0x01;
3683 p_fs
->hint_uentry
.clu
.flags
= 0x01;
3685 if (clu
.flags
== 0x01)
3686 FAT_write(sb
, last_clu
, clu
.dir
);
3688 if (p_fs
->hint_uentry
.entry
== -1) {
3689 p_fs
->hint_uentry
.dir
= p_dir
->dir
;
3690 p_fs
->hint_uentry
.entry
= p_dir
->size
<< (p_fs
->cluster_size_bits
- DENTRY_SIZE_BITS
);
3692 p_fs
->hint_uentry
.clu
.dir
= clu
.dir
;
3693 p_fs
->hint_uentry
.clu
.size
= 0;
3694 p_fs
->hint_uentry
.clu
.flags
= clu
.flags
;
3696 p_fs
->hint_uentry
.clu
.size
++;
3699 /* (3) update the directory entry */
3700 if (p_fs
->vol_type
== EXFAT
) {
3701 if (p_dir
->dir
!= p_fs
->root_dir
) {
3702 size
+= p_fs
->cluster_size
;
3704 ep
= get_entry_in_dir(sb
, &(fid
->dir
), fid
->entry
+1, §or
);
3707 p_fs
->fs_func
->set_entry_size(ep
, size
);
3708 p_fs
->fs_func
->set_entry_flag(ep
, p_dir
->flags
);
3709 buf_modify(sb
, sector
);
3711 update_dir_checksum(sb
, &(fid
->dir
), fid
->entry
);
3715 i_size_write(inode
, i_size_read(inode
)+p_fs
->cluster_size
);
3716 EXFAT_I(inode
)->mmu_private
+= p_fs
->cluster_size
;
3717 EXFAT_I(inode
)->fid
.size
+= p_fs
->cluster_size
;
3718 EXFAT_I(inode
)->fid
.flags
= p_dir
->flags
;
3719 inode
->i_blocks
+= 1 << (p_fs
->cluster_size_bits
- 9);
3723 } /* end of find_empty_entry */
3725 /* return values of fat_find_dir_entry()
3726 >= 0 : return dir entiry position with the name in dir
3727 -1 : (root dir, ".") it is the root dir itself
3728 -2 : entry with the name does not exist */
3729 INT32
fat_find_dir_entry(struct super_block
*sb
, CHAIN_T
*p_dir
, UNI_NAME_T
*p_uniname
, INT32 num_entries
, DOS_NAME_T
*p_dosname
, UINT32 type
)
3731 INT32 i
, dentry
= 0, len
;
3732 INT32 order
= 0, is_feasible_entry
= TRUE
, has_ext_entry
= FALSE
;
3733 INT32 dentries_per_clu
;
3735 UINT16 entry_uniname
[14], *uniname
= NULL
, unichar
;
3738 DOS_DENTRY_T
*dos_ep
;
3739 EXT_DENTRY_T
*ext_ep
;
3740 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3742 if (p_dir
->dir
== p_fs
->root_dir
) {
3743 if ((!nls_uniname_cmp(sb
, p_uniname
->name
, (UINT16
*) UNI_CUR_DIR_NAME
)) ||
3744 (!nls_uniname_cmp(sb
, p_uniname
->name
, (UINT16
*) UNI_PAR_DIR_NAME
)))
3745 return -1; // special case, root directory itself
3748 if (p_dir
->dir
== CLUSTER_32(0)) /* FAT16 root_dir */
3749 dentries_per_clu
= p_fs
->dentries_in_root
;
3751 dentries_per_clu
= p_fs
->dentries_per_clu
;
3753 clu
.dir
= p_dir
->dir
;
3754 clu
.flags
= p_dir
->flags
;
3756 while (clu
.dir
!= CLUSTER_32(~0)) {
3757 if (p_fs
->dev_ejected
)
3760 for (i
= 0; i
< dentries_per_clu
; i
++, dentry
++) {
3761 ep
= get_entry_in_dir(sb
, &clu
, i
, NULL
);
3765 entry_type
= p_fs
->fs_func
->get_entry_type(ep
);
3767 if ((entry_type
== TYPE_FILE
) || (entry_type
== TYPE_DIR
)) {
3768 if ((type
== TYPE_ALL
) || (type
== entry_type
)) {
3769 if (is_feasible_entry
&& has_ext_entry
)
3772 dos_ep
= (DOS_DENTRY_T
*) ep
;
3773 if (!nls_dosname_cmp(sb
, p_dosname
->name
, dos_ep
->name
))
3776 is_feasible_entry
= TRUE
;
3777 has_ext_entry
= FALSE
;
3778 } else if (entry_type
== TYPE_EXTEND
) {
3779 if (is_feasible_entry
) {
3780 ext_ep
= (EXT_DENTRY_T
*) ep
;
3781 if (ext_ep
->order
> 0x40) {
3782 order
= (INT32
)(ext_ep
->order
- 0x40);
3783 uniname
= p_uniname
->name
+ 13 * (order
-1);
3785 order
= (INT32
) ext_ep
->order
;
3789 len
= extract_uni_name_from_ext_entry(ext_ep
, entry_uniname
, order
);
3791 unichar
= *(uniname
+len
);
3792 *(uniname
+len
) = 0x0;
3794 if (nls_uniname_cmp(sb
, uniname
, entry_uniname
)) {
3795 is_feasible_entry
= FALSE
;
3798 *(uniname
+len
) = unichar
;
3800 has_ext_entry
= TRUE
;
3801 } else if (entry_type
== TYPE_UNUSED
) {
3804 is_feasible_entry
= TRUE
;
3805 has_ext_entry
= FALSE
;
3809 if (p_dir
->dir
== CLUSTER_32(0))
3810 break; /* FAT16 root_dir */
3812 if (FAT_read(sb
, clu
.dir
, &(clu
.dir
)) != 0)
3817 } /* end of fat_find_dir_entry */
3819 /* return values of exfat_find_dir_entry()
3820 >= 0 : return dir entiry position with the name in dir
3821 -1 : (root dir, ".") it is the root dir itself
3822 -2 : entry with the name does not exist */
3823 INT32
exfat_find_dir_entry(struct super_block
*sb
, CHAIN_T
*p_dir
, UNI_NAME_T
*p_uniname
, INT32 num_entries
, DOS_NAME_T
*p_dosname
, UINT32 type
)
3825 INT32 i
, dentry
= 0, num_ext_entries
= 0, len
;
3826 INT32 order
= 0, is_feasible_entry
= FALSE
;
3827 INT32 dentries_per_clu
, num_empty
= 0;
3829 UINT16 entry_uniname
[16], *uniname
= NULL
, unichar
;
3832 FILE_DENTRY_T
*file_ep
;
3833 STRM_DENTRY_T
*strm_ep
;
3834 NAME_DENTRY_T
*name_ep
;
3835 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3837 if (p_dir
->dir
== p_fs
->root_dir
) {
3838 if ((!nls_uniname_cmp(sb
, p_uniname
->name
, (UINT16
*) UNI_CUR_DIR_NAME
)) ||
3839 (!nls_uniname_cmp(sb
, p_uniname
->name
, (UINT16
*) UNI_PAR_DIR_NAME
)))
3840 return -1; // special case, root directory itself
3843 if (p_dir
->dir
== CLUSTER_32(0)) /* FAT16 root_dir */
3844 dentries_per_clu
= p_fs
->dentries_in_root
;
3846 dentries_per_clu
= p_fs
->dentries_per_clu
;
3848 clu
.dir
= p_dir
->dir
;
3849 clu
.size
= p_dir
->size
;
3850 clu
.flags
= p_dir
->flags
;
3852 p_fs
->hint_uentry
.dir
= p_dir
->dir
;
3853 p_fs
->hint_uentry
.entry
= -1;
3855 while (clu
.dir
!= CLUSTER_32(~0)) {
3856 if (p_fs
->dev_ejected
)
3859 for (i
= 0; i
< dentries_per_clu
; i
++, dentry
++) {
3860 ep
= get_entry_in_dir(sb
, &clu
, i
, NULL
);
3864 entry_type
= p_fs
->fs_func
->get_entry_type(ep
);
3866 if ((entry_type
== TYPE_UNUSED
) || (entry_type
== TYPE_DELETED
)) {
3867 is_feasible_entry
= FALSE
;
3869 if (p_fs
->hint_uentry
.entry
== -1) {
3872 if (num_empty
== 1) {
3873 p_fs
->hint_uentry
.clu
.dir
= clu
.dir
;
3874 p_fs
->hint_uentry
.clu
.size
= clu
.size
;
3875 p_fs
->hint_uentry
.clu
.flags
= clu
.flags
;
3877 if ((num_empty
>= num_entries
) || (entry_type
== TYPE_UNUSED
)) {
3878 p_fs
->hint_uentry
.entry
= dentry
- (num_empty
-1);
3882 if (entry_type
== TYPE_UNUSED
) {
3888 if ((entry_type
== TYPE_FILE
) || (entry_type
== TYPE_DIR
)) {
3889 if ((type
== TYPE_ALL
) || (type
== entry_type
)) {
3890 file_ep
= (FILE_DENTRY_T
*) ep
;
3891 num_ext_entries
= file_ep
->num_ext
;
3892 is_feasible_entry
= TRUE
;
3894 is_feasible_entry
= FALSE
;
3896 } else if (entry_type
== TYPE_STREAM
) {
3897 if (is_feasible_entry
) {
3898 strm_ep
= (STRM_DENTRY_T
*) ep
;
3899 if (p_uniname
->name_len
== strm_ep
->name_len
) {
3902 is_feasible_entry
= FALSE
;
3905 } else if (entry_type
== TYPE_EXTEND
) {
3906 if (is_feasible_entry
) {
3907 name_ep
= (NAME_DENTRY_T
*) ep
;
3910 uniname
= p_uniname
->name
;
3914 len
= extract_uni_name_from_name_entry(name_ep
, entry_uniname
, order
);
3916 unichar
= *(uniname
+len
);
3917 *(uniname
+len
) = 0x0;
3919 if (nls_uniname_cmp(sb
, uniname
, entry_uniname
)) {
3920 is_feasible_entry
= FALSE
;
3921 } else if (order
== num_ext_entries
) {
3922 p_fs
->hint_uentry
.dir
= CLUSTER_32(~0);
3923 p_fs
->hint_uentry
.entry
= -1;
3924 return(dentry
- (num_ext_entries
));
3927 *(uniname
+len
) = unichar
;
3930 is_feasible_entry
= FALSE
;
3935 if (p_dir
->dir
== CLUSTER_32(0))
3936 break; /* FAT16 root_dir */
3938 if (clu
.flags
== 0x03) {
3939 if ((--clu
.size
) > 0)
3942 clu
.dir
= CLUSTER_32(~0);
3944 if (FAT_read(sb
, clu
.dir
, &(clu
.dir
)) != 0)
3950 } /* end of exfat_find_dir_entry */
3952 /* returns -1 on error */
3953 INT32
fat_count_ext_entries(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, DENTRY_T
*p_entry
)
3957 DOS_DENTRY_T
*dos_ep
= (DOS_DENTRY_T
*) p_entry
;
3958 EXT_DENTRY_T
*ext_ep
;
3959 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3961 chksum
= calc_checksum_1byte((void *) dos_ep
->name
, DOS_NAME_LENGTH
, 0);
3963 for (entry
--; entry
>= 0; entry
--) {
3964 ext_ep
= (EXT_DENTRY_T
*) get_entry_in_dir(sb
, p_dir
, entry
, NULL
);
3968 if ((p_fs
->fs_func
->get_entry_type((DENTRY_T
*) ext_ep
) == TYPE_EXTEND
) &&
3969 (ext_ep
->checksum
== chksum
)) {
3971 if (ext_ep
->order
> 0x40)
3979 } /* end of fat_count_ext_entries */
3981 /* returns -1 on error */
3982 INT32
exfat_count_ext_entries(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, DENTRY_T
*p_entry
)
3986 FILE_DENTRY_T
*file_ep
= (FILE_DENTRY_T
*) p_entry
;
3988 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
3990 for (i
= 0, entry
++; i
< file_ep
->num_ext
; i
++, entry
++) {
3991 ext_ep
= get_entry_in_dir(sb
, p_dir
, entry
, NULL
);
3995 type
= p_fs
->fs_func
->get_entry_type(ext_ep
);
3996 if ((type
== TYPE_EXTEND
) || (type
== TYPE_STREAM
)) {
4004 } /* end of exfat_count_ext_entries */
4006 /* returns -1 on error */
4007 INT32
count_dos_name_entries(struct super_block
*sb
, CHAIN_T
*p_dir
, UINT32 type
)
4010 INT32 dentries_per_clu
;
4014 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4016 if (p_dir
->dir
== CLUSTER_32(0)) /* FAT16 root_dir */
4017 dentries_per_clu
= p_fs
->dentries_in_root
;
4019 dentries_per_clu
= p_fs
->dentries_per_clu
;
4021 clu
.dir
= p_dir
->dir
;
4022 clu
.size
= p_dir
->size
;
4023 clu
.flags
= p_dir
->flags
;
4025 while (clu
.dir
!= CLUSTER_32(~0)) {
4026 if (p_fs
->dev_ejected
)
4029 for (i
= 0; i
< dentries_per_clu
; i
++) {
4030 ep
= get_entry_in_dir(sb
, &clu
, i
, NULL
);
4034 entry_type
= p_fs
->fs_func
->get_entry_type(ep
);
4036 if (entry_type
== TYPE_UNUSED
)
4038 if (!(type
& TYPE_CRITICAL_PRI
) && !(type
& TYPE_BENIGN_PRI
))
4041 if ((type
== TYPE_ALL
) || (type
== entry_type
))
4045 if (p_dir
->dir
== CLUSTER_32(0))
4046 break; /* FAT16 root_dir */
4048 if (clu
.flags
== 0x03) {
4049 if ((--clu
.size
) > 0)
4052 clu
.dir
= CLUSTER_32(~0);
4054 if (FAT_read(sb
, clu
.dir
, &(clu
.dir
)) != 0)
4060 } /* end of count_dos_name_entries */
4062 BOOL
is_dir_empty(struct super_block
*sb
, CHAIN_T
*p_dir
)
4065 INT32 dentries_per_clu
;
4069 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4071 if (p_dir
->dir
== CLUSTER_32(0)) /* FAT16 root_dir */
4072 dentries_per_clu
= p_fs
->dentries_in_root
;
4074 dentries_per_clu
= p_fs
->dentries_per_clu
;
4076 clu
.dir
= p_dir
->dir
;
4077 clu
.size
= p_dir
->size
;
4078 clu
.flags
= p_dir
->flags
;
4080 while (clu
.dir
!= CLUSTER_32(~0)) {
4081 if (p_fs
->dev_ejected
)
4084 for (i
= 0; i
< dentries_per_clu
; i
++) {
4085 ep
= get_entry_in_dir(sb
, &clu
, i
, NULL
);
4089 type
= p_fs
->fs_func
->get_entry_type(ep
);
4091 if (type
== TYPE_UNUSED
)
4093 if ((type
!= TYPE_FILE
) && (type
!= TYPE_DIR
))
4096 if (p_dir
->dir
== CLUSTER_32(0)) { /* FAT16 root_dir */
4099 if (p_fs
->vol_type
== EXFAT
)
4101 if ((p_dir
->dir
== p_fs
->root_dir
) || ((++count
) > 2))
4106 if (p_dir
->dir
== CLUSTER_32(0))
4107 break; /* FAT16 root_dir */
4109 if (clu
.flags
== 0x03) {
4110 if ((--clu
.size
) > 0)
4113 clu
.dir
= CLUSTER_32(~0);
4115 if (FAT_read(sb
, clu
.dir
, &(clu
.dir
)) != 0)
4121 } /* end of is_dir_empty */
4124 * Name Conversion Functions
4127 /* input : dir, uni_name
4128 output : num_of_entry, dos_name(format : aaaaaa~1.bbb) */
4129 INT32
get_num_entries_and_dos_name(struct super_block
*sb
, CHAIN_T
*p_dir
, UNI_NAME_T
*p_uniname
, INT32
*entries
, DOS_NAME_T
*p_dosname
)
4131 INT32 ret
, num_entries
, lossy
= FALSE
;
4133 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4135 num_entries
= p_fs
->fs_func
->calc_num_entries(p_uniname
);
4136 if (num_entries
== 0)
4137 return FFS_INVALIDPATH
;
4139 if (p_fs
->vol_type
!= EXFAT
) {
4140 nls_uniname_to_dosname(sb
, p_dosname
, p_uniname
, &lossy
);
4143 ret
= fat_generate_dos_name(sb
, p_dir
, p_dosname
);
4147 for (r
= reserved_names
; *r
; r
++) {
4148 if (!STRNCMP((void *) p_dosname
->name
, *r
, 8))
4149 return FFS_INVALIDPATH
;
4152 if (p_dosname
->name_case
!= 0xFF)
4156 if (num_entries
> 1)
4157 p_dosname
->name_case
= 0x0;
4160 *entries
= num_entries
;
4163 } /* end of get_num_entries_and_dos_name */
4165 void get_uni_name_from_dos_entry(struct super_block
*sb
, DOS_DENTRY_T
*ep
, UNI_NAME_T
*p_uniname
, UINT8 mode
)
4167 DOS_NAME_T dos_name
;
4170 dos_name
.name_case
= 0x0;
4172 dos_name
.name_case
= ep
->lcase
;
4174 MEMCPY(dos_name
.name
, ep
->name
, DOS_NAME_LENGTH
);
4175 nls_dosname_to_uniname(sb
, p_uniname
, &dos_name
);
4176 } /* end of get_uni_name_from_dos_entry */
4178 void fat_get_uni_name_from_ext_entry(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, UINT16
*uniname
)
4182 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4184 for (entry
--, i
= 1; entry
>= 0; entry
--, i
++) {
4185 ep
= (EXT_DENTRY_T
*) get_entry_in_dir(sb
, p_dir
, entry
, NULL
);
4189 if (p_fs
->fs_func
->get_entry_type((DENTRY_T
*) ep
) == TYPE_EXTEND
) {
4190 extract_uni_name_from_ext_entry(ep
, uniname
, i
);
4191 if (ep
->order
> 0x40)
4199 } /* end of fat_get_uni_name_from_ext_entry */
4201 void exfat_get_uni_name_from_ext_entry(struct super_block
*sb
, CHAIN_T
*p_dir
, INT32 entry
, UINT16
*uniname
)
4205 ENTRY_SET_CACHE_T
*es
;
4206 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4208 es
= get_entry_set_in_dir(sb
, p_dir
, entry
, ES_ALL_ENTRIES
, &ep
);
4209 if (es
== NULL
|| es
->num_entries
< 3) {
4211 release_entry_set(es
);
4219 * First entry : file entry
4220 * Second entry : stream-extension entry
4221 * Third entry : first file-name entry
4222 * So, the index of first file-name dentry should start from 2.
4224 for (i
= 2; i
< es
->num_entries
; i
++, ep
++) {
4225 if (p_fs
->fs_func
->get_entry_type(ep
) == TYPE_EXTEND
) {
4226 extract_uni_name_from_name_entry((NAME_DENTRY_T
*)ep
, uniname
, i
);
4228 /* end of name entry */
4235 release_entry_set(es
);
4236 } /* end of exfat_get_uni_name_from_ext_entry */
4238 INT32
extract_uni_name_from_ext_entry(EXT_DENTRY_T
*ep
, UINT16
*uniname
, INT32 order
)
4242 for (i
= 0; i
< 10; i
+= 2) {
4243 *uniname
= GET16(ep
->unicode_0_4
+i
);
4244 if (*uniname
== 0x0)
4251 for (i
= 0; i
< 12; i
+= 2) {
4252 *uniname
= GET16_A(ep
->unicode_5_10
+i
);
4253 if (*uniname
== 0x0)
4259 for (i
= 0; i
< 8; i
+= 2) {
4260 *uniname
= GET16_A(ep
->unicode_5_10
+i
);
4261 if (*uniname
== 0x0)
4266 *uniname
= 0x0; /* uniname[MAX_NAME_LENGTH-1] */
4270 for (i
= 0; i
< 4; i
+= 2) {
4271 *uniname
= GET16_A(ep
->unicode_11_12
+i
);
4272 if (*uniname
== 0x0)
4281 } /* end of extract_uni_name_from_ext_entry */
4283 INT32
extract_uni_name_from_name_entry(NAME_DENTRY_T
*ep
, UINT16
*uniname
, INT32 order
)
4287 for (i
= 0; i
< 30; i
+= 2) {
4288 *uniname
= GET16_A(ep
->unicode_0_14
+i
);
4289 if (*uniname
== 0x0)
4298 } /* end of extract_uni_name_from_name_entry */
4300 INT32
fat_generate_dos_name(struct super_block
*sb
, CHAIN_T
*p_dir
, DOS_NAME_T
*p_dosname
)
4302 INT32 i
, j
, count
= 0, count_begin
= FALSE
;
4303 INT32 dentries_per_clu
;
4305 UINT8 bmap
[128/* 1 ~ 1023 */];
4308 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4310 Bitmap_clear_all(bmap
, 128);
4311 Bitmap_set(bmap
, 0);
4313 if (p_dir
->dir
== CLUSTER_32(0)) /* FAT16 root_dir */
4314 dentries_per_clu
= p_fs
->dentries_in_root
;
4316 dentries_per_clu
= p_fs
->dentries_per_clu
;
4318 clu
.dir
= p_dir
->dir
;
4319 clu
.flags
= p_dir
->flags
;
4321 while (clu
.dir
!= CLUSTER_32(~0)) {
4322 if (p_fs
->dev_ejected
)
4325 for (i
= 0; i
< dentries_per_clu
; i
++) {
4326 ep
= (DOS_DENTRY_T
*) get_entry_in_dir(sb
, &clu
, i
, NULL
);
4328 return FFS_MEDIAERR
;
4330 type
= p_fs
->fs_func
->get_entry_type((DENTRY_T
*) ep
);
4332 if (type
== TYPE_UNUSED
)
4334 if ((type
!= TYPE_FILE
) && (type
!= TYPE_DIR
))
4338 count_begin
= FALSE
;
4340 for (j
= 0; j
< 8; j
++) {
4341 if (ep
->name
[j
] == ' ')
4344 if (ep
->name
[j
] == '~') {
4346 } else if (count_begin
) {
4347 if ((ep
->name
[j
] >= '0') && (ep
->name
[j
] <= '9')) {
4348 count
= count
* 10 + (ep
->name
[j
] - '0');
4351 count_begin
= FALSE
;
4356 if ((count
> 0) && (count
< 1024))
4357 Bitmap_set(bmap
, count
);
4360 if (p_dir
->dir
== CLUSTER_32(0))
4361 break; /* FAT16 root_dir */
4363 if (FAT_read(sb
, clu
.dir
, &(clu
.dir
)) != 0)
4364 return FFS_MEDIAERR
;
4368 for (i
= 0; i
< 128; i
++) {
4369 if (bmap
[i
] != 0xFF) {
4370 for (j
= 0; j
< 8; j
++) {
4371 if (Bitmap_test(&(bmap
[i
]), j
) == 0) {
4372 count
= (i
<< 3) + j
;
4381 if ((count
== 0) || (count
>= 1024))
4382 return FFS_FILEEXIST
;
4384 fat_attach_count_to_dos_name(p_dosname
->name
, count
);
4386 /* Now dos_name has DOS~????.EXT */
4388 } /* end of generate_dos_name */
4390 void fat_attach_count_to_dos_name(UINT8
*dosname
, INT32 count
)
4396 str_count
[1] = '\0';
4397 my_itoa(&(str_count
[1]), count
);
4398 length
= STRLEN(str_count
);
4401 while (j
<= (8 - length
)) {
4403 if (dosname
[j
] == ' ')
4405 if (dosname
[j
] & 0x80)
4411 for (j
= 0; j
< length
; i
++, j
++)
4412 dosname
[i
] = (UINT8
) str_count
[j
];
4417 } /* end of attach_count_to_dos_name */
4419 INT32
fat_calc_num_entries(UNI_NAME_T
*p_uniname
)
4423 len
= p_uniname
->name_len
;
4427 /* 1 dos name entry + extended entries */
4428 return((len
-1) / 13 + 2);
4430 } /* end of calc_num_enties */
4432 INT32
exfat_calc_num_entries(UNI_NAME_T
*p_uniname
)
4436 len
= p_uniname
->name_len
;
4440 /* 1 file entry + 1 stream entry + name entries */
4441 return((len
-1) / 15 + 3);
4443 } /* end of exfat_calc_num_enties */
4445 UINT8
calc_checksum_1byte(void *data
, INT32 len
, UINT8 chksum
)
4448 UINT8
*c
= (UINT8
*) data
;
4450 for (i
= 0; i
< len
; i
++, c
++)
4451 chksum
= (((chksum
& 1) << 7) | ((chksum
& 0xFE) >> 1)) + *c
;
4454 } /* end of calc_checksum_1byte */
4456 UINT16
calc_checksum_2byte(void *data
, INT32 len
, UINT16 chksum
, INT32 type
)
4459 UINT8
*c
= (UINT8
*) data
;
4463 for (i
= 0; i
< len
; i
++, c
++) {
4464 if ((i
== 2) || (i
== 3))
4466 chksum
= (((chksum
& 1) << 15) | ((chksum
& 0xFFFE) >> 1)) + (UINT16
) *c
;
4471 for (i
= 0; i
< len
; i
++, c
++) {
4472 chksum
= (((chksum
& 1) << 15) | ((chksum
& 0xFFFE) >> 1)) + (UINT16
) *c
;
4477 } /* end of calc_checksum_2byte */
4479 UINT32
calc_checksum_4byte(void *data
, INT32 len
, UINT32 chksum
, INT32 type
)
4482 UINT8
*c
= (UINT8
*) data
;
4486 for (i
= 0; i
< len
; i
++, c
++) {
4487 if ((i
== 106) || (i
== 107) || (i
== 112))
4489 chksum
= (((chksum
& 1) << 31) | ((chksum
& 0xFFFFFFFE) >> 1)) + (UINT32
) *c
;
4494 for (i
= 0; i
< len
; i
++, c
++) {
4495 chksum
= (((chksum
& 1) << 31) | ((chksum
& 0xFFFFFFFE) >> 1)) + (UINT32
) *c
;
4500 } /* end of calc_checksum_4byte */
4503 * Name Resolution Functions
4506 /* return values of resolve_path()
4507 > 0 : return the length of the path
4508 < 0 : return error */
4509 INT32
resolve_path(struct inode
*inode
, UINT8
*path
, CHAIN_T
*p_dir
, UNI_NAME_T
*p_uniname
)
4511 INT32 lossy
= FALSE
;
4512 struct super_block
*sb
= inode
->i_sb
;
4513 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4514 FILE_ID_T
*fid
= &(EXFAT_I(inode
)->fid
);
4516 if (STRLEN(path
) >= (MAX_NAME_LENGTH
* MAX_CHARSET_SIZE
))
4517 return(FFS_INVALIDPATH
);
4519 STRCPY(name_buf
, path
);
4521 nls_cstring_to_uniname(sb
, p_uniname
, name_buf
, &lossy
);
4523 return(FFS_INVALIDPATH
);
4525 fid
->size
= i_size_read(inode
);
4527 p_dir
->dir
= fid
->start_clu
;
4528 p_dir
->size
= (INT32
)(fid
->size
>> p_fs
->cluster_size_bits
);
4529 p_dir
->flags
= fid
->flags
;
4531 return(FFS_SUCCESS
);
4535 * File Operation Functions
4537 static FS_FUNC_T fat_fs_func
= {
4538 .alloc_cluster
= fat_alloc_cluster
,
4539 .free_cluster
= fat_free_cluster
,
4540 .count_used_clusters
= fat_count_used_clusters
,
4542 .init_dir_entry
= fat_init_dir_entry
,
4543 .init_ext_entry
= fat_init_ext_entry
,
4544 .find_dir_entry
= fat_find_dir_entry
,
4545 .delete_dir_entry
= fat_delete_dir_entry
,
4546 .get_uni_name_from_ext_entry
= fat_get_uni_name_from_ext_entry
,
4547 .count_ext_entries
= fat_count_ext_entries
,
4548 .calc_num_entries
= fat_calc_num_entries
,
4550 .get_entry_type
= fat_get_entry_type
,
4551 .set_entry_type
= fat_set_entry_type
,
4552 .get_entry_attr
= fat_get_entry_attr
,
4553 .set_entry_attr
= fat_set_entry_attr
,
4554 .get_entry_flag
= fat_get_entry_flag
,
4555 .set_entry_flag
= fat_set_entry_flag
,
4556 .get_entry_clu0
= fat_get_entry_clu0
,
4557 .set_entry_clu0
= fat_set_entry_clu0
,
4558 .get_entry_size
= fat_get_entry_size
,
4559 .set_entry_size
= fat_set_entry_size
,
4560 .get_entry_time
= fat_get_entry_time
,
4561 .set_entry_time
= fat_set_entry_time
,
4565 INT32
fat16_mount(struct super_block
*sb
, PBR_SECTOR_T
*p_pbr
)
4567 INT32 num_reserved
, num_root_sectors
;
4568 BPB16_T
*p_bpb
= (BPB16_T
*) p_pbr
->bpb
;
4569 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4570 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
4572 if (p_bpb
->num_fats
== 0)
4573 return FFS_FORMATERR
;
4575 num_root_sectors
= GET16(p_bpb
->num_root_entries
) << DENTRY_SIZE_BITS
;
4576 num_root_sectors
= ((num_root_sectors
-1) >> p_bd
->sector_size_bits
) + 1;
4578 p_fs
->sectors_per_clu
= p_bpb
->sectors_per_clu
;
4579 p_fs
->sectors_per_clu_bits
= my_log2(p_bpb
->sectors_per_clu
);
4580 p_fs
->cluster_size_bits
= p_fs
->sectors_per_clu_bits
+ p_bd
->sector_size_bits
;
4581 p_fs
->cluster_size
= 1 << p_fs
->cluster_size_bits
;
4583 p_fs
->num_FAT_sectors
= GET16(p_bpb
->num_fat_sectors
);
4585 p_fs
->FAT1_start_sector
= p_fs
->PBR_sector
+ GET16(p_bpb
->num_reserved
);
4586 if (p_bpb
->num_fats
== 1)
4587 p_fs
->FAT2_start_sector
= p_fs
->FAT1_start_sector
;
4589 p_fs
->FAT2_start_sector
= p_fs
->FAT1_start_sector
+ p_fs
->num_FAT_sectors
;
4591 p_fs
->root_start_sector
= p_fs
->FAT2_start_sector
+ p_fs
->num_FAT_sectors
;
4592 p_fs
->data_start_sector
= p_fs
->root_start_sector
+ num_root_sectors
;
4594 p_fs
->num_sectors
= GET16(p_bpb
->num_sectors
);
4595 if (p_fs
->num_sectors
== 0)
4596 p_fs
->num_sectors
= GET32(p_bpb
->num_huge_sectors
);
4598 num_reserved
= p_fs
->data_start_sector
- p_fs
->PBR_sector
;
4599 p_fs
->num_clusters
= ((p_fs
->num_sectors
- num_reserved
) >> p_fs
->sectors_per_clu_bits
) + 2;
4600 /* because the cluster index starts with 2 */
4602 if (p_fs
->num_clusters
< FAT12_THRESHOLD
)
4603 p_fs
->vol_type
= FAT12
;
4605 p_fs
->vol_type
= FAT16
;
4606 p_fs
->vol_id
= GET32(p_bpb
->vol_serial
);
4609 p_fs
->dentries_in_root
= GET16(p_bpb
->num_root_entries
);
4610 p_fs
->dentries_per_clu
= 1 << (p_fs
->cluster_size_bits
- DENTRY_SIZE_BITS
);
4612 p_fs
->vol_flag
= VOL_CLEAN
;
4613 p_fs
->clu_srch_ptr
= 2;
4614 p_fs
->used_clusters
= (UINT32
) ~0;
4616 p_fs
->fs_func
= &fat_fs_func
;
4619 } /* end of fat16_mount */
4621 INT32
fat32_mount(struct super_block
*sb
, PBR_SECTOR_T
*p_pbr
)
4624 BPB32_T
*p_bpb
= (BPB32_T
*) p_pbr
->bpb
;
4625 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4626 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
4628 if (p_bpb
->num_fats
== 0)
4629 return FFS_FORMATERR
;
4631 p_fs
->sectors_per_clu
= p_bpb
->sectors_per_clu
;
4632 p_fs
->sectors_per_clu_bits
= my_log2(p_bpb
->sectors_per_clu
);
4633 p_fs
->cluster_size_bits
= p_fs
->sectors_per_clu_bits
+ p_bd
->sector_size_bits
;
4634 p_fs
->cluster_size
= 1 << p_fs
->cluster_size_bits
;
4636 p_fs
->num_FAT_sectors
= GET32(p_bpb
->num_fat32_sectors
);
4638 p_fs
->FAT1_start_sector
= p_fs
->PBR_sector
+ GET16(p_bpb
->num_reserved
);
4639 if (p_bpb
->num_fats
== 1)
4640 p_fs
->FAT2_start_sector
= p_fs
->FAT1_start_sector
;
4642 p_fs
->FAT2_start_sector
= p_fs
->FAT1_start_sector
+ p_fs
->num_FAT_sectors
;
4644 p_fs
->root_start_sector
= p_fs
->FAT2_start_sector
+ p_fs
->num_FAT_sectors
;
4645 p_fs
->data_start_sector
= p_fs
->root_start_sector
;
4647 p_fs
->num_sectors
= GET32(p_bpb
->num_huge_sectors
);
4648 num_reserved
= p_fs
->data_start_sector
- p_fs
->PBR_sector
;
4650 p_fs
->num_clusters
= ((p_fs
->num_sectors
-num_reserved
) >> p_fs
->sectors_per_clu_bits
) + 2;
4651 /* because the cluster index starts with 2 */
4653 p_fs
->vol_type
= FAT32
;
4654 p_fs
->vol_id
= GET32(p_bpb
->vol_serial
);
4656 p_fs
->root_dir
= GET32(p_bpb
->root_cluster
);
4657 p_fs
->dentries_in_root
= 0;
4658 p_fs
->dentries_per_clu
= 1 << (p_fs
->cluster_size_bits
- DENTRY_SIZE_BITS
);
4660 p_fs
->vol_flag
= VOL_CLEAN
;
4661 p_fs
->clu_srch_ptr
= 2;
4662 p_fs
->used_clusters
= (UINT32
) ~0;
4664 p_fs
->fs_func
= &fat_fs_func
;
4667 } /* end of fat32_mount */
4669 static FS_FUNC_T exfat_fs_func
= {
4670 .alloc_cluster
= exfat_alloc_cluster
,
4671 .free_cluster
= exfat_free_cluster
,
4672 .count_used_clusters
= exfat_count_used_clusters
,
4674 .init_dir_entry
= exfat_init_dir_entry
,
4675 .init_ext_entry
= exfat_init_ext_entry
,
4676 .find_dir_entry
= exfat_find_dir_entry
,
4677 .delete_dir_entry
= exfat_delete_dir_entry
,
4678 .get_uni_name_from_ext_entry
= exfat_get_uni_name_from_ext_entry
,
4679 .count_ext_entries
= exfat_count_ext_entries
,
4680 .calc_num_entries
= exfat_calc_num_entries
,
4682 .get_entry_type
= exfat_get_entry_type
,
4683 .set_entry_type
= exfat_set_entry_type
,
4684 .get_entry_attr
= exfat_get_entry_attr
,
4685 .set_entry_attr
= exfat_set_entry_attr
,
4686 .get_entry_flag
= exfat_get_entry_flag
,
4687 .set_entry_flag
= exfat_set_entry_flag
,
4688 .get_entry_clu0
= exfat_get_entry_clu0
,
4689 .set_entry_clu0
= exfat_set_entry_clu0
,
4690 .get_entry_size
= exfat_get_entry_size
,
4691 .set_entry_size
= exfat_set_entry_size
,
4692 .get_entry_time
= exfat_get_entry_time
,
4693 .set_entry_time
= exfat_set_entry_time
,
4696 INT32
exfat_mount(struct super_block
*sb
, PBR_SECTOR_T
*p_pbr
)
4698 BPBEX_T
*p_bpb
= (BPBEX_T
*) p_pbr
->bpb
;
4699 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4700 BD_INFO_T
*p_bd
= &(EXFAT_SB(sb
)->bd_info
);
4702 if (p_bpb
->num_fats
== 0)
4703 return FFS_FORMATERR
;
4705 p_fs
->sectors_per_clu
= 1 << p_bpb
->sectors_per_clu_bits
;
4706 p_fs
->sectors_per_clu_bits
= p_bpb
->sectors_per_clu_bits
;
4707 p_fs
->cluster_size_bits
= p_fs
->sectors_per_clu_bits
+ p_bd
->sector_size_bits
;
4708 p_fs
->cluster_size
= 1 << p_fs
->cluster_size_bits
;
4710 p_fs
->num_FAT_sectors
= GET32(p_bpb
->fat_length
);
4712 p_fs
->FAT1_start_sector
= p_fs
->PBR_sector
+ GET32(p_bpb
->fat_offset
);
4713 if (p_bpb
->num_fats
== 1)
4714 p_fs
->FAT2_start_sector
= p_fs
->FAT1_start_sector
;
4716 p_fs
->FAT2_start_sector
= p_fs
->FAT1_start_sector
+ p_fs
->num_FAT_sectors
;
4718 p_fs
->root_start_sector
= p_fs
->PBR_sector
+ GET32(p_bpb
->clu_offset
);
4719 p_fs
->data_start_sector
= p_fs
->root_start_sector
;
4721 p_fs
->num_sectors
= GET64(p_bpb
->vol_length
);
4722 p_fs
->num_clusters
= GET32(p_bpb
->clu_count
) + 2;
4723 /* because the cluster index starts with 2 */
4725 p_fs
->vol_type
= EXFAT
;
4726 p_fs
->vol_id
= GET32(p_bpb
->vol_serial
);
4728 p_fs
->root_dir
= GET32(p_bpb
->root_cluster
);
4729 p_fs
->dentries_in_root
= 0;
4730 p_fs
->dentries_per_clu
= 1 << (p_fs
->cluster_size_bits
- DENTRY_SIZE_BITS
);
4732 p_fs
->vol_flag
= (UINT32
) GET16(p_bpb
->vol_flags
);
4733 p_fs
->clu_srch_ptr
= 2;
4734 p_fs
->used_clusters
= (UINT32
) ~0;
4736 p_fs
->fs_func
= &exfat_fs_func
;
4739 } /* end of exfat_mount */
4741 INT32
create_dir(struct inode
*inode
, CHAIN_T
*p_dir
, UNI_NAME_T
*p_uniname
, FILE_ID_T
*fid
)
4743 INT32 ret
, dentry
, num_entries
;
4746 DOS_NAME_T dos_name
, dot_name
;
4747 struct super_block
*sb
= inode
->i_sb
;
4748 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4750 ret
= get_num_entries_and_dos_name(sb
, p_dir
, p_uniname
, &num_entries
, &dos_name
);
4754 /* find_empty_entry must be called before alloc_cluster */
4755 dentry
= find_empty_entry(inode
, p_dir
, num_entries
);
4759 clu
.dir
= CLUSTER_32(~0);
4761 clu
.flags
= (p_fs
->vol_type
== EXFAT
) ? 0x03 : 0x01;
4763 /* (1) allocate a cluster */
4764 ret
= p_fs
->fs_func
->alloc_cluster(sb
, 1, &clu
);
4768 ret
= clear_cluster(sb
, clu
.dir
);
4769 if (ret
!= FFS_SUCCESS
)
4772 if (p_fs
->vol_type
== EXFAT
) {
4773 size
= p_fs
->cluster_size
;
4777 /* initialize the . and .. entry
4778 Information for . points to itself
4779 Information for .. points to parent dir */
4781 dot_name
.name_case
= 0x0;
4782 MEMCPY(dot_name
.name
, DOS_CUR_DIR_NAME
, DOS_NAME_LENGTH
);
4784 ret
= p_fs
->fs_func
->init_dir_entry(sb
, &clu
, 0, TYPE_DIR
, clu
.dir
, 0);
4785 if (ret
!= FFS_SUCCESS
)
4788 ret
= p_fs
->fs_func
->init_ext_entry(sb
, &clu
, 0, 1, NULL
, &dot_name
);
4789 if (ret
!= FFS_SUCCESS
)
4792 MEMCPY(dot_name
.name
, DOS_PAR_DIR_NAME
, DOS_NAME_LENGTH
);
4794 if (p_dir
->dir
== p_fs
->root_dir
)
4795 ret
= p_fs
->fs_func
->init_dir_entry(sb
, &clu
, 1, TYPE_DIR
, CLUSTER_32(0), 0);
4797 ret
= p_fs
->fs_func
->init_dir_entry(sb
, &clu
, 1, TYPE_DIR
, p_dir
->dir
, 0);
4799 if (ret
!= FFS_SUCCESS
)
4802 ret
= p_fs
->fs_func
->init_ext_entry(sb
, &clu
, 1, 1, NULL
, &dot_name
);
4803 if (ret
!= FFS_SUCCESS
)
4807 /* (2) update the directory entry */
4808 /* make sub-dir entry in parent directory */
4809 ret
= p_fs
->fs_func
->init_dir_entry(sb
, p_dir
, dentry
, TYPE_DIR
, clu
.dir
, size
);
4810 if (ret
!= FFS_SUCCESS
)
4813 ret
= p_fs
->fs_func
->init_ext_entry(sb
, p_dir
, dentry
, num_entries
, p_uniname
, &dos_name
);
4814 if (ret
!= FFS_SUCCESS
)
4817 fid
->dir
.dir
= p_dir
->dir
;
4818 fid
->dir
.size
= p_dir
->size
;
4819 fid
->dir
.flags
= p_dir
->flags
;
4820 fid
->entry
= dentry
;
4822 fid
->attr
= ATTR_SUBDIR
;
4823 fid
->flags
= (p_fs
->vol_type
== EXFAT
) ? 0x03 : 0x01;
4825 fid
->start_clu
= clu
.dir
;
4827 fid
->type
= TYPE_DIR
;
4829 fid
->hint_last_off
= -1;
4832 } /* end of create_dir */
4834 INT32
create_file(struct inode
*inode
, CHAIN_T
*p_dir
, UNI_NAME_T
*p_uniname
, UINT8 mode
, FILE_ID_T
*fid
)
4836 INT32 ret
, dentry
, num_entries
;
4837 DOS_NAME_T dos_name
;
4838 struct super_block
*sb
= inode
->i_sb
;
4839 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4841 ret
= get_num_entries_and_dos_name(sb
, p_dir
, p_uniname
, &num_entries
, &dos_name
);
4845 /* find_empty_entry must be called before alloc_cluster() */
4846 dentry
= find_empty_entry(inode
, p_dir
, num_entries
);
4850 /* (1) update the directory entry */
4851 /* fill the dos name directory entry information of the created file.
4852 the first cluster is not determined yet. (0) */
4853 ret
= p_fs
->fs_func
->init_dir_entry(sb
, p_dir
, dentry
, TYPE_FILE
| mode
, CLUSTER_32(0), 0);
4854 if (ret
!= FFS_SUCCESS
)
4857 ret
= p_fs
->fs_func
->init_ext_entry(sb
, p_dir
, dentry
, num_entries
, p_uniname
, &dos_name
);
4858 if (ret
!= FFS_SUCCESS
)
4861 fid
->dir
.dir
= p_dir
->dir
;
4862 fid
->dir
.size
= p_dir
->size
;
4863 fid
->dir
.flags
= p_dir
->flags
;
4864 fid
->entry
= dentry
;
4866 fid
->attr
= ATTR_ARCHIVE
| mode
;
4867 fid
->flags
= (p_fs
->vol_type
== EXFAT
) ? 0x03 : 0x01;
4869 fid
->start_clu
= CLUSTER_32(~0);
4871 fid
->type
= TYPE_FILE
;
4873 fid
->hint_last_off
= -1;
4876 } /* end of create_file */
4878 void remove_file(struct inode
*inode
, CHAIN_T
*p_dir
, INT32 entry
)
4883 struct super_block
*sb
= inode
->i_sb
;
4884 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4886 ep
= get_entry_in_dir(sb
, p_dir
, entry
, §or
);
4890 buf_lock(sb
, sector
);
4892 /* buf_lock() before call count_ext_entries() */
4893 num_entries
= p_fs
->fs_func
->count_ext_entries(sb
, p_dir
, entry
, ep
);
4894 if (num_entries
< 0) {
4895 buf_unlock(sb
, sector
);
4900 buf_unlock(sb
, sector
);
4902 /* (1) update the directory entry */
4903 p_fs
->fs_func
->delete_dir_entry(sb
, p_dir
, entry
, 0, num_entries
);
4904 } /* end of remove_file */
4906 INT32
rename_file(struct inode
*inode
, CHAIN_T
*p_dir
, INT32 oldentry
, UNI_NAME_T
*p_uniname
, FILE_ID_T
*fid
)
4908 INT32 ret
, newentry
= -1, num_old_entries
, num_new_entries
;
4909 UINT32 sector_old
, sector_new
;
4910 DOS_NAME_T dos_name
;
4911 DENTRY_T
*epold
, *epnew
;
4912 struct super_block
*sb
= inode
->i_sb
;
4913 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
4915 epold
= get_entry_in_dir(sb
, p_dir
, oldentry
, §or_old
);
4917 return FFS_MEDIAERR
;
4919 buf_lock(sb
, sector_old
);
4921 /* buf_lock() before call count_ext_entries() */
4922 num_old_entries
= p_fs
->fs_func
->count_ext_entries(sb
, p_dir
, oldentry
, epold
);
4923 if (num_old_entries
< 0) {
4924 buf_unlock(sb
, sector_old
);
4925 return FFS_MEDIAERR
;
4929 ret
= get_num_entries_and_dos_name(sb
, p_dir
, p_uniname
, &num_new_entries
, &dos_name
);
4931 buf_unlock(sb
, sector_old
);
4935 if (num_old_entries
< num_new_entries
) {
4936 newentry
= find_empty_entry(inode
, p_dir
, num_new_entries
);
4938 buf_unlock(sb
, sector_old
);
4942 epnew
= get_entry_in_dir(sb
, p_dir
, newentry
, §or_new
);
4944 buf_unlock(sb
, sector_old
);
4945 return FFS_MEDIAERR
;
4948 MEMCPY((void *) epnew
, (void *) epold
, DENTRY_SIZE
);
4949 if (p_fs
->fs_func
->get_entry_type(epnew
) == TYPE_FILE
) {
4950 p_fs
->fs_func
->set_entry_attr(epnew
, p_fs
->fs_func
->get_entry_attr(epnew
) | ATTR_ARCHIVE
);
4951 fid
->attr
|= ATTR_ARCHIVE
;
4953 buf_modify(sb
, sector_new
);
4954 buf_unlock(sb
, sector_old
);
4956 if (p_fs
->vol_type
== EXFAT
) {
4957 epold
= get_entry_in_dir(sb
, p_dir
, oldentry
+1, §or_old
);
4958 buf_lock(sb
, sector_old
);
4959 epnew
= get_entry_in_dir(sb
, p_dir
, newentry
+1, §or_new
);
4961 if (!epold
|| !epnew
) {
4962 buf_unlock(sb
, sector_old
);
4963 return FFS_MEDIAERR
;
4966 MEMCPY((void *) epnew
, (void *) epold
, DENTRY_SIZE
);
4967 buf_modify(sb
, sector_new
);
4968 buf_unlock(sb
, sector_old
);
4971 ret
= p_fs
->fs_func
->init_ext_entry(sb
, p_dir
, newentry
, num_new_entries
, p_uniname
, &dos_name
);
4972 if (ret
!= FFS_SUCCESS
)
4975 p_fs
->fs_func
->delete_dir_entry(sb
, p_dir
, oldentry
, 0, num_old_entries
);
4976 fid
->entry
= newentry
;
4978 if (p_fs
->fs_func
->get_entry_type(epold
) == TYPE_FILE
) {
4979 p_fs
->fs_func
->set_entry_attr(epold
, p_fs
->fs_func
->get_entry_attr(epold
) | ATTR_ARCHIVE
);
4980 fid
->attr
|= ATTR_ARCHIVE
;
4982 buf_modify(sb
, sector_old
);
4983 buf_unlock(sb
, sector_old
);
4985 ret
= p_fs
->fs_func
->init_ext_entry(sb
, p_dir
, oldentry
, num_new_entries
, p_uniname
, &dos_name
);
4986 if (ret
!= FFS_SUCCESS
)
4989 p_fs
->fs_func
->delete_dir_entry(sb
, p_dir
, oldentry
, num_new_entries
, num_old_entries
);
4993 } /* end of rename_file */
4995 INT32
move_file(struct inode
*inode
, CHAIN_T
*p_olddir
, INT32 oldentry
, CHAIN_T
*p_newdir
, UNI_NAME_T
*p_uniname
, FILE_ID_T
*fid
)
4997 INT32 ret
, newentry
, num_new_entries
, num_old_entries
;
4998 UINT32 sector_mov
, sector_new
;
5000 DOS_NAME_T dos_name
;
5001 DENTRY_T
*epmov
, *epnew
;
5002 struct super_block
*sb
= inode
->i_sb
;
5003 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
5005 epmov
= get_entry_in_dir(sb
, p_olddir
, oldentry
, §or_mov
);
5007 return FFS_MEDIAERR
;
5009 /* check if the source and target directory is the same */
5010 if (p_fs
->fs_func
->get_entry_type(epmov
) == TYPE_DIR
&&
5011 p_fs
->fs_func
->get_entry_clu0(epmov
) == p_newdir
->dir
)
5012 return FFS_INVALIDPATH
;
5014 buf_lock(sb
, sector_mov
);
5016 /* buf_lock() before call count_ext_entries() */
5017 num_old_entries
= p_fs
->fs_func
->count_ext_entries(sb
, p_olddir
, oldentry
, epmov
);
5018 if (num_old_entries
< 0) {
5019 buf_unlock(sb
, sector_mov
);
5020 return FFS_MEDIAERR
;
5024 ret
= get_num_entries_and_dos_name(sb
, p_newdir
, p_uniname
, &num_new_entries
, &dos_name
);
5026 buf_unlock(sb
, sector_mov
);
5030 newentry
= find_empty_entry(inode
, p_newdir
, num_new_entries
);
5032 buf_unlock(sb
, sector_mov
);
5036 epnew
= get_entry_in_dir(sb
, p_newdir
, newentry
, §or_new
);
5038 buf_unlock(sb
, sector_mov
);
5039 return FFS_MEDIAERR
;
5042 MEMCPY((void *) epnew
, (void *) epmov
, DENTRY_SIZE
);
5043 if (p_fs
->fs_func
->get_entry_type(epnew
) == TYPE_FILE
) {
5044 p_fs
->fs_func
->set_entry_attr(epnew
, p_fs
->fs_func
->get_entry_attr(epnew
) | ATTR_ARCHIVE
);
5045 fid
->attr
|= ATTR_ARCHIVE
;
5047 buf_modify(sb
, sector_new
);
5048 buf_unlock(sb
, sector_mov
);
5050 if (p_fs
->vol_type
== EXFAT
) {
5051 epmov
= get_entry_in_dir(sb
, p_olddir
, oldentry
+1, §or_mov
);
5052 buf_lock(sb
, sector_mov
);
5053 epnew
= get_entry_in_dir(sb
, p_newdir
, newentry
+1, §or_new
);
5054 if (!epmov
|| !epnew
) {
5055 buf_unlock(sb
, sector_mov
);
5056 return FFS_MEDIAERR
;
5059 MEMCPY((void *) epnew
, (void *) epmov
, DENTRY_SIZE
);
5060 buf_modify(sb
, sector_new
);
5061 buf_unlock(sb
, sector_mov
);
5062 } else if (p_fs
->fs_func
->get_entry_type(epnew
) == TYPE_DIR
) {
5063 /* change ".." pointer to new parent dir */
5064 clu
.dir
= p_fs
->fs_func
->get_entry_clu0(epnew
);
5067 epnew
= get_entry_in_dir(sb
, &clu
, 1, §or_new
);
5069 return FFS_MEDIAERR
;
5071 if (p_newdir
->dir
== p_fs
->root_dir
)
5072 p_fs
->fs_func
->set_entry_clu0(epnew
, CLUSTER_32(0));
5074 p_fs
->fs_func
->set_entry_clu0(epnew
, p_newdir
->dir
);
5075 buf_modify(sb
, sector_new
);
5078 ret
= p_fs
->fs_func
->init_ext_entry(sb
, p_newdir
, newentry
, num_new_entries
, p_uniname
, &dos_name
);
5079 if (ret
!= FFS_SUCCESS
)
5082 p_fs
->fs_func
->delete_dir_entry(sb
, p_olddir
, oldentry
, 0, num_old_entries
);
5084 fid
->dir
.dir
= p_newdir
->dir
;
5085 fid
->dir
.size
= p_newdir
->size
;
5086 fid
->dir
.flags
= p_newdir
->flags
;
5088 fid
->entry
= newentry
;
5091 } /* end of move_file */
5094 * Sector Read/Write Functions
5097 INT32
sector_read(struct super_block
*sb
, UINT32 sec
, struct buffer_head
**bh
, INT32 read
)
5099 INT32 ret
= FFS_MEDIAERR
;
5100 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
5102 if ((sec
>= (p_fs
->PBR_sector
+p_fs
->num_sectors
)) && (p_fs
->num_sectors
> 0)) {
5103 PRINT("[EXFAT] sector_read: out of range error! (sec = %d)\n", sec
);
5108 if (!p_fs
->dev_ejected
) {
5109 ret
= bdev_read(sb
, sec
, bh
, 1, read
);
5110 if (ret
!= FFS_SUCCESS
)
5111 p_fs
->dev_ejected
= TRUE
;
5115 } /* end of sector_read */
5117 INT32
sector_write(struct super_block
*sb
, UINT32 sec
, struct buffer_head
*bh
, INT32 sync
)
5119 INT32 ret
= FFS_MEDIAERR
;
5120 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
5122 if (sec
>= (p_fs
->PBR_sector
+p_fs
->num_sectors
) && (p_fs
->num_sectors
> 0)) {
5123 PRINT("[EXFAT] sector_write: out of range error! (sec = %d)\n", sec
);
5128 PRINT("[EXFAT] sector_write: bh is NULL!\n");
5133 if (!p_fs
->dev_ejected
) {
5134 ret
= bdev_write(sb
, sec
, bh
, 1, sync
);
5135 if (ret
!= FFS_SUCCESS
)
5136 p_fs
->dev_ejected
= TRUE
;
5140 } /* end of sector_write */
5142 INT32
multi_sector_read(struct super_block
*sb
, UINT32 sec
, struct buffer_head
**bh
, INT32 num_secs
, INT32 read
)
5144 INT32 ret
= FFS_MEDIAERR
;
5145 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
5147 if (((sec
+num_secs
) > (p_fs
->PBR_sector
+p_fs
->num_sectors
)) && (p_fs
->num_sectors
> 0)) {
5148 PRINT("[EXFAT] multi_sector_read: out of range error! (sec = %d, num_secs = %d)\n", sec
, num_secs
);
5153 if (!p_fs
->dev_ejected
) {
5154 ret
= bdev_read(sb
, sec
, bh
, num_secs
, read
);
5155 if (ret
!= FFS_SUCCESS
)
5156 p_fs
->dev_ejected
= TRUE
;
5160 } /* end of multi_sector_read */
5162 INT32
multi_sector_write(struct super_block
*sb
, UINT32 sec
, struct buffer_head
*bh
, INT32 num_secs
, INT32 sync
)
5164 INT32 ret
= FFS_MEDIAERR
;
5165 FS_INFO_T
*p_fs
= &(EXFAT_SB(sb
)->fs_info
);
5167 if ((sec
+num_secs
) > (p_fs
->PBR_sector
+p_fs
->num_sectors
) && (p_fs
->num_sectors
> 0)) {
5168 PRINT("[EXFAT] multi_sector_write: out of range error! (sec = %d, num_secs = %d)\n", sec
, num_secs
);
5173 PRINT("[EXFAT] multi_sector_write: bh is NULL!\n");
5178 if (!p_fs
->dev_ejected
) {
5179 ret
= bdev_write(sb
, sec
, bh
, num_secs
, sync
);
5180 if (ret
!= FFS_SUCCESS
)
5181 p_fs
->dev_ejected
= TRUE
;
5185 } /* end of multi_sector_write */
5187 /* end of exfat_core.c */