exfat, version, 1.1.0p2, as downloaded from Samsung's website at: http://opensource...
[binbang:exfat-linux.git] / exfat.c
1 /* Some of the source code in this file came from "linux/fs/fat/misc.c".  */
2 /*
3  *  linux/fs/fat/misc.c
4  *
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)
8  */
9
10 /*
11  *  Copyright (C) 2012-2013 Samsung Electronics Co., Ltd.
12  *
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.
17  *
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.
22  *
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.
26  */
27
28 #include <linux/version.h>
29
30 #include "exfat_config.h"
31 #include "exfat_global.h"
32 #include "exfat_data.h"
33 #include "exfat_oal.h"
34
35 #include "exfat_blkdev.h"
36 #include "exfat_cache.h"
37 #include "exfat_nls.h"
38 #include "exfat_api.h"
39 #include "exfat_super.h"
40 #include "exfat.h"
41
42 #include <linux/blkdev.h>
43
44 #define THERE_IS_MBR        0 
45
46 #if (THERE_IS_MBR == 1)
47 #include "exfat_part.h"
48 #endif
49
50 #define DELAYED_SYNC        0
51
52 #define ELAPSED_TIME        0
53
54 #if (ELAPSED_TIME == 1)
55 #include <linux/time.h>
56
57 static UINT32 __t1, __t2;
58 static UINT32 get_current_msec(void)
59 {
60         struct timeval tm;
61         do_gettimeofday(&tm);
62         return (UINT32)(tm.tv_sec*1000000 + tm.tv_usec);
63 }
64 #define TIME_START()        do {__t1 = get_current_msec(); } while (0)
65 #define TIME_END()          do {__t2 = get_current_msec(); } while (0)
66 #define PRINT_TIME(n)       do {printk("[EXFAT] Elapsed time %d = %d (usec)\n", n, (__t2 - __t1)); } while (0)
67 #else
68 #define TIME_START()
69 #define TIME_END()
70 #define PRINT_TIME(n)
71 #endif
72
73 extern UINT8 uni_upcase[];
74 static UINT8 name_buf[MAX_PATH_LENGTH *MAX_CHARSET_SIZE];
75 static INT8 *reserved_names[] = {
76         "AUX     ", "CON     ", "NUL     ", "PRN     ",
77         "COM1    ", "COM2    ", "COM3    ", "COM4    ",
78         "COM5    ", "COM6    ", "COM7    ", "COM8    ", "COM9    ",
79         "LPT1    ", "LPT2    ", "LPT3    ", "LPT4    ",
80         "LPT5    ", "LPT6    ", "LPT7    ", "LPT8    ", "LPT9    ",
81         NULL
82 };
83
84 static UINT8 free_bit[] = {
85         0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,
86         0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3,
87         0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,
88         0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
89         0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2,
90         0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3,
91         0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,
92         0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5,
93         0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2,
94         0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3,
95         0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2,
96         0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4,
97         0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0                
98 };
99
100 static UINT8 used_bit[] = {
101         0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3,
102         2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4,
103         2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5,
104         4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
105         2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4,
106         3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6,
107         4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4,
108         3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
109         2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5,
110         4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5,
111         3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6,
112         5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
113         4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8            
114 };
115
116 INT32 ffsInit(void)
117 {
118         INT32 ret;
119
120         ret = bdev_init();
121         if (ret)
122                 return ret;
123
124         ret = fs_init();
125         if (ret)
126                 return ret;
127
128         return FFS_SUCCESS;
129 }
130
131 INT32 ffsShutdown(void)
132 {
133         INT32 ret;
134         ret = fs_shutdown();
135         if (ret)
136                 return ret;
137
138         ret = bdev_shutdown();
139         if (ret)
140                 return ret;
141
142         return FFS_SUCCESS;
143 }
144
145 INT32 ffsMountVol(struct super_block *sb, INT32 drv)
146 {
147         INT32 i, ret;
148 #if (THERE_IS_MBR == 1)
149         MBR_SECTOR_T *p_mbr;
150         PART_ENTRY_T *p_pte;
151 #endif
152         PBR_SECTOR_T *p_pbr;
153         struct buffer_head *tmp_bh = NULL;
154         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
155         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
156
157         printk("[EXFAT] ===== ffsMountVol =====\n");
158
159         p_fs->drv = drv;
160         p_fs->dev_ejected = FALSE;
161
162         if (bdev_open(sb))
163                 return FFS_MEDIAERR;
164
165         if (p_bd->sector_size < sb->s_blocksize)
166                 return FFS_MEDIAERR;
167         if (p_bd->sector_size > sb->s_blocksize)
168                 sb_set_blocksize(sb, p_bd->sector_size);
169
170         if (sector_read(sb, 0, &tmp_bh, 1) != FFS_SUCCESS)
171                 return FFS_MEDIAERR;
172
173 #if (THERE_IS_MBR == 1)
174         if (buf[0] != 0xEB) {
175                 p_mbr = (MBR_SECTOR_T *) tmp_bh->b_data;
176
177                 if (GET16_A(p_mbr->signature) != MBR_SIGNATURE) {
178                         brelse(tmp_bh);
179                         bdev_close(sb);
180                         return FFS_FORMATERR;
181                 }
182
183                 p_pte = (PART_ENTRY_T *) p_mbr->partition + 0;
184                 p_fs->PBR_sector = GET32(p_pte->start_sector);
185                 p_fs->num_sectors = GET32(p_pte->num_sectors);
186
187                 if (p_fs->num_sectors == 0) {
188                         brelse(tmp_bh);
189                         bdev_close(sb);
190                         return FFS_ERROR;
191                 }
192
193                 if (sector_read(sb, p_fs->PBR_sector, &tmp_bh, 1) != FFS_SUCCESS) {
194                         bdev_close(sb);
195                         return FFS_MEDIAERR;
196                 }
197         } else {
198 #endif
199                 p_fs->PBR_sector = 0;
200 #if (THERE_IS_MBR == 1)
201         }
202 #endif
203
204         p_pbr = (PBR_SECTOR_T *) tmp_bh->b_data;
205
206         if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) {
207                 brelse(tmp_bh);
208                 bdev_close(sb);
209                 return FFS_FORMATERR;
210         }
211
212         for (i = 0; i < 53; i++)
213                 if (p_pbr->bpb[i])
214                         break;
215
216         if (i < 53) {
217                 if (GET16(p_pbr->bpb+11))
218                         ret = fat16_mount(sb, p_pbr);
219                 else
220                         ret = fat32_mount(sb, p_pbr);
221         } else {
222                 ret = exfat_mount(sb, p_pbr);
223         }
224
225         brelse(tmp_bh);
226
227         if (ret) {
228                 bdev_close(sb);
229                 return ret;
230         }
231
232         if (p_fs->vol_type == EXFAT) {
233                 ret = load_alloc_bitmap(sb);
234                 if (ret) {
235                         bdev_close(sb);
236                         return ret;
237                 }
238                 ret = load_upcase_table(sb);
239                 if (ret) {
240                         free_alloc_bitmap(sb);
241                         bdev_close(sb);
242                         return ret;
243                 }
244         }
245
246         if (p_fs->dev_ejected) {
247                 if (p_fs->vol_type == EXFAT) {
248                         free_upcase_table(sb);
249                         free_alloc_bitmap(sb);
250                 }
251                 bdev_close(sb);
252                 return FFS_MEDIAERR;
253         }
254
255         return FFS_SUCCESS;
256 }
257
258 INT32 ffsUmountVol(struct super_block *sb)
259 {
260         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
261
262         fs_sync(sb, 0);
263         fs_set_vol_flags(sb, VOL_CLEAN);
264
265         if (p_fs->vol_type == EXFAT) {
266                 free_upcase_table(sb);
267                 free_alloc_bitmap(sb);
268         }
269
270         FAT_release_all(sb);
271         buf_release_all(sb);
272
273         bdev_close(sb);
274
275         if (p_fs->dev_ejected)
276                 return FFS_MEDIAERR;
277
278         return FFS_SUCCESS;
279 }
280
281 INT32 ffsGetVolInfo(struct super_block *sb, VOL_INFO_T *info)
282 {
283         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
284
285         if (p_fs->used_clusters == (UINT32) ~0)
286                 p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb);
287
288         info->FatType = p_fs->vol_type;
289         info->ClusterSize = p_fs->cluster_size;
290         info->NumClusters = p_fs->num_clusters - 2;
291         info->UsedClusters = p_fs->used_clusters;
292         info->FreeClusters = info->NumClusters - info->UsedClusters;
293
294         if (p_fs->dev_ejected)
295                 return FFS_MEDIAERR;
296
297         return FFS_SUCCESS;
298 }
299
300 INT32 ffsSyncVol(struct super_block *sb, INT32 do_sync)
301 {
302         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
303
304         fs_sync(sb, do_sync);
305         fs_set_vol_flags(sb, VOL_CLEAN);
306
307         if (p_fs->dev_ejected)
308                 return FFS_MEDIAERR;
309
310         return FFS_SUCCESS;
311 }
312
313 INT32 ffsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid)
314 {
315         INT32 ret, dentry, num_entries;
316         CHAIN_T dir;
317         UNI_NAME_T uni_name;
318         DOS_NAME_T dos_name;
319         DENTRY_T *ep, *ep2;
320         ENTRY_SET_CACHE_T *es=NULL;
321         struct super_block *sb = inode->i_sb;
322         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
323
324         PRINTK("ffsLookupFile entered\n");
325
326         ret = resolve_path(inode, path, &dir, &uni_name);
327         if (ret)
328                 return ret;
329
330         ret = get_num_entries_and_dos_name(sb, &dir, &uni_name, &num_entries, &dos_name);
331         if (ret)
332                 return ret;
333
334         dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries, &dos_name, TYPE_ALL);
335         if (dentry < -1)
336                 return FFS_NOTFOUND;
337
338         fid->dir.dir = dir.dir;
339         fid->dir.size = dir.size;
340         fid->dir.flags = dir.flags;
341         fid->entry = dentry;
342
343         if (dentry == -1) {
344                 fid->type = TYPE_DIR;
345                 fid->rwoffset = 0;
346                 fid->hint_last_off = -1;
347
348                 fid->attr = ATTR_SUBDIR;
349                 fid->flags = 0x01;
350                 fid->size = 0;
351                 fid->start_clu = p_fs->root_dir;
352         } else {
353                 if (p_fs->vol_type == EXFAT) {
354                         es = get_entry_set_in_dir(sb, &dir, dentry, ES_2_ENTRIES, &ep);
355                         if (!es)
356                                 return FFS_MEDIAERR;
357                         ep2 = ep+1;
358                 } else {
359                         ep = get_entry_in_dir(sb, &dir, dentry, NULL);
360                         if (!ep)
361                                 return FFS_MEDIAERR;
362                         ep2 = ep;
363                 }
364
365                 fid->type = p_fs->fs_func->get_entry_type(ep);
366                 fid->rwoffset = 0;
367                 fid->hint_last_off = -1;
368                 fid->attr = p_fs->fs_func->get_entry_attr(ep);
369
370                 fid->size = p_fs->fs_func->get_entry_size(ep2);
371                 if ((fid->type == TYPE_FILE) && (fid->size == 0)) {
372                         fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
373                         fid->start_clu = CLUSTER_32(~0);
374                 } else {
375                         fid->flags = p_fs->fs_func->get_entry_flag(ep2);
376                         fid->start_clu = p_fs->fs_func->get_entry_clu0(ep2);
377                 }
378
379                 if (p_fs->vol_type == EXFAT)
380                         release_entry_set(es);
381         }
382
383         if (p_fs->dev_ejected)
384                 return FFS_MEDIAERR;
385
386         PRINTK("ffsLookupFile exited successfully\n");
387
388         return FFS_SUCCESS;
389 }
390
391 INT32 ffsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid)
392 {
393         INT32 ret;
394         CHAIN_T dir;
395         UNI_NAME_T uni_name;
396         struct super_block *sb = inode->i_sb;
397         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
398
399         ret = resolve_path(inode, path, &dir, &uni_name);
400         if (ret)
401                 return ret;
402
403         fs_set_vol_flags(sb, VOL_DIRTY);
404
405         ret = create_file(inode, &dir, &uni_name, mode, fid);
406
407 #if (DELAYED_SYNC == 0)
408         fs_sync(sb, 0);
409         fs_set_vol_flags(sb, VOL_CLEAN);
410 #endif
411
412         if (p_fs->dev_ejected)
413                 return FFS_MEDIAERR;
414
415         return ret;
416 }
417
418 INT32 ffsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount)
419 {
420         INT32 offset, sec_offset, clu_offset;
421         UINT32 clu, LogSector;
422         UINT64 oneblkread, read_bytes;
423         struct buffer_head *tmp_bh = NULL;
424         struct super_block *sb = inode->i_sb;
425         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
426         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
427
428         if (fid->type != TYPE_FILE)
429                 return FFS_PERMISSIONERR;
430
431         if (fid->rwoffset > fid->size)
432                 fid->rwoffset = fid->size;
433
434         if (count > (fid->size - fid->rwoffset))
435                 count = fid->size - fid->rwoffset;
436
437         if (count == 0) {
438                 if (rcount != NULL)
439                         *rcount = 0;
440                 return FFS_EOF;
441         }
442
443         read_bytes = 0;
444
445         while (count > 0) {
446                 clu_offset = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits);
447                 clu = fid->start_clu;
448
449                 if (fid->flags == 0x03) {
450                         clu += clu_offset;
451                 } else {
452                         if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
453                                 (clu_offset >= fid->hint_last_off)) {
454                                 clu_offset -= fid->hint_last_off;
455                                 clu = fid->hint_last_clu;
456                         }
457
458                         while (clu_offset > 0) {
459                                 if (FAT_read(sb, clu, &clu) == -1)
460                                         return FFS_MEDIAERR;
461
462                                 clu_offset--;
463                         }
464                 }
465
466                 fid->hint_last_off = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits);
467                 fid->hint_last_clu = clu;
468
469                 offset = (INT32)(fid->rwoffset & (p_fs->cluster_size-1));
470                 sec_offset = offset >> p_bd->sector_size_bits;          
471                 offset &= p_bd->sector_size_mask;                      
472
473                 LogSector = START_SECTOR(clu) + sec_offset;
474
475                 oneblkread = (UINT64)(p_bd->sector_size - offset);
476                 if (oneblkread > count)
477                         oneblkread = count;
478
479                 if ((offset == 0) && (oneblkread == p_bd->sector_size)) {
480                         if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS)
481                                 goto err_out;
482                         MEMCPY(((INT8 *) buffer)+read_bytes, ((INT8 *) tmp_bh->b_data), (INT32) oneblkread);
483                 } else {
484                         if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS)
485                                 goto err_out;
486                         MEMCPY(((INT8 *) buffer)+read_bytes, ((INT8 *) tmp_bh->b_data)+offset, (INT32) oneblkread);
487                 }
488                 count -= oneblkread;
489                 read_bytes += oneblkread;
490                 fid->rwoffset += oneblkread;
491         }
492         brelse(tmp_bh);
493
494 err_out:
495         if (rcount != NULL)
496                 *rcount = read_bytes;
497
498         if (p_fs->dev_ejected)
499                 return FFS_MEDIAERR;
500
501         return FFS_SUCCESS;
502 }
503
504 INT32 ffsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount)
505 {
506         INT32 modified = FALSE, offset, sec_offset, clu_offset;
507         INT32 num_clusters, num_alloc, num_alloced = (INT32) ~0;
508         UINT32 clu, last_clu, LogSector, sector;
509         UINT64 oneblkwrite, write_bytes;
510         CHAIN_T new_clu;
511         TIMESTAMP_T tm;
512         DENTRY_T *ep, *ep2;
513         ENTRY_SET_CACHE_T *es = NULL;
514         struct buffer_head *tmp_bh = NULL;
515         struct super_block *sb = inode->i_sb;
516         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
517         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
518
519         if (fid->type != TYPE_FILE)
520                 return FFS_PERMISSIONERR;
521
522         if (fid->rwoffset > fid->size)
523                 fid->rwoffset = fid->size;
524
525         if (count == 0) {
526                 if (wcount != NULL)
527                         *wcount = 0;
528                 return FFS_SUCCESS;
529         }
530
531         fs_set_vol_flags(sb, VOL_DIRTY);
532
533         if (fid->size == 0)
534                 num_clusters = 0;
535         else
536                 num_clusters = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1;
537
538         write_bytes = 0;
539
540         while (count > 0) {
541                 clu_offset = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits);
542                 clu = last_clu = fid->start_clu;
543
544                 if (fid->flags == 0x03) {
545                         if ((clu_offset > 0) && (clu != CLUSTER_32(~0))) {
546                                 last_clu += clu_offset - 1;
547
548                                 if (clu_offset == num_clusters)
549                                         clu = CLUSTER_32(~0);
550                                 else
551                                         clu += clu_offset;
552                         }
553                 } else {
554                         if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
555                                 (clu_offset >= fid->hint_last_off)) {
556                                 clu_offset -= fid->hint_last_off;
557                                 clu = fid->hint_last_clu;
558                         }
559
560                         while ((clu_offset > 0) && (clu != CLUSTER_32(~0))) {
561                                 last_clu = clu;
562                                 if (FAT_read(sb, clu, &clu) == -1)
563                                         return FFS_MEDIAERR;
564
565                                 clu_offset--;
566                         }
567                 }
568
569                 if (clu == CLUSTER_32(~0)) {
570                         num_alloc = (INT32)((count-1) >> p_fs->cluster_size_bits) + 1;
571                         new_clu.dir = (last_clu == CLUSTER_32(~0)) ? CLUSTER_32(~0) : last_clu+1;
572                         new_clu.size = 0;
573                         new_clu.flags = fid->flags;
574
575                         num_alloced = p_fs->fs_func->alloc_cluster(sb, num_alloc, &new_clu);
576                         if (num_alloced == 0)
577                                 break;
578
579                         if (last_clu == CLUSTER_32(~0)) {
580                                 if (new_clu.flags == 0x01)
581                                         fid->flags = 0x01;
582                                 fid->start_clu = new_clu.dir;
583                                 modified = TRUE;
584                         } else {
585                                 if (new_clu.flags != fid->flags) {
586                                         exfat_chain_cont_cluster(sb, fid->start_clu, num_clusters);
587                                         fid->flags = 0x01;
588                                         modified = TRUE;
589                                 }
590                                 if (new_clu.flags == 0x01)
591                                         FAT_write(sb, last_clu, new_clu.dir);
592                         }
593
594                         num_clusters += num_alloced;
595                         clu = new_clu.dir;
596                 }
597
598                 fid->hint_last_off = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits);
599                 fid->hint_last_clu = clu;
600
601                 offset = (INT32)(fid->rwoffset & (p_fs->cluster_size-1));
602                 sec_offset = offset >> p_bd->sector_size_bits;          
603                 offset &= p_bd->sector_size_mask;                      
604
605                 LogSector = START_SECTOR(clu) + sec_offset;
606
607                 oneblkwrite = (UINT64)(p_bd->sector_size - offset);
608                 if (oneblkwrite > count)
609                         oneblkwrite = count;
610
611                 if ((offset == 0) && (oneblkwrite == p_bd->sector_size)) {
612                         if (sector_read(sb, LogSector, &tmp_bh, 0) != FFS_SUCCESS)
613                                 goto err_out;
614                         MEMCPY(((INT8 *) tmp_bh->b_data), ((INT8 *) buffer)+write_bytes, (INT32) oneblkwrite);
615                         if (sector_write(sb, LogSector, tmp_bh, 0) != FFS_SUCCESS) {
616                                 brelse(tmp_bh);
617                                 goto err_out;
618                         }
619                 } else {
620                         if ((offset > 0) || ((fid->rwoffset+oneblkwrite) < fid->size)) {
621                                 if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS)
622                                         goto err_out;
623                         } else {
624                                 if (sector_read(sb, LogSector, &tmp_bh, 0) != FFS_SUCCESS)
625                                         goto err_out;
626                         }
627
628                         MEMCPY(((INT8 *) tmp_bh->b_data)+offset, ((INT8 *) buffer)+write_bytes, (INT32) oneblkwrite);
629                         if (sector_write(sb, LogSector, tmp_bh, 0) != FFS_SUCCESS) {
630                                 brelse(tmp_bh);
631                                 goto err_out;
632                         }
633                 }
634
635                 count -= oneblkwrite;
636                 write_bytes += oneblkwrite;
637                 fid->rwoffset += oneblkwrite;
638
639                 fid->attr |= ATTR_ARCHIVE;
640
641                 if (fid->size < fid->rwoffset) {
642                         fid->size = fid->rwoffset;
643                         modified = TRUE;
644                 }
645         }
646
647         brelse(tmp_bh);
648
649         if (p_fs->vol_type == EXFAT) {
650                 es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
651                 if (es == NULL)
652                         goto err_out;
653                 ep2 = ep+1;
654         } else {
655                 ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, &sector);
656                 if (!ep)
657                         goto err_out;
658                 ep2 = ep;
659         }
660
661         p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY);
662         p_fs->fs_func->set_entry_attr(ep, fid->attr);
663
664         if (p_fs->vol_type != EXFAT)
665                 buf_modify(sb, sector);
666
667         if (modified) {
668                 if (p_fs->fs_func->get_entry_flag(ep2) != fid->flags)
669                         p_fs->fs_func->set_entry_flag(ep2, fid->flags);
670
671                 if (p_fs->fs_func->get_entry_size(ep2) != fid->size)
672                         p_fs->fs_func->set_entry_size(ep2, fid->size);
673
674                 if (p_fs->fs_func->get_entry_clu0(ep2) != fid->start_clu)
675                         p_fs->fs_func->set_entry_clu0(ep2, fid->start_clu);
676
677                 if (p_fs->vol_type != EXFAT)
678                         buf_modify(sb, sector);
679         }
680
681         if (p_fs->vol_type == EXFAT) {
682                 update_dir_checksum_with_entry_set(sb, es);
683                 release_entry_set(es);
684         }
685
686 #if (DELAYED_SYNC == 0)
687         fs_sync(sb, 0);
688         fs_set_vol_flags(sb, VOL_CLEAN);
689 #endif
690
691 err_out:
692         if (wcount != NULL)
693                 *wcount = write_bytes;
694
695         if (num_alloced == 0)
696                 return FFS_FULL;
697
698         if (p_fs->dev_ejected)
699                 return FFS_MEDIAERR;
700
701         return FFS_SUCCESS;
702 }
703
704 INT32 ffsTruncateFile(struct inode *inode, UINT64 new_size)
705 {
706         INT32 num_clusters;
707         UINT32 last_clu = CLUSTER_32(0), sector;
708         CHAIN_T clu;
709         TIMESTAMP_T tm;
710         DENTRY_T *ep, *ep2;
711         struct super_block *sb = inode->i_sb;
712         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
713         FILE_ID_T *fid = &(EXFAT_I(inode)->fid);
714         ENTRY_SET_CACHE_T *es=NULL;
715
716         if (fid->type != TYPE_FILE)
717                 return FFS_PERMISSIONERR;
718
719         if (fid->size <= new_size)
720                 return FFS_SUCCESS;
721
722         fs_set_vol_flags(sb, VOL_DIRTY);
723
724         clu.dir = fid->start_clu;
725         clu.size = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1;
726         clu.flags = fid->flags;
727
728         if (new_size > 0) {
729                 num_clusters = (INT32)((new_size-1) >> p_fs->cluster_size_bits) + 1;
730
731                 if (clu.flags == 0x03) {
732                         clu.dir += num_clusters;
733                 } else {
734                         while (num_clusters > 0) {
735                                 last_clu = clu.dir;
736                                 if (FAT_read(sb, clu.dir, &(clu.dir)) == -1)
737                                         return FFS_MEDIAERR;
738                                 num_clusters--;
739                         }
740                 }
741
742                 clu.size -= num_clusters;
743         }
744
745         fid->size = new_size;
746         fid->attr |= ATTR_ARCHIVE;
747         if (new_size == 0) {
748                 fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01;
749                 fid->start_clu = CLUSTER_32(~0);
750         }
751
752         if (p_fs->vol_type == EXFAT) {
753                 es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
754                 if (es == NULL)
755                         return FFS_MEDIAERR;
756                 ep2 = ep+1;
757         } else {
758                 ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, &sector);
759                 if (!ep)
760                         return FFS_MEDIAERR;
761                 ep2 = ep;
762         }
763
764         p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY);
765         p_fs->fs_func->set_entry_attr(ep, fid->attr);
766
767         p_fs->fs_func->set_entry_size(ep2, new_size);
768         if (new_size == 0) {
769                 p_fs->fs_func->set_entry_flag(ep2, 0x01);
770                 p_fs->fs_func->set_entry_clu0(ep2, CLUSTER_32(0));
771         }
772
773         if (p_fs->vol_type != EXFAT)
774                 buf_modify(sb, sector);
775         else {
776                 update_dir_checksum_with_entry_set(sb, es);
777                 release_entry_set(es);
778         }
779
780         if (last_clu != CLUSTER_32(0)) {
781                 if (fid->flags == 0x01)
782                         FAT_write(sb, last_clu, CLUSTER_32(~0));
783         }
784
785         p_fs->fs_func->free_cluster(sb, &clu, 0);
786
787         fid->hint_last_off = -1;
788         if (fid->rwoffset > fid->size) {
789                 fid->rwoffset = fid->size;
790         }
791
792 #if (DELAYED_SYNC == 0)
793         fs_sync(sb, 0);
794         fs_set_vol_flags(sb, VOL_CLEAN);
795 #endif
796
797         if (p_fs->dev_ejected)
798                 return FFS_MEDIAERR;
799
800         return FFS_SUCCESS;
801 }
802
803 INT32 ffsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry)
804 {
805         INT32 ret;
806         INT32 dentry;
807         CHAIN_T olddir, newdir;
808         CHAIN_T *p_dir=NULL;
809         UNI_NAME_T uni_name;
810         DENTRY_T *ep;
811         struct super_block *sb = old_parent_inode->i_sb;
812         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
813         UINT8 *new_path = (UINT8 *) new_dentry->d_name.name;
814         struct inode *new_inode = new_dentry->d_inode;
815         int num_entries;
816         FILE_ID_T *new_fid = NULL;
817         INT32 new_entry=0;
818
819         if ((new_path == NULL) || (STRLEN(new_path) == 0))
820                 return FFS_ERROR;
821
822         olddir.dir = fid->dir.dir;
823         olddir.size = fid->dir.size;
824         olddir.flags = fid->dir.flags;
825
826         dentry = fid->entry;
827
828         if (p_fs->vol_type != EXFAT) {
829                 if ((olddir.dir != p_fs->root_dir) && (dentry < 2))
830                         return FFS_PERMISSIONERR;
831         }
832
833         ep = get_entry_in_dir(sb, &olddir, dentry, NULL);
834         if (!ep)
835                 return FFS_MEDIAERR;
836
837         if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY)
838                 return FFS_PERMISSIONERR;
839
840         if (new_inode) {
841                 UINT32 entry_type;
842
843                 ret = FFS_MEDIAERR;
844                 new_fid = &EXFAT_I(new_inode)->fid;
845                 p_dir = &(new_fid->dir);
846                 new_entry = new_fid->entry;
847                 ep = get_entry_in_dir(sb, p_dir, new_entry, NULL);
848                 if (!ep)
849                         goto out;
850
851                 entry_type = p_fs->fs_func->get_entry_type(ep);
852
853                 if (entry_type == TYPE_DIR) {
854                         CHAIN_T new_clu;
855                         new_clu.dir = new_fid->start_clu;
856                         new_clu.size = (INT32)((new_fid->size-1) >> p_fs->cluster_size_bits) + 1;
857                         new_clu.flags = new_fid->flags;
858
859                         if (!is_dir_empty(sb, &new_clu))
860                                 return FFS_FILEEXIST;
861                 }
862         }
863
864         ret = resolve_path(new_parent_inode, new_path, &newdir, &uni_name);
865         if (ret)
866                 return ret;
867
868         fs_set_vol_flags(sb, VOL_DIRTY);
869
870         if (olddir.dir == newdir.dir)
871                 ret = rename_file(new_parent_inode, &olddir, dentry, &uni_name, fid);
872         else
873                 ret = move_file(new_parent_inode, &olddir, dentry, &newdir, &uni_name, fid);
874
875         if ((ret == FFS_SUCCESS) && new_inode) {
876                 ep = get_entry_in_dir(sb, p_dir, new_entry, NULL);
877                 if (!ep)
878                         goto out;
879
880                 num_entries = p_fs->fs_func->count_ext_entries(sb, p_dir, new_entry, ep);
881                 if (num_entries < 0)
882                         goto out;
883                 p_fs->fs_func->delete_dir_entry(sb, p_dir, new_entry, 0, num_entries+1);
884         }
885 out:
886 #if (DELAYED_SYNC == 0)
887         fs_sync(sb, 0);
888         fs_set_vol_flags(sb, VOL_CLEAN);
889 #endif
890
891         if (p_fs->dev_ejected)
892                 return FFS_MEDIAERR;
893
894         return ret;
895 }
896
897 INT32 ffsRemoveFile(struct inode *inode, FILE_ID_T *fid)
898 {
899         INT32 dentry;
900         CHAIN_T dir, clu_to_free;
901         DENTRY_T *ep;
902         struct super_block *sb = inode->i_sb;
903         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
904
905         dir.dir = fid->dir.dir;
906         dir.size = fid->dir.size;
907         dir.flags = fid->dir.flags;
908
909         dentry = fid->entry;
910
911         ep = get_entry_in_dir(sb, &dir, dentry, NULL);
912         if (!ep)
913                 return FFS_MEDIAERR;
914
915         if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY)
916                 return FFS_PERMISSIONERR;
917
918         fs_set_vol_flags(sb, VOL_DIRTY);
919
920         remove_file(inode, &dir, dentry);
921
922         clu_to_free.dir = fid->start_clu;
923         clu_to_free.size = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1;
924         clu_to_free.flags = fid->flags;
925
926         p_fs->fs_func->free_cluster(sb, &clu_to_free, 0);
927
928 #if (DELAYED_SYNC == 0)
929         fs_sync(sb, 0);
930         fs_set_vol_flags(sb, VOL_CLEAN);
931 #endif
932
933         if (p_fs->dev_ejected)
934                 return FFS_MEDIAERR;
935
936         return FFS_SUCCESS;
937 }
938
939 INT32 ffsSetAttr(struct inode *inode, UINT32 attr)
940 {
941         UINT32 type, sector;
942         DENTRY_T *ep;
943         struct super_block *sb = inode->i_sb;
944         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
945         FILE_ID_T *fid = &(EXFAT_I(inode)->fid);
946         UINT8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0;
947         ENTRY_SET_CACHE_T *es = NULL;
948
949         if (fid->attr == attr) {
950                 if (p_fs->dev_ejected)
951                         return FFS_MEDIAERR;
952                 return FFS_SUCCESS;
953         }
954
955         if (is_dir) {
956                 if ((fid->dir.dir == p_fs->root_dir) &&
957                         (fid->entry == -1)) {
958                         if (p_fs->dev_ejected)
959                                 return FFS_MEDIAERR;
960                         return FFS_SUCCESS;
961                 }
962         }
963
964         if (p_fs->vol_type == EXFAT) {
965                 es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
966                 if (es == NULL)
967                         return FFS_MEDIAERR;
968         } else {
969                 ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, &sector);
970                 if (!ep)
971                         return FFS_MEDIAERR;
972         }
973
974         type = p_fs->fs_func->get_entry_type(ep);
975
976         if (((type == TYPE_FILE) && (attr & ATTR_SUBDIR)) ||
977                 ((type == TYPE_DIR) && (!(attr & ATTR_SUBDIR)))) {
978                 INT32 err;
979                 if (p_fs->dev_ejected)
980                         err = FFS_MEDIAERR;
981                 else
982                         err = FFS_ERROR;
983
984                 if (p_fs->vol_type == EXFAT)
985                         release_entry_set(es);
986                 return err;
987         }
988
989         fs_set_vol_flags(sb, VOL_DIRTY);
990
991         fid->attr = attr;
992         p_fs->fs_func->set_entry_attr(ep, attr);
993
994         if (p_fs->vol_type != EXFAT)
995                 buf_modify(sb, sector);
996         else {
997                 update_dir_checksum_with_entry_set(sb, es);
998                 release_entry_set(es);
999         }
1000
1001 #if (DELAYED_SYNC == 0)
1002         fs_sync(sb, 0);
1003         fs_set_vol_flags(sb, VOL_CLEAN);
1004 #endif
1005
1006         if (p_fs->dev_ejected)
1007                 return FFS_MEDIAERR;
1008
1009         return FFS_SUCCESS;
1010 }
1011
1012 INT32 ffsGetStat(struct inode *inode, DIR_ENTRY_T *info)
1013 {
1014         UINT32 sector;
1015         INT32 count;
1016         CHAIN_T dir;
1017         UNI_NAME_T uni_name;
1018         TIMESTAMP_T tm;
1019         DENTRY_T *ep, *ep2;
1020         struct super_block *sb = inode->i_sb;
1021         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1022         FILE_ID_T *fid = &(EXFAT_I(inode)->fid);
1023         ENTRY_SET_CACHE_T *es=NULL;
1024         UINT8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0;
1025
1026         PRINTK("ffsGetStat entered\n");
1027
1028         if (is_dir) {
1029                 if ((fid->dir.dir == p_fs->root_dir) &&
1030                         (fid->entry == -1)) {
1031                         info->Attr = ATTR_SUBDIR;
1032                         MEMSET((INT8 *) &info->CreateTimestamp, 0, sizeof(DATE_TIME_T));
1033                         MEMSET((INT8 *) &info->ModifyTimestamp, 0, sizeof(DATE_TIME_T));
1034                         MEMSET((INT8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T));
1035                         STRCPY(info->ShortName, ".");
1036                         STRCPY(info->Name, ".");
1037
1038                         dir.dir = p_fs->root_dir;
1039                         dir.flags = 0x01;
1040
1041                         if (p_fs->root_dir == CLUSTER_32(0))
1042                                 info->Size = p_fs->dentries_in_root << DENTRY_SIZE_BITS;
1043                         else
1044                                 info->Size = count_num_clusters(sb, &dir) << p_fs->cluster_size_bits;
1045
1046                         count = count_dos_name_entries(sb, &dir, TYPE_DIR);
1047                         if (count < 0)
1048                                 return FFS_MEDIAERR;
1049                         info->NumSubdirs = count;
1050
1051                         if (p_fs->dev_ejected)
1052                                 return FFS_MEDIAERR;
1053                         return FFS_SUCCESS;
1054                 }
1055         }
1056
1057         if (p_fs->vol_type == EXFAT) {
1058                 es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_2_ENTRIES, &ep);
1059                 if (es == NULL)
1060                         return FFS_MEDIAERR;
1061                 ep2 = ep+1;
1062         } else {
1063                 ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, &sector);
1064                 if (!ep)
1065                         return FFS_MEDIAERR;
1066                 ep2 = ep;
1067                 buf_lock(sb, sector);
1068         }
1069
1070         info->Attr = p_fs->fs_func->get_entry_attr(ep);
1071
1072         p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE);
1073         info->CreateTimestamp.Year = tm.year;
1074         info->CreateTimestamp.Month = tm.mon;
1075         info->CreateTimestamp.Day = tm.day;
1076         info->CreateTimestamp.Hour = tm.hour;
1077         info->CreateTimestamp.Minute = tm.min;
1078         info->CreateTimestamp.Second = tm.sec;
1079         info->CreateTimestamp.MilliSecond = 0;
1080
1081         p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY);
1082         info->ModifyTimestamp.Year = tm.year;
1083         info->ModifyTimestamp.Month = tm.mon;
1084         info->ModifyTimestamp.Day = tm.day;
1085         info->ModifyTimestamp.Hour = tm.hour;
1086         info->ModifyTimestamp.Minute = tm.min;
1087         info->ModifyTimestamp.Second = tm.sec;
1088         info->ModifyTimestamp.MilliSecond = 0;
1089
1090         MEMSET((INT8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T));
1091
1092         *(uni_name.name) = 0x0;
1093         p_fs->fs_func->get_uni_name_from_ext_entry(sb, &(fid->dir), fid->entry, uni_name.name);
1094         if (*(uni_name.name) == 0x0)
1095                 get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x1);
1096         nls_uniname_to_cstring(sb, info->Name, &uni_name);
1097
1098         if (p_fs->vol_type == EXFAT) {
1099                 info->NumSubdirs = 2;
1100         } else {
1101                 buf_unlock(sb, sector);
1102                 get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x0);
1103                 nls_uniname_to_cstring(sb, info->ShortName, &uni_name);
1104                 info->NumSubdirs = 0;
1105         }
1106
1107         info->Size = p_fs->fs_func->get_entry_size(ep2);
1108
1109         if (p_fs->vol_type == EXFAT)
1110                 release_entry_set(es);
1111
1112         if (is_dir) {
1113                 dir.dir = fid->start_clu;
1114                 dir.flags = 0x01;
1115
1116                 if (info->Size == 0)
1117                         info->Size = (UINT64) count_num_clusters(sb, &dir) << p_fs->cluster_size_bits;
1118
1119                 count = count_dos_name_entries(sb, &dir, TYPE_DIR);
1120                 if (count < 0)
1121                         return FFS_MEDIAERR;
1122                 info->NumSubdirs += count;
1123         }
1124
1125         if (p_fs->dev_ejected)
1126                 return FFS_MEDIAERR;
1127
1128         PRINTK("ffsGetStat exited successfully\n");
1129         return FFS_SUCCESS;
1130 }
1131
1132 INT32 ffsSetStat(struct inode *inode, DIR_ENTRY_T *info)
1133 {
1134         UINT32 sector;
1135         TIMESTAMP_T tm;
1136         DENTRY_T *ep, *ep2;
1137         ENTRY_SET_CACHE_T *es=NULL;
1138         struct super_block *sb = inode->i_sb;
1139         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1140         FILE_ID_T *fid = &(EXFAT_I(inode)->fid);
1141         UINT8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0;
1142
1143         if (is_dir) {
1144                 if ((fid->dir.dir == p_fs->root_dir) &&
1145                         (fid->entry == -1)) {
1146                         if (p_fs->dev_ejected)
1147                                 return FFS_MEDIAERR;
1148                         return FFS_SUCCESS;
1149                 }
1150         }
1151
1152         fs_set_vol_flags(sb, VOL_DIRTY);
1153
1154         if (p_fs->vol_type == EXFAT) {
1155                 es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
1156                 if (es == NULL)
1157                         return FFS_MEDIAERR;
1158                 ep2 = ep+1;
1159         } else {
1160                 ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, &sector);
1161                 if (!ep)
1162                         return FFS_MEDIAERR;
1163                 ep2 = ep;
1164         }
1165
1166
1167         p_fs->fs_func->set_entry_attr(ep, info->Attr);
1168
1169         tm.sec  = info->CreateTimestamp.Second;
1170         tm.min  = info->CreateTimestamp.Minute;
1171         tm.hour = info->CreateTimestamp.Hour;
1172         tm.day  = info->CreateTimestamp.Day;
1173         tm.mon  = info->CreateTimestamp.Month;
1174         tm.year = info->CreateTimestamp.Year;
1175         p_fs->fs_func->set_entry_time(ep, &tm, TM_CREATE);
1176
1177         tm.sec  = info->ModifyTimestamp.Second;
1178         tm.min  = info->ModifyTimestamp.Minute;
1179         tm.hour = info->ModifyTimestamp.Hour;
1180         tm.day  = info->ModifyTimestamp.Day;
1181         tm.mon  = info->ModifyTimestamp.Month;
1182         tm.year = info->ModifyTimestamp.Year;
1183         p_fs->fs_func->set_entry_time(ep, &tm, TM_MODIFY);
1184
1185
1186         p_fs->fs_func->set_entry_size(ep2, info->Size);
1187
1188         if (p_fs->vol_type != EXFAT) {
1189                 buf_modify(sb, sector);
1190         } else {
1191                 update_dir_checksum_with_entry_set(sb, es);
1192                 release_entry_set(es);
1193         }
1194
1195         if (p_fs->dev_ejected)
1196                 return FFS_MEDIAERR;
1197
1198         return FFS_SUCCESS;
1199 }
1200
1201 INT32 ffsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu)
1202 {
1203         INT32 num_clusters, num_alloced, modified = FALSE;
1204         UINT32 last_clu, sector;
1205         CHAIN_T new_clu;
1206         DENTRY_T *ep;
1207         ENTRY_SET_CACHE_T *es = NULL;
1208         struct super_block *sb = inode->i_sb;
1209         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1210         FILE_ID_T *fid = &(EXFAT_I(inode)->fid);
1211
1212         fid->rwoffset = (INT64)(clu_offset) << p_fs->cluster_size_bits;
1213
1214         if (EXFAT_I(inode)->mmu_private == 0)
1215                 num_clusters = 0;
1216         else
1217                 num_clusters = (INT32)((EXFAT_I(inode)->mmu_private-1) >> p_fs->cluster_size_bits) + 1;
1218
1219         *clu = last_clu = fid->start_clu;
1220
1221         if (fid->flags == 0x03) {
1222                 if ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) {
1223                         last_clu += clu_offset - 1;
1224
1225                         if (clu_offset == num_clusters)
1226                                 *clu = CLUSTER_32(~0);
1227                         else
1228                                 *clu += clu_offset;
1229                 }
1230         } else {
1231                 if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
1232                         (clu_offset >= fid->hint_last_off)) {
1233                         clu_offset -= fid->hint_last_off;
1234                         *clu = fid->hint_last_clu;
1235                 }
1236
1237                 while ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) {
1238                         last_clu = *clu;
1239                         if (FAT_read(sb, *clu, clu) == -1)
1240                                 return FFS_MEDIAERR;
1241                         clu_offset--;
1242                 }
1243         }
1244
1245         if (*clu == CLUSTER_32(~0)) {
1246                 fs_set_vol_flags(sb, VOL_DIRTY);
1247
1248                 new_clu.dir = (last_clu == CLUSTER_32(~0)) ? CLUSTER_32(~0) : last_clu+1;
1249                 new_clu.size = 0;
1250                 new_clu.flags = fid->flags;
1251
1252                 num_alloced = p_fs->fs_func->alloc_cluster(sb, 1, &new_clu);
1253                 if (num_alloced < 1)
1254                         return FFS_FULL;
1255
1256                 if (last_clu == CLUSTER_32(~0)) {
1257                         if (new_clu.flags == 0x01)
1258                                 fid->flags = 0x01;
1259                         fid->start_clu = new_clu.dir;
1260                         modified = TRUE;
1261                 } else {
1262                         if (new_clu.flags != fid->flags) {
1263                                 exfat_chain_cont_cluster(sb, fid->start_clu, num_clusters);
1264                                 fid->flags = 0x01;
1265                                 modified = TRUE;
1266                         }
1267                         if (new_clu.flags == 0x01)
1268                                 FAT_write(sb, last_clu, new_clu.dir);
1269                 }
1270
1271                 num_clusters += num_alloced;
1272                 *clu = new_clu.dir;
1273
1274                 if (p_fs->vol_type == EXFAT) {
1275                         es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep);
1276                         if (es == NULL)
1277                                 return FFS_MEDIAERR;
1278                         ep++;
1279                 }
1280
1281                 if (modified) {
1282                         if (p_fs->vol_type != EXFAT) {
1283                                 ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, &sector);
1284                                 if (!ep)
1285                                         return FFS_MEDIAERR;
1286                         }
1287
1288                         if (p_fs->fs_func->get_entry_flag(ep) != fid->flags)
1289                                 p_fs->fs_func->set_entry_flag(ep, fid->flags);
1290
1291                         if (p_fs->fs_func->get_entry_clu0(ep) != fid->start_clu)
1292                                 p_fs->fs_func->set_entry_clu0(ep, fid->start_clu);
1293
1294                         if (p_fs->vol_type != EXFAT)
1295                                 buf_modify(sb, sector);
1296                 }
1297
1298                 if (p_fs->vol_type == EXFAT) {
1299                         update_dir_checksum_with_entry_set(sb, es);
1300                         release_entry_set(es);
1301                 }
1302
1303                 inode->i_blocks += num_alloced << (p_fs->cluster_size_bits - 9);
1304         }
1305
1306         fid->hint_last_off = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits);
1307         fid->hint_last_clu = *clu;
1308
1309         if (p_fs->dev_ejected)
1310                 return FFS_MEDIAERR;
1311
1312         return FFS_SUCCESS;
1313 }
1314
1315 INT32 ffsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid)
1316 {
1317         INT32 ret;
1318         CHAIN_T dir;
1319         UNI_NAME_T uni_name;
1320         struct super_block *sb = inode->i_sb;
1321         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1322
1323         PRINTK("ffsCreateDir entered\n");
1324
1325         ret = resolve_path(inode, path, &dir, &uni_name);
1326         if (ret)
1327                 return ret;
1328
1329         fs_set_vol_flags(sb, VOL_DIRTY);
1330
1331         ret = create_dir(inode, &dir, &uni_name, fid);
1332
1333 #if (DELAYED_SYNC == 0)
1334         fs_sync(sb, 0);
1335         fs_set_vol_flags(sb, VOL_CLEAN);
1336 #endif
1337
1338         if (p_fs->dev_ejected)
1339                 return FFS_MEDIAERR;
1340
1341         return ret;
1342 }
1343
1344 INT32 ffsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry)
1345 {
1346         INT32 i, dentry, clu_offset;
1347         INT32 dentries_per_clu, dentries_per_clu_bits = 0;
1348         UINT32 type, sector;
1349         CHAIN_T dir, clu;
1350         UNI_NAME_T uni_name;
1351         TIMESTAMP_T tm;
1352         DENTRY_T *ep;
1353         struct super_block *sb = inode->i_sb;
1354         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1355         FILE_ID_T *fid = &(EXFAT_I(inode)->fid);
1356
1357         if (fid->type != TYPE_DIR)
1358                 return FFS_PERMISSIONERR;
1359
1360         if (fid->entry == -1) {
1361                 dir.dir = p_fs->root_dir;
1362                 dir.flags = 0x01;
1363         } else {
1364                 dir.dir = fid->start_clu;
1365                 dir.size = (INT32)(fid->size >> p_fs->cluster_size_bits);
1366                 dir.flags = fid->flags;
1367         }
1368
1369         dentry = (INT32) fid->rwoffset;
1370
1371         if (dir.dir == CLUSTER_32(0)) {
1372                 dentries_per_clu = p_fs->dentries_in_root;
1373
1374                 if (dentry == dentries_per_clu) {
1375                         clu.dir = CLUSTER_32(~0);
1376                 } else {
1377                         clu.dir = dir.dir;
1378                         clu.size = dir.size;
1379                         clu.flags = dir.flags;
1380                 }
1381         } else {
1382                 dentries_per_clu = p_fs->dentries_per_clu;
1383                 dentries_per_clu_bits = my_log2(dentries_per_clu);
1384
1385                 clu_offset = dentry >> dentries_per_clu_bits;
1386                 clu.dir = dir.dir;
1387                 clu.size = dir.size;
1388                 clu.flags = dir.flags;
1389
1390                 if (clu.flags == 0x03) {
1391                         clu.dir += clu_offset;
1392                         clu.size -= clu_offset;
1393                 } else {
1394                         if ((clu_offset > 0) && (fid->hint_last_off > 0) &&
1395                                 (clu_offset >= fid->hint_last_off)) {
1396                                 clu_offset -= fid->hint_last_off;
1397                                 clu.dir = fid->hint_last_clu;
1398                         }
1399
1400                         while (clu_offset > 0) {
1401                                 if (FAT_read(sb, clu.dir, &(clu.dir)) == -1)
1402                                         return FFS_MEDIAERR;
1403
1404                                 clu_offset--;
1405                         }
1406                 }
1407         }
1408
1409         while (clu.dir != CLUSTER_32(~0)) {
1410                 if (p_fs->dev_ejected)
1411                         break;
1412
1413                 if (dir.dir == CLUSTER_32(0))
1414                         i = dentry % dentries_per_clu;
1415                 else
1416                         i = dentry & (dentries_per_clu-1);
1417
1418                 for ( ; i < dentries_per_clu; i++, dentry++) {
1419                         ep = get_entry_in_dir(sb, &clu, i, &sector);
1420                         if (!ep)
1421                                 return FFS_MEDIAERR;
1422
1423                         type = p_fs->fs_func->get_entry_type(ep);
1424
1425                         if (type == TYPE_UNUSED)
1426                                 break;
1427
1428                         if ((type != TYPE_FILE) && (type != TYPE_DIR))
1429                                 continue;
1430
1431                         buf_lock(sb, sector);
1432                         dir_entry->Attr = p_fs->fs_func->get_entry_attr(ep);
1433
1434                         p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE);
1435                         dir_entry->CreateTimestamp.Year = tm.year;
1436                         dir_entry->CreateTimestamp.Month = tm.mon;
1437                         dir_entry->CreateTimestamp.Day = tm.day;
1438                         dir_entry->CreateTimestamp.Hour = tm.hour;
1439                         dir_entry->CreateTimestamp.Minute = tm.min;
1440                         dir_entry->CreateTimestamp.Second = tm.sec;
1441                         dir_entry->CreateTimestamp.MilliSecond = 0;
1442
1443                         p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY);
1444                         dir_entry->ModifyTimestamp.Year = tm.year;
1445                         dir_entry->ModifyTimestamp.Month = tm.mon;
1446                         dir_entry->ModifyTimestamp.Day = tm.day;
1447                         dir_entry->ModifyTimestamp.Hour = tm.hour;
1448                         dir_entry->ModifyTimestamp.Minute = tm.min;
1449                         dir_entry->ModifyTimestamp.Second = tm.sec;
1450                         dir_entry->ModifyTimestamp.MilliSecond = 0;
1451
1452                         MEMSET((INT8 *) &dir_entry->AccessTimestamp, 0, sizeof(DATE_TIME_T));
1453
1454                         *(uni_name.name) = 0x0;
1455                         p_fs->fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry, uni_name.name);
1456                         if (*(uni_name.name) == 0x0)
1457                                 get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x1);
1458                         nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name);
1459                         buf_unlock(sb, sector);
1460
1461                         if (p_fs->vol_type == EXFAT) {
1462                                 ep = get_entry_in_dir(sb, &clu, i+1, NULL);
1463                                 if (!ep)
1464                                         return FFS_MEDIAERR;
1465                         } else {
1466                                 get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x0);
1467                                 nls_uniname_to_cstring(sb, dir_entry->ShortName, &uni_name);
1468                         }
1469
1470                         dir_entry->Size = p_fs->fs_func->get_entry_size(ep);
1471
1472                         if (dir.dir == CLUSTER_32(0)) {
1473                         } else {
1474                                 fid->hint_last_off = dentry >> dentries_per_clu_bits;
1475                                 fid->hint_last_clu = clu.dir;
1476                         }
1477
1478                         fid->rwoffset = (INT64) ++dentry;
1479
1480                         if (p_fs->dev_ejected)
1481                                 return FFS_MEDIAERR;
1482
1483                         return FFS_SUCCESS;
1484                 }
1485
1486                 if (dir.dir == CLUSTER_32(0))
1487                         break;
1488
1489                 if (clu.flags == 0x03) {
1490                         if ((--clu.size) > 0)
1491                                 clu.dir++;
1492                         else
1493                                 clu.dir = CLUSTER_32(~0);
1494                 } else {
1495                         if (FAT_read(sb, clu.dir, &(clu.dir)) == -1)
1496                                 return FFS_MEDIAERR;
1497                 }
1498         }
1499
1500         *(dir_entry->Name) = '\0';
1501
1502         fid->rwoffset = (INT64) ++dentry;
1503
1504         if (p_fs->dev_ejected)
1505                 return FFS_MEDIAERR;
1506
1507         return FFS_SUCCESS;
1508 }
1509
1510 INT32 ffsRemoveDir(struct inode *inode, FILE_ID_T *fid)
1511 {
1512         INT32 dentry;
1513         CHAIN_T dir, clu_to_free;
1514         struct super_block *sb = inode->i_sb;
1515         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1516
1517         dir.dir = fid->dir.dir;
1518         dir.size = fid->dir.size;
1519         dir.flags = fid->dir.flags;
1520
1521         dentry = fid->entry;
1522
1523         if (p_fs->vol_type != EXFAT) {
1524                 if ((dir.dir != p_fs->root_dir) && (dentry < 2))
1525                         return FFS_PERMISSIONERR;
1526         }
1527
1528         clu_to_free.dir = fid->start_clu;
1529         clu_to_free.size = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1;
1530         clu_to_free.flags = fid->flags;
1531
1532         if (!is_dir_empty(sb, &clu_to_free))
1533                 return FFS_FILEEXIST;
1534
1535         fs_set_vol_flags(sb, VOL_DIRTY);
1536
1537         remove_file(inode, &dir, dentry);
1538
1539         p_fs->fs_func->free_cluster(sb, &clu_to_free, 1);
1540
1541 #if (DELAYED_SYNC == 0)
1542         fs_sync(sb, 0);
1543         fs_set_vol_flags(sb, VOL_CLEAN);
1544 #endif
1545
1546         if (p_fs->dev_ejected)
1547                 return FFS_MEDIAERR;
1548
1549         return FFS_SUCCESS;
1550 }
1551
1552 INT32 fs_init(void)
1553 {
1554         if (sizeof(DENTRY_T) != DENTRY_SIZE) {
1555                 return FFS_ALIGNMENTERR;
1556         }
1557
1558         if (sizeof(DOS_DENTRY_T) != DENTRY_SIZE) {
1559                 return FFS_ALIGNMENTERR;
1560         }
1561
1562         if (sizeof(EXT_DENTRY_T) != DENTRY_SIZE) {
1563                 return FFS_ALIGNMENTERR;
1564         }
1565
1566         if (sizeof(FILE_DENTRY_T) != DENTRY_SIZE) {
1567                 return FFS_ALIGNMENTERR;
1568         }
1569
1570         if (sizeof(STRM_DENTRY_T) != DENTRY_SIZE) {
1571                 return FFS_ALIGNMENTERR;
1572         }
1573
1574         if (sizeof(NAME_DENTRY_T) != DENTRY_SIZE) {
1575                 return FFS_ALIGNMENTERR;
1576         }
1577
1578         if (sizeof(BMAP_DENTRY_T) != DENTRY_SIZE) {
1579                 return FFS_ALIGNMENTERR;
1580         }
1581
1582         if (sizeof(CASE_DENTRY_T) != DENTRY_SIZE) {
1583                 return FFS_ALIGNMENTERR;
1584         }
1585
1586         if (sizeof(VOLM_DENTRY_T) != DENTRY_SIZE) {
1587                 return FFS_ALIGNMENTERR;
1588         }
1589
1590         return FFS_SUCCESS;
1591 }
1592
1593 INT32 fs_shutdown(void)
1594 {
1595         return FFS_SUCCESS;
1596 }
1597
1598 void fs_set_vol_flags(struct super_block *sb, UINT32 new_flag)
1599 {
1600         PBR_SECTOR_T *p_pbr;
1601         BPBEX_T *p_bpb;
1602         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1603
1604         if (p_fs->vol_flag == new_flag)
1605                 return;
1606
1607         p_fs->vol_flag = new_flag;
1608
1609         if (p_fs->vol_type == EXFAT) {
1610                 if (p_fs->pbr_bh == NULL) {
1611                         if (sector_read(sb, p_fs->PBR_sector, &(p_fs->pbr_bh), 1) != FFS_SUCCESS)
1612                                 return;
1613                 }
1614
1615                 p_pbr = (PBR_SECTOR_T *) p_fs->pbr_bh->b_data;
1616                 p_bpb = (BPBEX_T *) p_pbr->bpb;
1617                 SET16(p_bpb->vol_flags, (UINT16) new_flag);
1618
1619                 if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh)))
1620                         sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1);
1621                 else
1622                         sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0);
1623         }
1624 }
1625
1626 void fs_sync(struct super_block *sb, INT32 do_sync)
1627 {
1628         if (do_sync)
1629                 bdev_sync(sb);
1630 }
1631
1632 void fs_error(struct super_block *sb)
1633 {
1634         struct exfat_mount_options *opts = &EXFAT_SB(sb)->options;
1635
1636         if (opts->errors == EXFAT_ERRORS_PANIC)
1637                 panic("EXFAT: fs panic from previous error\n");
1638         else if ((opts->errors == EXFAT_ERRORS_RO) && !(sb->s_flags & MS_RDONLY)) {
1639                 sb->s_flags |= MS_RDONLY;
1640                 printk(KERN_ERR "EXFAT: Filesystem has been set read-only\n");
1641         }
1642 }
1643
1644 INT32 clear_cluster(struct super_block *sb, UINT32 clu)
1645 {
1646         UINT32 s, n;
1647         INT32 ret = FFS_SUCCESS;
1648         struct buffer_head *tmp_bh = NULL;
1649         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1650         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
1651
1652         if (clu == CLUSTER_32(0)) {
1653                 s = p_fs->root_start_sector;
1654                 n = p_fs->data_start_sector;
1655         } else {
1656                 s = START_SECTOR(clu);
1657                 n = s + p_fs->sectors_per_clu;
1658         }
1659
1660         for ( ; s < n; s++) {
1661                 if ((ret = sector_read(sb, s, &tmp_bh, 0)) != FFS_SUCCESS)
1662                         return ret;
1663
1664                 MEMSET((INT8 *) tmp_bh->b_data, 0x0, p_bd->sector_size);
1665                 if ((ret = sector_write(sb, s, tmp_bh, 0)) !=FFS_SUCCESS)
1666                         break;
1667         }
1668
1669         brelse(tmp_bh);
1670         return ret;
1671 }
1672
1673 INT32 fat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain)
1674 {
1675         INT32 i, num_clusters = 0;
1676         UINT32 new_clu, last_clu = CLUSTER_32(~0), read_clu;
1677         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1678
1679         new_clu = p_chain->dir;
1680         if (new_clu == CLUSTER_32(~0))
1681                 new_clu = p_fs->clu_srch_ptr;
1682         else if (new_clu >= p_fs->num_clusters)
1683                 new_clu = 2;
1684
1685         sb->s_dirt = 1;
1686
1687         p_chain->dir = CLUSTER_32(~0);
1688
1689         for (i = 2; i < p_fs->num_clusters; i++) {
1690                 if (FAT_read(sb, new_clu, &read_clu) != 0)
1691                         return 0;
1692
1693                 if (read_clu == CLUSTER_32(0)) {
1694                         FAT_write(sb, new_clu, CLUSTER_32(~0));
1695                         num_clusters++;
1696
1697                         if (p_chain->dir == CLUSTER_32(~0))
1698                                 p_chain->dir = new_clu;
1699                         else
1700                                 FAT_write(sb, last_clu, new_clu);
1701
1702                         last_clu = new_clu;
1703
1704                         if ((--num_alloc) == 0) {
1705                                 p_fs->clu_srch_ptr = new_clu;
1706                                 if (p_fs->used_clusters != (UINT32) ~0)
1707                                         p_fs->used_clusters += num_clusters;
1708
1709                                 return(num_clusters);
1710                         }
1711                 }
1712                 if ((++new_clu) >= p_fs->num_clusters)
1713                         new_clu = 2;
1714         }
1715
1716         p_fs->clu_srch_ptr = new_clu;
1717         if (p_fs->used_clusters != (UINT32) ~0)
1718                 p_fs->used_clusters += num_clusters;
1719
1720         return(num_clusters);
1721 }
1722
1723 INT32 exfat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain)
1724 {
1725         INT32 num_clusters = 0;
1726         UINT32 hint_clu, new_clu, last_clu = CLUSTER_32(~0);
1727         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1728
1729         hint_clu = p_chain->dir;
1730         if (hint_clu == CLUSTER_32(~0)) {
1731                 hint_clu = test_alloc_bitmap(sb, p_fs->clu_srch_ptr-2);
1732                 if (hint_clu == CLUSTER_32(~0))
1733                         return 0;
1734         } else if (hint_clu >= p_fs->num_clusters) {
1735                 hint_clu = 2;
1736                 p_chain->flags = 0x01;
1737         }
1738
1739         sb->s_dirt = 1;
1740
1741         p_chain->dir = CLUSTER_32(~0);
1742
1743         while ((new_clu = test_alloc_bitmap(sb, hint_clu-2)) != CLUSTER_32(~0)) {
1744                 if (new_clu != hint_clu) {
1745                         if (p_chain->flags == 0x03) {
1746                                 exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters);
1747                                 p_chain->flags = 0x01;
1748                         }
1749                 }
1750
1751                 if (set_alloc_bitmap(sb, new_clu-2) != FFS_SUCCESS)
1752                         return 0;
1753
1754                 num_clusters++;
1755
1756                 if (p_chain->flags == 0x01)
1757                         FAT_write(sb, new_clu, CLUSTER_32(~0));
1758
1759                 if (p_chain->dir == CLUSTER_32(~0)) {
1760                         p_chain->dir = new_clu;
1761                 } else {
1762                         if (p_chain->flags == 0x01)
1763                                 FAT_write(sb, last_clu, new_clu);
1764                 }
1765                 last_clu = new_clu;
1766
1767                 if ((--num_alloc) == 0) {
1768                         p_fs->clu_srch_ptr = hint_clu;
1769                         if (p_fs->used_clusters != (UINT32) ~0)
1770                                 p_fs->used_clusters += num_clusters;
1771
1772                         p_chain->size += num_clusters;
1773                         return(num_clusters);
1774                 }
1775
1776                 hint_clu = new_clu + 1;
1777                 if (hint_clu >= p_fs->num_clusters) {
1778                         hint_clu = 2;
1779
1780                         if (p_chain->flags == 0x03) {
1781                                 exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters);
1782                                 p_chain->flags = 0x01;
1783                         }
1784                 }
1785         }
1786
1787         p_fs->clu_srch_ptr = hint_clu;
1788         if (p_fs->used_clusters != (UINT32) ~0)
1789                 p_fs->used_clusters += num_clusters;
1790
1791         p_chain->size += num_clusters;
1792         return(num_clusters);
1793
1794
1795 void fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse)
1796 {
1797         INT32 num_clusters = 0;
1798         UINT32 clu, prev;
1799         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1800 #if 1
1801         INT32 i;
1802         UINT32 sector;
1803 #endif
1804
1805         if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
1806                 return;
1807
1808         sb->s_dirt = 1;
1809
1810         clu = p_chain->dir;
1811
1812         do {
1813                 if (p_fs->dev_ejected)
1814                         break;
1815 #if 1
1816                 if (do_relse) {
1817                         sector = START_SECTOR(clu);
1818                         for (i = 0; i < p_fs->sectors_per_clu; i++) {
1819                                 buf_release(sb, sector+i);
1820                         }
1821                 }
1822 #endif
1823                 prev = clu;
1824                 if (FAT_read(sb, clu, &clu) == -1)
1825                         break;
1826
1827                 FAT_write(sb, prev, CLUSTER_32(0));
1828                 num_clusters++;
1829
1830         } while (clu != CLUSTER_32(~0));
1831
1832         if (p_fs->used_clusters != (UINT32) ~0)
1833                 p_fs->used_clusters -= num_clusters;
1834 }
1835
1836 void exfat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse)
1837 {
1838         INT32 num_clusters = 0;
1839         UINT32 clu;
1840         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1841 #if 1
1842         INT32 i;
1843         UINT32 sector;
1844 #endif
1845
1846         if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
1847                 return;
1848
1849         sb->s_dirt = 1;
1850
1851         clu = p_chain->dir;
1852
1853         if (p_chain->flags == 0x03) {
1854                 do {
1855 #if 1
1856                         if (do_relse) {
1857                                 sector = START_SECTOR(clu);
1858                                 for (i = 0; i < p_fs->sectors_per_clu; i++) {
1859                                         buf_release(sb, sector+i);
1860                                 }
1861                         }
1862 #endif
1863                         if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS)
1864                                 break;
1865                         clu++;
1866
1867                         num_clusters++;
1868                 } while (num_clusters < p_chain->size);
1869         } else {
1870                 do {
1871                         if (p_fs->dev_ejected)
1872                                 break;
1873 #if 1
1874                         if (do_relse) {
1875                                 sector = START_SECTOR(clu);
1876                                 for (i = 0; i < p_fs->sectors_per_clu; i++) {
1877                                         buf_release(sb, sector+i);
1878                                 }
1879                         }
1880 #endif
1881                         if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS)
1882                                 break;
1883
1884                         if (FAT_read(sb, clu, &clu) == -1)
1885                                 break;
1886                         num_clusters++;
1887                 } while (clu != CLUSTER_32(~0));
1888         }
1889
1890         if (p_fs->used_clusters != (UINT32) ~0)
1891                 p_fs->used_clusters -= num_clusters;
1892 }
1893
1894 UINT32 find_last_cluster(struct super_block *sb, CHAIN_T *p_chain)
1895 {
1896         UINT32 clu, next;
1897         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1898
1899         clu = p_chain->dir;
1900
1901         if (p_chain->flags == 0x03) {
1902                 clu += p_chain->size - 1;
1903         } else {
1904                 while((FAT_read(sb, clu, &next) == 0) && (next != CLUSTER_32(~0))) {
1905                         if (p_fs->dev_ejected)
1906                                 break;
1907                         clu = next;
1908                 }
1909         }
1910
1911         return(clu);
1912 }
1913
1914 INT32 count_num_clusters(struct super_block *sb, CHAIN_T *p_chain)
1915 {
1916         INT32 i, count = 0;
1917         UINT32 clu;
1918         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1919
1920         if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0)))
1921                 return 0;
1922
1923         clu = p_chain->dir;
1924
1925         if (p_chain->flags == 0x03) {
1926                 count = p_chain->size;
1927         } else {
1928                 for (i = 2; i < p_fs->num_clusters; i++) {
1929                         count++;
1930                         if (FAT_read(sb, clu, &clu) != 0)
1931                                 return 0;
1932                         if (clu == CLUSTER_32(~0))
1933                                 break;
1934                 }
1935         }
1936
1937         return(count);
1938 }
1939
1940 INT32 fat_count_used_clusters(struct super_block *sb)
1941 {
1942         INT32 i, count = 0;
1943         UINT32 clu;
1944         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1945
1946         for (i = 2; i < p_fs->num_clusters; i++) {
1947                 if (FAT_read(sb, i, &clu) != 0)
1948                         break;
1949                 if (clu != CLUSTER_32(0))
1950                         count++;
1951         }
1952
1953         return(count);
1954 }
1955
1956 INT32 exfat_count_used_clusters(struct super_block *sb)
1957 {
1958         INT32 i, map_i, map_b, count = 0;
1959         UINT8 k;
1960         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1961         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
1962
1963         map_i = map_b = 0;
1964
1965         for (i = 2; i < p_fs->num_clusters; i += 8) {
1966                 k = *(((UINT8 *) p_fs->vol_amap[map_i]->b_data) + map_b);
1967                 count += used_bit[k];
1968
1969                 if ((++map_b) >= p_bd->sector_size) {
1970                         map_i++;
1971                         map_b = 0;
1972                 }
1973         }
1974
1975         return(count);
1976 }
1977
1978 void exfat_chain_cont_cluster(struct super_block *sb, UINT32 chain, INT32 len)
1979 {
1980         if (len == 0)
1981                 return;
1982
1983         while (len > 1) {
1984                 FAT_write(sb, chain, chain+1);
1985                 chain++;
1986                 len--;
1987         }
1988         FAT_write(sb, chain, CLUSTER_32(~0));
1989 }
1990
1991 INT32 load_alloc_bitmap(struct super_block *sb)
1992 {
1993         INT32 i, j, ret;
1994         UINT32 map_size;
1995         UINT32 type, sector;
1996         CHAIN_T clu;
1997         BMAP_DENTRY_T *ep;
1998         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
1999         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
2000
2001         clu.dir = p_fs->root_dir;
2002         clu.flags = 0x01;
2003
2004         while (clu.dir != CLUSTER_32(~0)) {
2005                 if (p_fs->dev_ejected)
2006                         break;
2007
2008                 for (i = 0; i < p_fs->dentries_per_clu; i++) {
2009                         ep = (BMAP_DENTRY_T *) get_entry_in_dir(sb, &clu, i, NULL);
2010                         if (!ep)
2011                                 return FFS_MEDIAERR;
2012
2013                         type = p_fs->fs_func->get_entry_type((DENTRY_T *) ep);
2014
2015                         if (type == TYPE_UNUSED)
2016                                 break;
2017                         if (type != TYPE_BITMAP)
2018                                 continue;
2019
2020                         if (ep->flags == 0x0) {
2021                                 p_fs->map_clu  = GET32_A(ep->start_clu);
2022                                 map_size = (UINT32) GET64_A(ep->size);
2023
2024                                 p_fs->map_sectors = ((map_size-1) >> p_bd->sector_size_bits) + 1;
2025
2026                                 p_fs->vol_amap = (struct buffer_head **) MALLOC(sizeof(struct buffer_head *) * p_fs->map_sectors);
2027                                 if (p_fs->vol_amap == NULL)
2028                                         return FFS_MEMORYERR;
2029
2030                                 sector = START_SECTOR(p_fs->map_clu);
2031
2032                                 for (j = 0; j < p_fs->map_sectors; j++) {
2033                                         p_fs->vol_amap[j] = NULL;
2034                                         ret = sector_read(sb, sector+j, &(p_fs->vol_amap[j]), 1);
2035                                         if (ret != FFS_SUCCESS) {
2036                                                 i=0;
2037                                                 while (i < j)
2038                                                         brelse(p_fs->vol_amap[i++]);
2039
2040                                                 FREE(p_fs->vol_amap);
2041                                                 p_fs->vol_amap = NULL;
2042                                                 return ret;
2043                                         }
2044                                 }
2045
2046                                 p_fs->pbr_bh = NULL;
2047                                 return FFS_SUCCESS;
2048                         }
2049                 }
2050
2051                 if (FAT_read(sb, clu.dir, &(clu.dir)) != 0)
2052                         return FFS_MEDIAERR;
2053         }
2054
2055         return FFS_FORMATERR;
2056 }
2057
2058 void free_alloc_bitmap(struct super_block *sb)
2059 {
2060         INT32 i;
2061         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2062
2063         brelse(p_fs->pbr_bh);
2064
2065         for (i = 0; i < p_fs->map_sectors; i++) {
2066                 __brelse(p_fs->vol_amap[i]);
2067         }
2068
2069         FREE(p_fs->vol_amap);
2070         p_fs->vol_amap = NULL;
2071 }
2072
2073 INT32 set_alloc_bitmap(struct super_block *sb, UINT32 clu)
2074 {
2075         INT32 i, b;
2076         UINT32 sector;
2077         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2078         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
2079
2080         i = clu >> (p_bd->sector_size_bits + 3);
2081         b = clu & ((p_bd->sector_size << 3) - 1);
2082
2083         sector = START_SECTOR(p_fs->map_clu) + i;
2084
2085         Bitmap_set((UINT8 *) p_fs->vol_amap[i]->b_data, b);
2086
2087         return (sector_write(sb, sector, p_fs->vol_amap[i], 0));
2088 }
2089
2090 INT32 clr_alloc_bitmap(struct super_block *sb, UINT32 clu)
2091 {
2092         INT32 i, b;
2093         UINT32 sector;
2094 #if EXFAT_CONFIG_DISCARD
2095         struct exfat_sb_info *sbi = EXFAT_SB(sb);
2096         struct exfat_mount_options *opts = &sbi->options;
2097         int ret;
2098 #endif
2099         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2100         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
2101
2102         i = clu >> (p_bd->sector_size_bits + 3);
2103         b = clu & ((p_bd->sector_size << 3) - 1);
2104
2105         sector = START_SECTOR(p_fs->map_clu) + i;
2106
2107         Bitmap_clear((UINT8 *) p_fs->vol_amap[i]->b_data, b);
2108
2109         return (sector_write(sb, sector, p_fs->vol_amap[i], 0));
2110
2111 #if EXFAT_CONFIG_DISCARD
2112         if (opts->discard) {
2113 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
2114                 ret = sb_issue_discard(sb, START_SECTOR(clu), (1 << p_fs->sectors_per_clu_bits));
2115 #else
2116                 ret = sb_issue_discard(sb, START_SECTOR(clu), (1 << p_fs->sectors_per_clu_bits), GFP_NOFS, 0);
2117 #endif
2118                 if (ret == EOPNOTSUPP) {
2119                         printk(KERN_WARNING "discard not supported by device, disabling");
2120                         opts->discard = 0;
2121                 }
2122         }
2123 #endif
2124 }
2125
2126 UINT32 test_alloc_bitmap(struct super_block *sb, UINT32 clu)
2127 {
2128         INT32 i, map_i, map_b;
2129         UINT32 clu_base, clu_free;
2130         UINT8 k, clu_mask;
2131         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2132         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
2133
2134         clu_base = (clu & ~(0x7)) + 2;
2135         clu_mask = (1 << (clu - clu_base + 2)) - 1;
2136
2137         map_i = clu >> (p_bd->sector_size_bits + 3);
2138         map_b = (clu >> 3) & p_bd->sector_size_mask;
2139
2140         for (i = 2; i < p_fs->num_clusters; i += 8) {
2141                 k = *(((UINT8 *) p_fs->vol_amap[map_i]->b_data) + map_b);
2142                 if (clu_mask > 0) {
2143                         k |= clu_mask;
2144                         clu_mask = 0;
2145                 }
2146                 if (k < 0xFF) {
2147                         clu_free = clu_base + free_bit[k];
2148                         if (clu_free < p_fs->num_clusters)
2149                                 return(clu_free);
2150                 }
2151                 clu_base += 8;
2152
2153                 if (((++map_b) >= p_bd->sector_size) || (clu_base >= p_fs->num_clusters)) {
2154                         if ((++map_i) >= p_fs->map_sectors) {
2155                                 clu_base = 2;
2156                                 map_i = 0;
2157                         }
2158                         map_b = 0;
2159                 }
2160         }
2161
2162         return(CLUSTER_32(~0));
2163 }
2164
2165 void sync_alloc_bitmap(struct super_block *sb)
2166 {
2167         INT32 i;
2168         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2169
2170         if (p_fs->vol_amap == NULL)
2171                 return;
2172
2173         for (i = 0; i < p_fs->map_sectors; i++) {
2174                 sync_dirty_buffer(p_fs->vol_amap[i]);
2175         }
2176 }
2177
2178 INT32 __load_upcase_table(struct super_block *sb, UINT32 sector, UINT32 num_sectors, UINT32 utbl_checksum)
2179 {
2180         INT32 i, ret = FFS_ERROR;
2181         UINT32 j;
2182         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2183         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
2184         struct buffer_head *tmp_bh = NULL;
2185
2186         UINT8   skip = FALSE;
2187         UINT32  index = 0;
2188         UINT16  uni = 0;
2189         UINT16 **upcase_table;
2190
2191         UINT32 checksum = 0;
2192
2193         upcase_table = p_fs->vol_utbl = (UINT16 **) MALLOC(UTBL_COL_COUNT * sizeof(UINT16 *));
2194         if(upcase_table == NULL)
2195                 return FFS_MEMORYERR;
2196         MEMSET(upcase_table, 0, UTBL_COL_COUNT * sizeof(UINT16 *));
2197
2198         num_sectors += sector;
2199
2200         while(sector < num_sectors) {
2201                 ret = sector_read(sb, sector, &tmp_bh, 1);
2202                 if (ret != FFS_SUCCESS) {
2203                         PRINTK("sector read (0x%X)fail\n", sector);
2204                         goto error;
2205                 }
2206                 sector++;
2207
2208                 for(i = 0; i < p_bd->sector_size && index <= 0xFFFF; i += 2) {
2209                         uni = GET16(((UINT8 *) tmp_bh->b_data)+i);
2210
2211                         checksum = ((checksum & 1) ? 0x80000000 : 0 ) + (checksum >> 1) + *(((UINT8 *) tmp_bh->b_data)+i);
2212                         checksum = ((checksum & 1) ? 0x80000000 : 0 ) + (checksum >> 1) + *(((UINT8 *) tmp_bh->b_data)+(i+1));
2213
2214                         if(skip) {
2215                                 PRINTK("skip from 0x%X ", index);
2216                                 index += uni;
2217                                 PRINTK("to 0x%X (amount of 0x%X)\n", index, uni);
2218                                 skip = FALSE;
2219                         } else if(uni == index)
2220                                 index++;
2221                         else if(uni == 0xFFFF)
2222                                 skip = TRUE;
2223                         else {
2224                                 UINT16 col_index = get_col_index(index);
2225
2226                                 if(upcase_table[col_index]== NULL) {
2227                                         PRINTK("alloc = 0x%X\n", col_index);
2228                                         upcase_table[col_index] = (UINT16 *) MALLOC(UTBL_ROW_COUNT * sizeof(UINT16));
2229                                         if(upcase_table[col_index] == NULL) {
2230                                                 ret = FFS_MEMORYERR;
2231                                                 goto error;
2232                                         }
2233
2234                                         for(j = 0 ; j < UTBL_ROW_COUNT  ; j++)
2235                                                 upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j;
2236                                 }
2237
2238                                 upcase_table[col_index][get_row_index(index)] = uni;
2239                                 index++;
2240                         }
2241                 }
2242         }
2243         if(index >= 0xFFFF && utbl_checksum == checksum) {
2244                 if(tmp_bh)
2245                         brelse(tmp_bh);
2246                 return FFS_SUCCESS;
2247         }
2248         ret = FFS_ERROR;
2249 error:
2250         if(tmp_bh)
2251                 brelse(tmp_bh);
2252         free_upcase_table(sb);
2253         return ret;
2254 }
2255
2256 INT32 __load_default_upcase_table(struct super_block *sb)
2257 {
2258         INT32 i, ret = FFS_ERROR;
2259         UINT32 j;
2260         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2261
2262         UINT8   skip = FALSE;
2263         UINT32  index = 0;
2264         UINT16  uni = 0;
2265         UINT16 **upcase_table;
2266
2267         upcase_table = p_fs->vol_utbl = (UINT16 **) MALLOC(UTBL_COL_COUNT * sizeof(UINT16 *));
2268         if(upcase_table == NULL)
2269                 return FFS_MEMORYERR;
2270         MEMSET(upcase_table, 0, UTBL_COL_COUNT * sizeof(UINT16 *));
2271
2272         for(i = 0; index <= 0xFFFF && i < NUM_UPCASE*2; i += 2) {
2273                 uni = GET16(uni_upcase + i);
2274                 if(skip) {
2275                         PRINTK("skip from 0x%X ", index);
2276                         index += uni;
2277                         PRINTK("to 0x%X (amount of 0x%X)\n", index, uni);
2278                         skip = FALSE;
2279                 } else if(uni == index)
2280                         index++;
2281                 else if(uni == 0xFFFF)
2282                         skip = TRUE;
2283                 else {
2284                         UINT16 col_index = get_col_index(index);
2285
2286                         if(upcase_table[col_index]== NULL) {
2287                                 PRINTK("alloc = 0x%X\n", col_index);
2288                                 upcase_table[col_index] = (UINT16 *) MALLOC(UTBL_ROW_COUNT * sizeof(UINT16));
2289                                 if(upcase_table[col_index] == NULL) {
2290                                         ret = FFS_MEMORYERR;
2291                                         goto error;
2292                                 }
2293
2294                                 for(j = 0 ; j < UTBL_ROW_COUNT  ; j++)
2295                                         upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j;
2296                         }
2297
2298                         upcase_table[col_index][get_row_index(index)] = uni;
2299                         index ++;
2300                 }
2301         }
2302
2303         if(index >= 0xFFFF)
2304                 return FFS_SUCCESS;
2305
2306 error:
2307         free_upcase_table(sb);
2308         return ret;
2309 }
2310
2311 INT32 load_upcase_table(struct super_block *sb)
2312 {
2313         INT32 i;
2314         UINT32 tbl_clu, tbl_size;
2315         UINT32 type, sector, num_sectors;
2316         CHAIN_T clu;
2317         CASE_DENTRY_T *ep;
2318         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2319         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
2320
2321         clu.dir = p_fs->root_dir;
2322         clu.flags = 0x01;
2323
2324         if (p_fs->dev_ejected)
2325                 return FFS_MEDIAERR;
2326
2327         while (clu.dir != CLUSTER_32(~0)) {
2328                 for (i = 0; i < p_fs->dentries_per_clu; i++) {
2329                         ep = (CASE_DENTRY_T *) get_entry_in_dir(sb, &clu, i, NULL);
2330                         if (!ep)
2331                                 return FFS_MEDIAERR;
2332
2333                         type = p_fs->fs_func->get_entry_type((DENTRY_T *) ep);
2334
2335                         if (type == TYPE_UNUSED)
2336                                 break;
2337                         if (type != TYPE_UPCASE)
2338                                 continue;
2339
2340                         tbl_clu  = GET32_A(ep->start_clu);
2341                         tbl_size = (UINT32) GET64_A(ep->size);
2342
2343                         sector = START_SECTOR(tbl_clu);
2344                         num_sectors = ((tbl_size-1) >> p_bd->sector_size_bits) + 1;
2345                         if(__load_upcase_table(sb, sector, num_sectors, GET32_A(ep->checksum)) != FFS_SUCCESS)
2346                                 break;
2347                         else
2348                                 return FFS_SUCCESS;
2349                 }
2350                 if (FAT_read(sb, clu.dir, &(clu.dir)) != 0)
2351                         return FFS_MEDIAERR;
2352         }
2353         return __load_default_upcase_table(sb);
2354 }
2355
2356 void free_upcase_table(struct super_block *sb)
2357 {
2358         UINT32 i;
2359         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2360         UINT16 **upcase_table;
2361
2362         upcase_table = p_fs->vol_utbl;
2363         for(i = 0 ; i < UTBL_COL_COUNT ; i ++)
2364                 FREE(upcase_table[i]);
2365
2366         FREE(p_fs->vol_utbl);
2367
2368         p_fs->vol_utbl = NULL;
2369 }
2370
2371 UINT32 fat_get_entry_type(DENTRY_T *p_entry)
2372 {
2373         DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2374
2375         if (*(ep->name) == 0x0)
2376                 return TYPE_UNUSED;
2377
2378         else if (*(ep->name) == 0xE5)
2379                 return TYPE_DELETED;
2380
2381         else if (ep->attr == ATTR_EXTEND)
2382                 return TYPE_EXTEND;
2383
2384         else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_VOLUME)
2385                 return TYPE_VOLUME;
2386
2387         else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_SUBDIR)
2388                 return TYPE_DIR;
2389
2390         return TYPE_FILE;
2391 }
2392
2393 UINT32 exfat_get_entry_type(DENTRY_T *p_entry)
2394 {
2395         FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
2396
2397         if (ep->type == 0x0) {
2398                 return TYPE_UNUSED;
2399         } else if (ep->type < 0x80) {
2400                 return TYPE_DELETED;
2401         } else if (ep->type == 0x80) {
2402                 return TYPE_INVALID;
2403         } else if (ep->type < 0xA0) {
2404                 if (ep->type == 0x81) {
2405                         return TYPE_BITMAP;
2406                 } else if (ep->type == 0x82) {
2407                         return TYPE_UPCASE;
2408                 } else if (ep->type == 0x83) {
2409                         return TYPE_VOLUME;
2410                 } else if (ep->type == 0x85) {
2411                         if (GET16_A(ep->attr) & ATTR_SUBDIR)
2412                                 return TYPE_DIR;
2413                         else
2414                                 return TYPE_FILE;
2415                 }
2416                 return TYPE_CRITICAL_PRI;
2417         } else if (ep->type < 0xC0) {
2418                 if (ep->type == 0xA0) {
2419                         return TYPE_GUID;
2420                 } else if (ep->type == 0xA1) {
2421                         return TYPE_PADDING;
2422                 } else if (ep->type == 0xA2) {
2423                         return TYPE_ACLTAB;
2424                 }
2425                 return TYPE_BENIGN_PRI;
2426         } else if (ep->type < 0xE0) {
2427                 if (ep->type == 0xC0) {
2428                         return TYPE_STREAM;
2429                 } else if (ep->type == 0xC1) {
2430                         return TYPE_EXTEND;
2431                 } else if (ep->type == 0xC2) {
2432                         return TYPE_ACL;
2433                 }
2434                 return TYPE_CRITICAL_SEC;
2435         }
2436
2437         return TYPE_BENIGN_SEC;
2438 }
2439
2440 void fat_set_entry_type(DENTRY_T *p_entry, UINT32 type)
2441 {
2442         DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2443
2444         if (type == TYPE_UNUSED)
2445                 *(ep->name) = 0x0;
2446
2447         else if (type == TYPE_DELETED)
2448                 *(ep->name) = 0xE5;
2449
2450         else if (type == TYPE_EXTEND)
2451                 ep->attr = ATTR_EXTEND;
2452
2453         else if (type == TYPE_DIR)
2454                 ep->attr = ATTR_SUBDIR;
2455
2456         else if (type == TYPE_FILE)
2457                 ep->attr = ATTR_ARCHIVE;
2458
2459         else if (type == TYPE_SYMLINK)
2460                 ep->attr = ATTR_ARCHIVE | ATTR_SYMLINK;
2461 }
2462
2463 void exfat_set_entry_type(DENTRY_T *p_entry, UINT32 type)
2464 {
2465         FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
2466
2467         if (type == TYPE_UNUSED) {
2468                 ep->type = 0x0;
2469         } else if (type == TYPE_DELETED) {
2470                 ep->type &= ~0x80;
2471         } else if (type == TYPE_STREAM) {
2472                 ep->type = 0xC0;
2473         } else if (type == TYPE_EXTEND) {
2474                 ep->type = 0xC1;
2475         } else if (type == TYPE_BITMAP) {
2476                 ep->type = 0x81;
2477         } else if (type == TYPE_UPCASE) {
2478                 ep->type = 0x82;
2479         } else if (type == TYPE_VOLUME) {
2480                 ep->type = 0x83;
2481         } else if (type == TYPE_DIR) {
2482                 ep->type = 0x85;
2483                 SET16_A(ep->attr, ATTR_SUBDIR);
2484         } else if (type == TYPE_FILE) {
2485                 ep->type = 0x85;
2486                 SET16_A(ep->attr, ATTR_ARCHIVE);
2487         } else if (type == TYPE_SYMLINK) {
2488                 ep->type = 0x85;
2489                 SET16_A(ep->attr, ATTR_ARCHIVE | ATTR_SYMLINK);
2490         }
2491 }
2492
2493 UINT32 fat_get_entry_attr(DENTRY_T *p_entry)
2494 {
2495         DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2496         return((UINT32) ep->attr);
2497 }
2498
2499 UINT32 exfat_get_entry_attr(DENTRY_T *p_entry)
2500 {
2501         FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
2502         return((UINT32) GET16_A(ep->attr));
2503 }
2504
2505 void fat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr)
2506 {
2507         DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2508         ep->attr = (UINT8) attr;
2509 }
2510
2511 void exfat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr)
2512 {
2513         FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
2514         SET16_A(ep->attr, (UINT16) attr);
2515 }
2516
2517 UINT8 fat_get_entry_flag(DENTRY_T *p_entry)
2518 {
2519         return 0x01;
2520 }
2521
2522 UINT8 exfat_get_entry_flag(DENTRY_T *p_entry)
2523 {
2524         STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
2525         return(ep->flags);
2526 }
2527
2528 void fat_set_entry_flag(DENTRY_T *p_entry, UINT8 flags)
2529 {
2530 }
2531
2532 void exfat_set_entry_flag(DENTRY_T *p_entry, UINT8 flags)
2533 {
2534         STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
2535         ep->flags = flags;
2536 }
2537
2538 UINT32 fat_get_entry_clu0(DENTRY_T *p_entry)
2539 {
2540         DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2541         return((GET32_A(ep->start_clu_hi) << 16) | GET16_A(ep->start_clu_lo));
2542 }
2543
2544 UINT32 exfat_get_entry_clu0(DENTRY_T *p_entry)
2545 {
2546         STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
2547         return(GET32_A(ep->start_clu));
2548 }
2549
2550 void fat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu)
2551 {
2552         DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2553         SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu));
2554         SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16));
2555 }
2556
2557 void exfat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu)
2558 {
2559         STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
2560         SET32_A(ep->start_clu, start_clu);
2561 }
2562
2563 UINT64 fat_get_entry_size(DENTRY_T *p_entry)
2564 {
2565         DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2566         return((UINT64) GET32_A(ep->size));
2567 }
2568
2569 UINT64 exfat_get_entry_size(DENTRY_T *p_entry)
2570 {
2571         STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
2572         return(GET64_A(ep->valid_size));
2573 }
2574
2575 void fat_set_entry_size(DENTRY_T *p_entry, UINT64 size)
2576 {
2577         DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2578         SET32_A(ep->size, (UINT32) size);
2579 }
2580
2581 void exfat_set_entry_size(DENTRY_T *p_entry, UINT64 size)
2582 {
2583         STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry;
2584         SET64_A(ep->valid_size, size);
2585         SET64_A(ep->size, size);
2586 }
2587
2588 void fat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode)
2589 {
2590         UINT16 t = 0x00, d = 0x21;
2591         DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2592
2593         switch (mode) {
2594         case TM_CREATE:
2595                 t = GET16_A(ep->create_time);
2596                 d = GET16_A(ep->create_date);
2597                 break;
2598         case TM_MODIFY:
2599                 t = GET16_A(ep->modify_time);
2600                 d = GET16_A(ep->modify_date);
2601                 break;
2602         }
2603
2604         tp->sec  = (t & 0x001F) << 1;
2605         tp->min  = (t >> 5) & 0x003F;
2606         tp->hour = (t >> 11);
2607         tp->day  = (d & 0x001F);
2608         tp->mon  = (d >> 5) & 0x000F;
2609         tp->year = (d >> 9);
2610 }
2611
2612 void exfat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode)
2613 {
2614         UINT16 t = 0x00, d = 0x21;
2615         FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
2616
2617         switch (mode) {
2618         case TM_CREATE:
2619                 t = GET16_A(ep->create_time);
2620                 d = GET16_A(ep->create_date);
2621                 break;
2622         case TM_MODIFY:
2623                 t = GET16_A(ep->modify_time);
2624                 d = GET16_A(ep->modify_date);
2625                 break;
2626         case TM_ACCESS:
2627                 t = GET16_A(ep->access_time);
2628                 d = GET16_A(ep->access_date);
2629                 break;
2630         }
2631
2632         tp->sec  = (t & 0x001F) << 1;
2633         tp->min  = (t >> 5) & 0x003F;
2634         tp->hour = (t >> 11);
2635         tp->day  = (d & 0x001F);
2636         tp->mon  = (d >> 5) & 0x000F;
2637         tp->year = (d >> 9);
2638
2639
2640 void fat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode)
2641 {
2642         UINT16 t, d;
2643         DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry;
2644
2645         t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1);
2646         d = (tp->year <<  9) | (tp->mon << 5) |  tp->day;
2647
2648         switch (mode) {
2649         case TM_CREATE:
2650                 SET16_A(ep->create_time, t);
2651                 SET16_A(ep->create_date, d);
2652                 break;
2653         case TM_MODIFY:
2654                 SET16_A(ep->modify_time, t);
2655                 SET16_A(ep->modify_date, d);
2656                 break;
2657         }
2658 }
2659
2660 void exfat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode)
2661 {
2662         UINT16 t, d;
2663         FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry;
2664
2665         t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1);
2666         d = (tp->year <<  9) | (tp->mon << 5) |  tp->day;
2667
2668         switch (mode) {
2669         case TM_CREATE:
2670                 SET16_A(ep->create_time, t);
2671                 SET16_A(ep->create_date, d);
2672                 break;
2673         case TM_MODIFY:
2674                 SET16_A(ep->modify_time, t);
2675                 SET16_A(ep->modify_date, d);
2676                 break;
2677         case TM_ACCESS:
2678                 SET16_A(ep->access_time, t);
2679                 SET16_A(ep->access_date, d);
2680                 break;
2681         }
2682 }
2683
2684 INT32 fat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type,
2685                                                  UINT32 start_clu, UINT64 size)
2686 {
2687         UINT32 sector;
2688         DOS_DENTRY_T *dos_ep;
2689
2690         dos_ep = (DOS_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, &sector);
2691         if (!dos_ep)
2692                 return FFS_MEDIAERR;
2693
2694         init_dos_entry(dos_ep, type, start_clu);
2695         buf_modify(sb, sector);
2696
2697         return FFS_SUCCESS;
2698 }
2699
2700 INT32 exfat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type,
2701                                                    UINT32 start_clu, UINT64 size)
2702 {
2703         UINT32 sector;
2704         UINT8 flags;
2705         FILE_DENTRY_T *file_ep;
2706         STRM_DENTRY_T *strm_ep;
2707
2708         flags = (type == TYPE_FILE) ? 0x01 : 0x03;
2709
2710         file_ep = (FILE_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, &sector);
2711         if (!file_ep)
2712                 return FFS_MEDIAERR;
2713
2714         strm_ep = (STRM_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry+1, &sector);
2715         if (!strm_ep)
2716                 return FFS_MEDIAERR;
2717
2718         init_file_entry(file_ep, type);
2719         buf_modify(sb, sector);
2720
2721         init_strm_entry(strm_ep, flags, start_clu, size);
2722         buf_modify(sb, sector);
2723
2724         return FFS_SUCCESS;
2725 }
2726
2727 INT32 fat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries,
2728                                                  UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname)
2729 {
2730         INT32 i;
2731         UINT32 sector;
2732         UINT8 chksum;
2733         UINT16 *uniname = p_uniname->name;
2734         DOS_DENTRY_T *dos_ep;
2735         EXT_DENTRY_T *ext_ep;
2736
2737         dos_ep = (DOS_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, &sector);
2738         if (!dos_ep)
2739                 return FFS_MEDIAERR;
2740
2741         dos_ep->lcase = p_dosname->name_case;
2742         MEMCPY(dos_ep->name, p_dosname->name, DOS_NAME_LENGTH);
2743         buf_modify(sb, sector);
2744
2745         if ((--num_entries) > 0) {
2746                 chksum = calc_checksum_1byte((void *) dos_ep->name, DOS_NAME_LENGTH, 0);
2747
2748                 for (i = 1; i < num_entries; i++) {
2749                         ext_ep = (EXT_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry-i, &sector);
2750                         if (!ext_ep)
2751                                 return FFS_MEDIAERR;
2752
2753                         init_ext_entry(ext_ep, i, chksum, uniname);
2754                         buf_modify(sb, sector);
2755                         uniname += 13;
2756                 }
2757
2758                 ext_ep = (EXT_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry-i, &sector);
2759                 if (!ext_ep)
2760                         return FFS_MEDIAERR;
2761
2762                 init_ext_entry(ext_ep, i+0x40, chksum, uniname);
2763                 buf_modify(sb, sector);
2764         }
2765
2766         return FFS_SUCCESS;
2767
2768
2769 INT32 exfat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries,
2770                                                    UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname)
2771 {
2772         INT32 i;
2773         UINT32 sector;
2774         UINT16 *uniname = p_uniname->name;
2775         FILE_DENTRY_T *file_ep;
2776         STRM_DENTRY_T *strm_ep;
2777         NAME_DENTRY_T *name_ep;
2778
2779         file_ep = (FILE_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, &sector);
2780         if (!file_ep)
2781                 return FFS_MEDIAERR;
2782
2783         file_ep->num_ext = (UINT8)(num_entries - 1);
2784         buf_modify(sb, sector);
2785
2786         strm_ep = (STRM_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry+1, &sector);
2787         if (!strm_ep)
2788                 return FFS_MEDIAERR;
2789
2790         strm_ep->name_len = p_uniname->name_len;
2791         SET16_A(strm_ep->name_hash, p_uniname->name_hash);
2792         buf_modify(sb, sector);
2793
2794         for (i = 2; i < num_entries; i++) {
2795                 name_ep = (NAME_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry+i, &sector);
2796                 if (!name_ep)
2797                         return FFS_MEDIAERR;
2798
2799                 init_name_entry(name_ep, uniname);
2800                 buf_modify(sb, sector);
2801                 uniname += 15;
2802         }
2803
2804         update_dir_checksum(sb, p_dir, entry);
2805
2806         return FFS_SUCCESS;
2807
2808
2809 void init_dos_entry(DOS_DENTRY_T *ep, UINT32 type, UINT32 start_clu)
2810 {
2811         TIMESTAMP_T tm, *tp;
2812
2813         fat_set_entry_type((DENTRY_T *) ep, type);
2814         SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu));
2815         SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16));
2816         SET32_A(ep->size, 0);
2817
2818         tp = tm_current(&tm);
2819         fat_set_entry_time((DENTRY_T *) ep, tp, TM_CREATE);
2820         fat_set_entry_time((DENTRY_T *) ep, tp, TM_MODIFY);
2821         SET16_A(ep->access_date, 0);
2822         ep->create_time_ms = 0;
2823 }
2824
2825 void init_ext_entry(EXT_DENTRY_T *ep, INT32 order, UINT8 chksum, UINT16 *uniname)
2826 {
2827         INT32 i;
2828         UINT8 end = FALSE;
2829
2830         fat_set_entry_type((DENTRY_T *) ep, TYPE_EXTEND);
2831         ep->order = (UINT8) order;
2832         ep->sysid = 0;
2833         ep->checksum = chksum;
2834         SET16_A(ep->start_clu, 0);
2835
2836         for (i = 0; i < 10; i += 2) {
2837                 if (!end) {
2838                         SET16(ep->unicode_0_4+i, *uniname);
2839                         if (*uniname == 0x0)
2840                                 end = TRUE;
2841                         else
2842                                 uniname++;
2843                 } else {
2844                         SET16(ep->unicode_0_4+i, 0xFFFF);
2845                 }
2846         }
2847
2848         for (i = 0; i < 12; i += 2) {
2849                 if (!end) {
2850                         SET16_A(ep->unicode_5_10+i, *uniname);
2851                         if (*uniname == 0x0)
2852                                 end = TRUE;
2853                         else
2854                                 uniname++;
2855                 } else {
2856                         SET16_A(ep->unicode_5_10+i, 0xFFFF);
2857                 }
2858         }
2859
2860         for (i = 0; i < 4; i += 2) {
2861                 if (!end) {
2862                         SET16_A(ep->unicode_11_12+i, *uniname);
2863                         if (*uniname == 0x0)
2864                                 end = TRUE;
2865                         else
2866                                 uniname++;
2867                 } else {
2868                         SET16_A(ep->unicode_11_12+i, 0xFFFF);
2869                 }
2870         }
2871 }
2872
2873 void init_file_entry(FILE_DENTRY_T *ep, UINT32 type)
2874 {
2875         TIMESTAMP_T tm, *tp;
2876
2877         exfat_set_entry_type((DENTRY_T *) ep, type);
2878
2879         tp = tm_current(&tm);
2880         exfat_set_entry_time((DENTRY_T *) ep, tp, TM_CREATE);
2881         exfat_set_entry_time((DENTRY_T *) ep, tp, TM_MODIFY);
2882         exfat_set_entry_time((DENTRY_T *) ep, tp, TM_ACCESS);
2883         ep->create_time_ms = 0;
2884         ep->modify_time_ms = 0;
2885         ep->access_time_ms = 0;
2886 }
2887
2888 void init_strm_entry(STRM_DENTRY_T *ep, UINT8 flags, UINT32 start_clu, UINT64 size)
2889 {
2890         exfat_set_entry_type((DENTRY_T *) ep, TYPE_STREAM);
2891         ep->flags = flags;
2892         SET32_A(ep->start_clu, start_clu);
2893         SET64_A(ep->valid_size, size);
2894         SET64_A(ep->size, size);
2895 }
2896
2897 void init_name_entry(NAME_DENTRY_T *ep, UINT16 *uniname)
2898 {
2899         INT32 i;
2900
2901         exfat_set_entry_type((DENTRY_T *) ep, TYPE_EXTEND);
2902         ep->flags = 0x0;
2903
2904         for (i = 0; i < 30; i++, i++) {
2905                 SET16_A(ep->unicode_0_14+i, *uniname);
2906                 if (*uniname == 0x0)
2907                         break;
2908                 uniname++;
2909         }
2910 }
2911
2912 void fat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 order, INT32 num_entries)
2913 {
2914         INT32 i;
2915         UINT32 sector;
2916         DENTRY_T *ep;
2917         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2918
2919         for (i = num_entries-1; i >= order; i--) {
2920                 ep = get_entry_in_dir(sb, p_dir, entry-i, &sector);
2921                 if (!ep)
2922                         return;
2923
2924                 p_fs->fs_func->set_entry_type(ep, TYPE_DELETED);
2925                 buf_modify(sb, sector);
2926         }
2927 }
2928
2929 void exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 order, INT32 num_entries)
2930 {
2931         INT32 i;
2932         UINT32 sector;
2933         DENTRY_T *ep;
2934         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
2935
2936         for (i = order; i < num_entries; i++) {
2937                 ep = get_entry_in_dir(sb, p_dir, entry+i, &sector);
2938                 if (!ep)
2939                         return;
2940
2941                 p_fs->fs_func->set_entry_type(ep, TYPE_DELETED);
2942                 buf_modify(sb, sector);
2943         }
2944 }
2945
2946 void update_dir_checksum(struct super_block *sb, CHAIN_T *p_dir, INT32 entry)
2947 {
2948         INT32 i, num_entries;
2949         UINT32 sector;
2950         UINT16 chksum;
2951         FILE_DENTRY_T *file_ep;
2952         DENTRY_T *ep;
2953
2954         file_ep = (FILE_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, &sector);
2955         if (!file_ep)
2956                 return;
2957
2958         buf_lock(sb, sector);
2959
2960         num_entries = (INT32) file_ep->num_ext + 1;
2961         chksum = calc_checksum_2byte((void *) file_ep, DENTRY_SIZE, 0, CS_DIR_ENTRY);
2962
2963         for (i = 1; i < num_entries; i++) {
2964                 ep = get_entry_in_dir(sb, p_dir, entry+i, NULL);
2965                 if (!ep) {
2966                         buf_unlock(sb, sector);
2967                         return;
2968                 }
2969
2970                 chksum = calc_checksum_2byte((void *) ep, DENTRY_SIZE, chksum, CS_DEFAULT);
2971         }
2972
2973         SET16_A(file_ep->checksum, chksum);
2974         buf_modify(sb, sector);
2975         buf_unlock(sb, sector);
2976 }
2977
2978 void update_dir_checksum_with_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es)
2979 {
2980         DENTRY_T *ep;
2981         UINT16 chksum = 0;
2982         INT32 chksum_type = CS_DIR_ENTRY, i;
2983
2984         ep = (DENTRY_T *)&(es->__buf);
2985         for (i=0; i < es->num_entries; i++) {
2986                 PRINTK ("update_dir_checksum_with_entry_set ep %p\n", ep);
2987                 chksum = calc_checksum_2byte((void *) ep, DENTRY_SIZE, chksum, chksum_type);
2988                 ep++;
2989                 chksum_type = CS_DEFAULT;
2990         }
2991
2992         ep = (DENTRY_T *)&(es->__buf);
2993         SET16_A(((FILE_DENTRY_T *)ep)->checksum, chksum);
2994         write_whole_entry_set(sb, es);
2995 }
2996
2997 static INT32 _walk_fat_chain (struct super_block *sb, CHAIN_T *p_dir, INT32 byte_offset, UINT32 *clu)
2998 {
2999         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
3000         INT32 clu_offset;
3001         UINT32 cur_clu;
3002
3003         clu_offset = byte_offset >> p_fs->cluster_size_bits;
3004         cur_clu = p_dir->dir;
3005
3006         if (p_dir->flags == 0x03) {
3007                 cur_clu += clu_offset;
3008         } else {
3009                 while (clu_offset > 0) {
3010                         if (FAT_read(sb, cur_clu, &cur_clu) == -1)
3011                                 return FFS_MEDIAERR;
3012                         clu_offset--;
3013                 }
3014         }
3015
3016         if (clu)
3017                 *clu = cur_clu;
3018         return FFS_SUCCESS;
3019 }
3020 INT32 find_location(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 *sector, INT32 *offset)
3021 {
3022         INT32 off, ret;
3023         UINT32 clu=0;
3024         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
3025         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
3026
3027         off = entry << DENTRY_SIZE_BITS;
3028
3029         if (p_dir->dir == CLUSTER_32(0)) {
3030                 *offset = off & p_bd->sector_size_mask;
3031                 *sector = off >> p_bd->sector_size_bits;
3032                 *sector += p_fs->root_start_sector;
3033         } else {
3034                 ret =_walk_fat_chain(sb, p_dir, off, &clu);
3035                 if (ret != FFS_SUCCESS)
3036                         return ret;
3037
3038                 off &= p_fs->cluster_size - 1;   
3039
3040                 *offset = off & p_bd->sector_size_mask; 
3041                 *sector = off >> p_bd->sector_size_bits;
3042                 *sector += START_SECTOR(clu);
3043         }
3044         return FFS_SUCCESS;
3045 }
3046
3047 DENTRY_T *get_entry_with_sector(struct super_block *sb, UINT32 sector, INT32 offset)
3048 {
3049         UINT8 *buf;
3050
3051         buf = buf_getblk(sb, sector);
3052
3053         if (buf == NULL)
3054                 return NULL;
3055
3056         return((DENTRY_T *)(buf + offset));
3057 }
3058
3059 DENTRY_T *get_entry_in_dir(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 *sector)
3060 {
3061         INT32 off;
3062         UINT32 sec;
3063         UINT8 *buf;
3064
3065         if (find_location(sb, p_dir, entry, &sec, &off) != FFS_SUCCESS)
3066                 return NULL;
3067
3068         buf = buf_getblk(sb, sec);
3069
3070         if (buf == NULL)
3071                 return NULL;
3072
3073         if (sector != NULL)
3074                 *sector = sec;
3075         return((DENTRY_T *)(buf + off));
3076 }
3077
3078 #if 1
3079
3080 #define ES_MODE_STARTED                                                         0
3081 #define ES_MODE_GET_FILE_ENTRY                                          1
3082 #define ES_MODE_GET_STRM_ENTRY                                          2
3083 #define ES_MODE_GET_NAME_ENTRY                                          3
3084 #define ES_MODE_GET_CRITICAL_SEC_ENTRY                          4
3085 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)
3086 {
3087         INT32 off, ret, byte_offset;
3088         UINT32 clu=0;
3089         UINT32 sec, entry_type;
3090         FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info);
3091         BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info);
3092         ENTRY_SET_CACHE_T *es = NULL;
3093         DENTRY_T *ep, *pos;
3094         UINT8 *buf;
3095         UINT8 num_entries;
3096         INT32 mode = ES_MODE_STARTED;
3097
3098         PRINTK("get_entry_set_in_dir entered\n");
3099         PRINTK("p_dir dir %u flags %x size %d\n", p_dir->dir, p_dir->flags, p_dir->size);
3100
3101         byte_offset = entry << DENTRY_SIZE_BITS;
3102         ret =_walk_fat_chain(sb, p_dir, byte_offset, &clu);
3103         if (ret != FFS_SUCCESS)
3104                 return NULL;
3105
3106         byte_offset &= p_fs->cluster_size - 1;     
3107
3108         off = byte_offset & p_bd->sector_size_mask; 
3109         sec = byte_offset >> p_bd->sector_size_bits;
3110         sec += START_SECTOR(clu);
3111
3112         buf = buf_getblk(sb, sec);
3113         if (buf == NULL)
3114                 goto err_out;
3115
3116         ep = (DENTRY_T *)(buf + off);
3117         entry_type = p_fs->fs_func->get_entry_type(ep);
3118
3119         if ((entry_type != TYPE_FILE)
3120                 && (entry_type != TYPE_DIR))
3121                 goto err_out;
3122
3123         if (type == ES_ALL_ENTRIES)
3124                 num_entries = ((FILE_DENTRY_T *)ep)->num_ext+1;
3125         else
3126                 num_entries = type;
3127
3128         PRINTK("trying to malloc %x bytes for %d entries\n", offsetof(ENTRY_SET_CACHE_T, __buf) + (num_entries)  * sizeof(DENTRY_T), num_entries);
3129         es = MALLOC(offsetof(ENTRY_SET_CACHE_T, __buf) + (num_entries)  * sizeof(DENTRY_T));
3130         if (es == NULL)
3131                 goto err_out;
3132
3133         es->num_entries = num_entries;
3134         es->sector = sec;
3135         es->offset = off;
3136         es->alloc_flag = p_dir->flags;
3137
3138         pos = (DENTRY_T *) &(es->__buf);
3139
3140         while(num_entries) {
3141
3142                 entry_type = p_fs->fs_func->get_entry_type(ep);
3143                 if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED))
3144                         goto err_out;
3145
3146                 switch(mode) {
3147                 case ES_MODE_STARTED:
3148                         if  ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR))
3149                                 mode = ES_MODE_GET_FILE_ENTRY;
3150                         else
3151                                 goto err_out;
3152                         break;
3153                 case ES_MODE_GET_FILE_ENTRY:
3154                         if (entry_type == TYPE_STREAM)
3155                                 mode = ES_MODE_GET_STRM_ENTRY;
3156                         else
3157                                 goto err_out;
3158                         break;
3159                 case ES_MODE_GET_STRM_ENTRY:
3160                         if (entry_type == TYPE_EXTEND)
3161                                 mode = ES_MODE_GET_NAME_ENTRY;
3162                         else
3163                                 goto err_out;
3164                         break;
3165                 case ES_MODE_GET_NAME_ENTRY:
3166                         if (entry_type == TYPE_EXTEND)
3167                                 break;
3168                         else if (entry_type == TYPE_STREAM)
3169                                 goto err_out;
3170                         else if (entry_type & TYPE_CRITICAL_SEC)
3171                                 mode = ES_MODE_GET_CRITICAL_SEC_ENTRY;
3172                         else
3173                                 goto err_out;
3174                         break;
3175                 case ES_MODE_GET_CRITICAL_SEC_ENTRY:
3176                         if ((entry_type == TYPE_EXTEND) || (entry_type == TYPE_STREAM))
3177       &nbs