11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * linux/fs/fat/misc.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Written 1992,1993 by Werner Almesberger 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fs.h> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/buffer_head.h> 121d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei#include <linux/time.h> 139e975dae2970d22557662761c8505ce9fd165684OGAWA Hirofumi#include "fat.h" 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1685c7859190c4197a7c34066db14c25903c401187Denis Karpov * fat_fs_error reports a file system problem that might indicate fa data 1785c7859190c4197a7c34066db14c25903c401187Denis Karpov * corruption/inconsistency. Depending on 'errors' mount option the 1885c7859190c4197a7c34066db14c25903c401187Denis Karpov * panic() is called, or error message is printed FAT and nothing is done, 1985c7859190c4197a7c34066db14c25903c401187Denis Karpov * or filesystem is remounted read-only (default behavior). 2085c7859190c4197a7c34066db14c25903c401187Denis Karpov * In case the file system is remounted read-only, it can be made writable 2185c7859190c4197a7c34066db14c25903c401187Denis Karpov * again by remounting it. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 232c8a5ffb94bbb4f04aaf8a923e9098fb7a51a75aAlexey Fishervoid __fat_fs_error(struct super_block *sb, int report, const char *fmt, ...) 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 252c8a5ffb94bbb4f04aaf8a923e9098fb7a51a75aAlexey Fisher struct fat_mount_options *opts = &MSDOS_SB(sb)->options; 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds va_list args; 272c8a5ffb94bbb4f04aaf8a923e9098fb7a51a75aAlexey Fisher struct va_format vaf; 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 29aaa04b4875f30659a0eb429e0e5203ae7fb7b18eOGAWA Hirofumi if (report) { 30aaa04b4875f30659a0eb429e0e5203ae7fb7b18eOGAWA Hirofumi va_start(args, fmt); 312c8a5ffb94bbb4f04aaf8a923e9098fb7a51a75aAlexey Fisher vaf.fmt = fmt; 322c8a5ffb94bbb4f04aaf8a923e9098fb7a51a75aAlexey Fisher vaf.va = &args; 33e68e96d2a7b2391cc1f70e207ec9cbe9d092adc9Gu Zheng fat_msg(sb, KERN_ERR, "error, %pV", &vaf); 34aaa04b4875f30659a0eb429e0e5203ae7fb7b18eOGAWA Hirofumi va_end(args); 35aaa04b4875f30659a0eb429e0e5203ae7fb7b18eOGAWA Hirofumi } 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3785c7859190c4197a7c34066db14c25903c401187Denis Karpov if (opts->errors == FAT_ERRORS_PANIC) 382c8a5ffb94bbb4f04aaf8a923e9098fb7a51a75aAlexey Fisher panic("FAT-fs (%s): fs panic from previous error\n", sb->s_id); 392c8a5ffb94bbb4f04aaf8a923e9098fb7a51a75aAlexey Fisher else if (opts->errors == FAT_ERRORS_RO && !(sb->s_flags & MS_RDONLY)) { 402c8a5ffb94bbb4f04aaf8a923e9098fb7a51a75aAlexey Fisher sb->s_flags |= MS_RDONLY; 41e68e96d2a7b2391cc1f70e207ec9cbe9d092adc9Gu Zheng fat_msg(sb, KERN_ERR, "Filesystem has been set read-only"); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 44aaa04b4875f30659a0eb429e0e5203ae7fb7b18eOGAWA HirofumiEXPORT_SYMBOL_GPL(__fat_fs_error); 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4681ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher/** 4781ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher * fat_msg() - print preformated FAT specific messages. Every thing what is 4881ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher * not fat_fs_error() should be fat_msg(). 4981ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher */ 5081ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fishervoid fat_msg(struct super_block *sb, const char *level, const char *fmt, ...) 5181ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher{ 5281ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher struct va_format vaf; 5381ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher va_list args; 5481ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher 5581ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher va_start(args, fmt); 5681ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher vaf.fmt = fmt; 5781ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher vaf.va = &args; 5881ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher printk("%sFAT-fs (%s): %pV\n", level, sb->s_id, &vaf); 5981ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher va_end(args); 6081ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher} 6181ac21d34a91e85b029cd86e2ed5eeae8d7c3cd4Alexey Fisher 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Flushes the number of free clusters on FAT32 */ 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* XXX: Need to write one per FSINFO block. Currently only writes 1 */ 64ed248b290da7297c9b9a3ff180f5eee4db016224OGAWA Hirofumiint fat_clusters_flush(struct super_block *sb) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct msdos_sb_info *sbi = MSDOS_SB(sb); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buffer_head *bh; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fat_boot_fsinfo *fsinfo; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sbi->fat_bits != 32) 71ed248b290da7297c9b9a3ff180f5eee4db016224OGAWA Hirofumi return 0; 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh = sb_bread(sb, sbi->fsinfo_sector); 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (bh == NULL) { 75869f58c0cdba3ae6880ab6113617e62672198773Alexey Fisher fat_msg(sb, KERN_ERR, "bread failed in fat_clusters_flush"); 76ed248b290da7297c9b9a3ff180f5eee4db016224OGAWA Hirofumi return -EIO; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsinfo = (struct fat_boot_fsinfo *)bh->b_data; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Sanity check */ 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!IS_FSINFO(fsinfo)) { 82869f58c0cdba3ae6880ab6113617e62672198773Alexey Fisher fat_msg(sb, KERN_ERR, "Invalid FSINFO signature: " 83869f58c0cdba3ae6880ab6113617e62672198773Alexey Fisher "0x%08x, 0x%08x (sector = %lu)", 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le32_to_cpu(fsinfo->signature1), 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds le32_to_cpu(fsinfo->signature2), 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sbi->fsinfo_sector); 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sbi->free_clusters != -1) 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsinfo->free_clusters = cpu_to_le32(sbi->free_clusters); 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sbi->prev_free != -1) 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fsinfo->next_cluster = cpu_to_le32(sbi->prev_free); 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mark_buffer_dirty(bh); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 95ed248b290da7297c9b9a3ff180f5eee4db016224OGAWA Hirofumi 96ed248b290da7297c9b9a3ff180f5eee4db016224OGAWA Hirofumi return 0; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * fat_chain_add() adds a new cluster to the chain of clusters represented 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * by inode. 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct super_block *sb = inode->i_sb; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct msdos_sb_info *sbi = MSDOS_SB(sb); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret, new_fclus, last; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * We must locate the last cluster of the file to add this new 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * one (new_dclus) to the end of the link list (the FAT). 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last = new_fclus = 0; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (MSDOS_I(inode)->i_start) { 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int fclus, dclus; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_fclus = fclus + 1; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds last = dclus; 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* add new one to the last of the cluster chain */ 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (last) { 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct fat_entry fatent; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fatent_init(&fatent); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = fat_ent_read(inode, &fatent, last); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret >= 0) { 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int wait = inode_needs_sync(inode); 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = fat_ent_write(inode, &fatent, new_dclus, wait); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fatent_brelse(&fatent); 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret < 0) 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 137c39540c6d1add1d0ad843b3d2437311924193359Ravishankar N /* 138c39540c6d1add1d0ad843b3d2437311924193359Ravishankar N * FIXME:Although we can add this cache, fat_cache_add() is 139c39540c6d1add1d0ad843b3d2437311924193359Ravishankar N * assuming to be called after linear search with fat_cache_id. 140c39540c6d1add1d0ad843b3d2437311924193359Ravishankar N */ 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// fat_cache_add(inode, new_fclus, new_dclus); 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MSDOS_I(inode)->i_start = new_dclus; 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MSDOS_I(inode)->i_logstart = new_dclus; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1462f3d675bcd4a84251d6e8eea8096ec8fc795e5d6Jan Kara * Since generic_write_sync() synchronizes regular files later, 1472f3d675bcd4a84251d6e8eea8096ec8fc795e5d6Jan Kara * we sync here only directories. 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode)) { 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = fat_sync_inode(inode); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mark_inode_dirty(inode); 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) { 15785c7859190c4197a7c34066db14c25903c401187Denis Karpov fat_fs_error(sb, "clusters badly computed (%d != %llu)", 158c3302931db090d87e9015c3a7ce5c97a7dd90f78OGAWA Hirofumi new_fclus, 159c3302931db090d87e9015c3a7ce5c97a7dd90f78OGAWA Hirofumi (llu)(inode->i_blocks >> (sbi->cluster_bits - 9))); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fat_cache_inval_inode(inode); 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inode->i_blocks += nr_cluster << (sbi->cluster_bits - 9); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1677decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi/* 1687decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi * The epoch of FAT timestamp is 1980. 1697decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi * : bits : value 1707decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi * date: 0 - 4: day (1 - 31) 1717decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi * date: 5 - 8: month (1 - 12) 1727decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi * date: 9 - 15: year (0 - 127) from 1980 1737decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi * time: 0 - 4: sec (0 - 29) 2sec counts 1747decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi * time: 5 - 10: min (0 - 59) 1757decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi * time: 11 - 15: hour (0 - 23) 1767decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi */ 1777decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi#define SECS_PER_MIN 60 1787decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi#define SECS_PER_HOUR (60 * 60) 1797decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi#define SECS_PER_DAY (SECS_PER_HOUR * 24) 1807decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi/* days between 1.1.70 and 1.1.80 (2 leap days) */ 1817decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi#define DAYS_DELTA (365 * 10 + 2) 1827decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi/* 120 (2100 - 1980) isn't leap year */ 1837decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi#define YEAR_2100 120 1847decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi#define IS_LEAP_YEAR(y) (!((y) & 3) && (y) != YEAR_2100) 1857decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Linear day numbers of the respective 1sts in non-leap years. */ 1877decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumistatic time_t days_in_year[] = { 1887decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ 1897decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1927decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ 1937decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumivoid fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, 1947decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi __le16 __time, __le16 __date, u8 time_cs) 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1967decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi u16 time = le16_to_cpu(__time), date = le16_to_cpu(__date); 1977decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi time_t second, day, leap_day, month, year; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1997decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi year = date >> 9; 2007decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi month = max(1, (date >> 5) & 0xf); 2017decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi day = max(1, date & 0x1f) - 1; 2027decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi 2037decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi leap_day = (year + 3) / 4; 2047decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi if (year > YEAR_2100) /* 2100 isn't leap year */ 2057decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi leap_day--; 2067decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi if (IS_LEAP_YEAR(year) && month > 2) 2077decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi leap_day++; 2087decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi 2097decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi second = (time & 0x1f) << 1; 2107decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi second += ((time >> 5) & 0x3f) * SECS_PER_MIN; 2117decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi second += (time >> 11) * SECS_PER_HOUR; 2127decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi second += (year * 365 + leap_day 2137decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi + days_in_year[month] + day 2147decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi + DAYS_DELTA) * SECS_PER_DAY; 2157decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi 21658156c8fbf43e71dd091848d4dbfd780d04016e6Jan Kara if (!sbi->options.tz_set) 2177decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi second += sys_tz.tz_minuteswest * SECS_PER_MIN; 21858156c8fbf43e71dd091848d4dbfd780d04016e6Jan Kara else 21958156c8fbf43e71dd091848d4dbfd780d04016e6Jan Kara second -= sbi->options.time_offset * SECS_PER_MIN; 2207decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi 2217decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi if (time_cs) { 2227decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi ts->tv_sec = second + (time_cs / 100); 2237decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi ts->tv_nsec = (time_cs % 100) * 10000000; 2247decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi } else { 2257decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi ts->tv_sec = second; 2267decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi ts->tv_nsec = 0; 2277decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi } 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2307decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi/* Convert linear UNIX date to a FAT time/date pair. */ 2317decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumivoid fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts, 2327decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi __le16 *time, __le16 *date, u8 *time_cs) 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2341d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei struct tm tm; 23558156c8fbf43e71dd091848d4dbfd780d04016e6Jan Kara time_to_tm(ts->tv_sec, 23658156c8fbf43e71dd091848d4dbfd780d04016e6Jan Kara (sbi->options.tz_set ? sbi->options.time_offset : 23758156c8fbf43e71dd091848d4dbfd780d04016e6Jan Kara -sys_tz.tz_minuteswest) * SECS_PER_MIN, &tm); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2391d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei /* FAT can only support year between 1980 to 2107 */ 2401d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei if (tm.tm_year < 1980 - 1900) { 2417decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi *time = 0; 2427decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi *date = cpu_to_le16((0 << 9) | (1 << 5) | 1); 2437decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi if (time_cs) 2447decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi *time_cs = 0; 2457decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi return; 2467decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi } 2471d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei if (tm.tm_year > 2107 - 1900) { 2487decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi *time = cpu_to_le16((23 << 11) | (59 << 5) | 29); 2497decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi *date = cpu_to_le16((127 << 9) | (12 << 5) | 31); 2507decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi if (time_cs) 2517decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi *time_cs = 199; 2527decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi return; 2537decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi } 2547decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi 2551d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei /* from 1900 -> from 1980 */ 2561d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei tm.tm_year -= 80; 2571d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei /* 0~11 -> 1~12 */ 2581d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei tm.tm_mon++; 2591d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei /* 0~59 -> 0~29(2sec counts) */ 2601d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei tm.tm_sec >>= 1; 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2621d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei *time = cpu_to_le16(tm.tm_hour << 11 | tm.tm_min << 5 | tm.tm_sec); 2631d81a181e07cec584d1ab142eb921addc81d9b73Zhaolei *date = cpu_to_le16(tm.tm_year << 9 | tm.tm_mon << 5 | tm.tm_mday); 2647decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi if (time_cs) 2657decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi *time_cs = (ts->tv_sec & 1) * 100 + ts->tv_nsec / 10000000; 2667decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA Hirofumi} 2677decd1cb0305b97243f283fa7f4baf5fe613edebOGAWA HirofumiEXPORT_SYMBOL_GPL(fat_time_unix2fat); 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2715b00226d4d3aa7969d84e16f857ea100465d9c98OGAWA Hirofumi int i, err = 0; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2739cb569d601e0b93e01c20a22872270ec663b75f6Christoph Hellwig for (i = 0; i < nr_bhs; i++) 2749cb569d601e0b93e01c20a22872270ec663b75f6Christoph Hellwig write_dirty_buffer(bhs[i], WRITE); 2759cb569d601e0b93e01c20a22872270ec663b75f6Christoph Hellwig 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < nr_bhs; i++) { 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds wait_on_buffer(bhs[i]); 2780edd55faea7c8081bc826234b917501738a6218fChristoph Hellwig if (!err && !buffer_uptodate(bhs[i])) 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = -EIO; 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 283