Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only 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 : : #include "fat.h" 11 : : #include <linux/iversion.h> 12 : : 13 : : /* 14 : : * fat_fs_error reports a file system problem that might indicate fa data 15 : : * corruption/inconsistency. Depending on 'errors' mount option the 16 : : * panic() is called, or error message is printed FAT and nothing is done, 17 : : * or filesystem is remounted read-only (default behavior). 18 : : * In case the file system is remounted read-only, it can be made writable 19 : : * again by remounting it. 20 : : */ 21 : 0 : void __fat_fs_error(struct super_block *sb, int report, const char *fmt, ...) 22 : : { 23 : : struct fat_mount_options *opts = &MSDOS_SB(sb)->options; 24 : : va_list args; 25 : : struct va_format vaf; 26 : : 27 : 0 : if (report) { 28 : 0 : va_start(args, fmt); 29 : 0 : vaf.fmt = fmt; 30 : 0 : vaf.va = &args; 31 : 0 : fat_msg(sb, KERN_ERR, "error, %pV", &vaf); 32 : 0 : va_end(args); 33 : : } 34 : : 35 : 0 : if (opts->errors == FAT_ERRORS_PANIC) 36 : 0 : panic("FAT-fs (%s): fs panic from previous error\n", sb->s_id); 37 : 0 : else if (opts->errors == FAT_ERRORS_RO && !sb_rdonly(sb)) { 38 : 0 : sb->s_flags |= SB_RDONLY; 39 : 0 : fat_msg(sb, KERN_ERR, "Filesystem has been set read-only"); 40 : : } 41 : 0 : } 42 : : EXPORT_SYMBOL_GPL(__fat_fs_error); 43 : : 44 : : /** 45 : : * fat_msg() - print preformated FAT specific messages. Every thing what is 46 : : * not fat_fs_error() should be fat_msg(). 47 : : */ 48 : 0 : void fat_msg(struct super_block *sb, const char *level, const char *fmt, ...) 49 : : { 50 : : struct va_format vaf; 51 : : va_list args; 52 : : 53 : 0 : va_start(args, fmt); 54 : 0 : vaf.fmt = fmt; 55 : 0 : vaf.va = &args; 56 : 0 : printk("%sFAT-fs (%s): %pV\n", level, sb->s_id, &vaf); 57 : 0 : va_end(args); 58 : 0 : } 59 : : 60 : : /* Flushes the number of free clusters on FAT32 */ 61 : : /* XXX: Need to write one per FSINFO block. Currently only writes 1 */ 62 : 3 : int fat_clusters_flush(struct super_block *sb) 63 : : { 64 : : struct msdos_sb_info *sbi = MSDOS_SB(sb); 65 : : struct buffer_head *bh; 66 : : struct fat_boot_fsinfo *fsinfo; 67 : : 68 : 3 : if (!is_fat32(sbi)) 69 : : return 0; 70 : : 71 : 3 : bh = sb_bread(sb, sbi->fsinfo_sector); 72 : 3 : if (bh == NULL) { 73 : 0 : fat_msg(sb, KERN_ERR, "bread failed in fat_clusters_flush"); 74 : 0 : return -EIO; 75 : : } 76 : : 77 : 3 : fsinfo = (struct fat_boot_fsinfo *)bh->b_data; 78 : : /* Sanity check */ 79 : 3 : if (!IS_FSINFO(fsinfo)) { 80 : 0 : fat_msg(sb, KERN_ERR, "Invalid FSINFO signature: " 81 : : "0x%08x, 0x%08x (sector = %lu)", 82 : : le32_to_cpu(fsinfo->signature1), 83 : : le32_to_cpu(fsinfo->signature2), 84 : : sbi->fsinfo_sector); 85 : : } else { 86 : 3 : if (sbi->free_clusters != -1) 87 : 3 : fsinfo->free_clusters = cpu_to_le32(sbi->free_clusters); 88 : 3 : if (sbi->prev_free != -1) 89 : 3 : fsinfo->next_cluster = cpu_to_le32(sbi->prev_free); 90 : 3 : mark_buffer_dirty(bh); 91 : : } 92 : : brelse(bh); 93 : : 94 : : return 0; 95 : : } 96 : : 97 : : /* 98 : : * fat_chain_add() adds a new cluster to the chain of clusters represented 99 : : * by inode. 100 : : */ 101 : 0 : int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster) 102 : : { 103 : 0 : struct super_block *sb = inode->i_sb; 104 : : struct msdos_sb_info *sbi = MSDOS_SB(sb); 105 : : int ret, new_fclus, last; 106 : : 107 : : /* 108 : : * We must locate the last cluster of the file to add this new 109 : : * one (new_dclus) to the end of the link list (the FAT). 110 : : */ 111 : : last = new_fclus = 0; 112 : 0 : if (MSDOS_I(inode)->i_start) { 113 : : int fclus, dclus; 114 : : 115 : 0 : ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus); 116 : 0 : if (ret < 0) 117 : 0 : return ret; 118 : 0 : new_fclus = fclus + 1; 119 : 0 : last = dclus; 120 : : } 121 : : 122 : : /* add new one to the last of the cluster chain */ 123 : 0 : if (last) { 124 : : struct fat_entry fatent; 125 : : 126 : : fatent_init(&fatent); 127 : 0 : ret = fat_ent_read(inode, &fatent, last); 128 : 0 : if (ret >= 0) { 129 : 0 : int wait = inode_needs_sync(inode); 130 : 0 : ret = fat_ent_write(inode, &fatent, new_dclus, wait); 131 : 0 : fatent_brelse(&fatent); 132 : : } 133 : 0 : if (ret < 0) 134 : 0 : return ret; 135 : : /* 136 : : * FIXME:Although we can add this cache, fat_cache_add() is 137 : : * assuming to be called after linear search with fat_cache_id. 138 : : */ 139 : : // fat_cache_add(inode, new_fclus, new_dclus); 140 : : } else { 141 : 0 : MSDOS_I(inode)->i_start = new_dclus; 142 : 0 : MSDOS_I(inode)->i_logstart = new_dclus; 143 : : /* 144 : : * Since generic_write_sync() synchronizes regular files later, 145 : : * we sync here only directories. 146 : : */ 147 : 0 : if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode)) { 148 : 0 : ret = fat_sync_inode(inode); 149 : 0 : if (ret) 150 : : return ret; 151 : : } else 152 : : mark_inode_dirty(inode); 153 : : } 154 : 0 : if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) { 155 : 0 : fat_fs_error(sb, "clusters badly computed (%d != %llu)", 156 : : new_fclus, 157 : : (llu)(inode->i_blocks >> (sbi->cluster_bits - 9))); 158 : 0 : fat_cache_inval_inode(inode); 159 : : } 160 : 0 : inode->i_blocks += nr_cluster << (sbi->cluster_bits - 9); 161 : : 162 : 0 : return 0; 163 : : } 164 : : 165 : : /* 166 : : * The epoch of FAT timestamp is 1980. 167 : : * : bits : value 168 : : * date: 0 - 4: day (1 - 31) 169 : : * date: 5 - 8: month (1 - 12) 170 : : * date: 9 - 15: year (0 - 127) from 1980 171 : : * time: 0 - 4: sec (0 - 29) 2sec counts 172 : : * time: 5 - 10: min (0 - 59) 173 : : * time: 11 - 15: hour (0 - 23) 174 : : */ 175 : : #define SECS_PER_MIN 60 176 : : #define SECS_PER_HOUR (60 * 60) 177 : : #define SECS_PER_DAY (SECS_PER_HOUR * 24) 178 : : /* days between 1.1.70 and 1.1.80 (2 leap days) */ 179 : : #define DAYS_DELTA (365 * 10 + 2) 180 : : /* 120 (2100 - 1980) isn't leap year */ 181 : : #define YEAR_2100 120 182 : : #define IS_LEAP_YEAR(y) (!((y) & 3) && (y) != YEAR_2100) 183 : : 184 : : /* Linear day numbers of the respective 1sts in non-leap years. */ 185 : : static long days_in_year[] = { 186 : : /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ 187 : : 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 188 : : }; 189 : : 190 : : static inline int fat_tz_offset(struct msdos_sb_info *sbi) 191 : : { 192 : 3 : return (sbi->options.tz_set ? 193 : 0 : -sbi->options.time_offset : 194 : 3 : sys_tz.tz_minuteswest) * SECS_PER_MIN; 195 : : } 196 : : 197 : : /* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ 198 : 3 : void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec64 *ts, 199 : : __le16 __time, __le16 __date, u8 time_cs) 200 : : { 201 : : u16 time = le16_to_cpu(__time), date = le16_to_cpu(__date); 202 : : time64_t second; 203 : : long day, leap_day, month, year; 204 : : 205 : 3 : year = date >> 9; 206 : 3 : month = max(1, (date >> 5) & 0xf); 207 : 3 : day = max(1, date & 0x1f) - 1; 208 : : 209 : 3 : leap_day = (year + 3) / 4; 210 : 3 : if (year > YEAR_2100) /* 2100 isn't leap year */ 211 : 3 : leap_day--; 212 : 3 : if (IS_LEAP_YEAR(year) && month > 2) 213 : 0 : leap_day++; 214 : : 215 : 3 : second = (time & 0x1f) << 1; 216 : 3 : second += ((time >> 5) & 0x3f) * SECS_PER_MIN; 217 : 3 : second += (time >> 11) * SECS_PER_HOUR; 218 : 3 : second += (time64_t)(year * 365 + leap_day 219 : 3 : + days_in_year[month] + day 220 : 3 : + DAYS_DELTA) * SECS_PER_DAY; 221 : : 222 : 3 : second += fat_tz_offset(sbi); 223 : : 224 : 3 : if (time_cs) { 225 : 0 : ts->tv_sec = second + (time_cs / 100); 226 : 0 : ts->tv_nsec = (time_cs % 100) * 10000000; 227 : : } else { 228 : 3 : ts->tv_sec = second; 229 : 3 : ts->tv_nsec = 0; 230 : : } 231 : 3 : } 232 : : 233 : : /* Convert linear UNIX date to a FAT time/date pair. */ 234 : 0 : void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec64 *ts, 235 : : __le16 *time, __le16 *date, u8 *time_cs) 236 : : { 237 : : struct tm tm; 238 : 0 : time64_to_tm(ts->tv_sec, -fat_tz_offset(sbi), &tm); 239 : : 240 : : /* FAT can only support year between 1980 to 2107 */ 241 : 0 : if (tm.tm_year < 1980 - 1900) { 242 : 0 : *time = 0; 243 : 0 : *date = cpu_to_le16((0 << 9) | (1 << 5) | 1); 244 : 0 : if (time_cs) 245 : 0 : *time_cs = 0; 246 : 0 : return; 247 : : } 248 : 0 : if (tm.tm_year > 2107 - 1900) { 249 : 0 : *time = cpu_to_le16((23 << 11) | (59 << 5) | 29); 250 : 0 : *date = cpu_to_le16((127 << 9) | (12 << 5) | 31); 251 : 0 : if (time_cs) 252 : 0 : *time_cs = 199; 253 : : return; 254 : : } 255 : : 256 : : /* from 1900 -> from 1980 */ 257 : 0 : tm.tm_year -= 80; 258 : : /* 0~11 -> 1~12 */ 259 : 0 : tm.tm_mon++; 260 : : /* 0~59 -> 0~29(2sec counts) */ 261 : 0 : tm.tm_sec >>= 1; 262 : : 263 : 0 : *time = cpu_to_le16(tm.tm_hour << 11 | tm.tm_min << 5 | tm.tm_sec); 264 : 0 : *date = cpu_to_le16(tm.tm_year << 9 | tm.tm_mon << 5 | tm.tm_mday); 265 : 0 : if (time_cs) 266 : 0 : *time_cs = (ts->tv_sec & 1) * 100 + ts->tv_nsec / 10000000; 267 : : } 268 : : EXPORT_SYMBOL_GPL(fat_time_unix2fat); 269 : : 270 : : static inline struct timespec64 fat_timespec64_trunc_2secs(struct timespec64 ts) 271 : : { 272 : 0 : return (struct timespec64){ ts.tv_sec & ~1ULL, 0 }; 273 : : } 274 : : /* 275 : : * truncate the various times with appropriate granularity: 276 : : * root inode: 277 : : * all times always 0 278 : : * all other inodes: 279 : : * mtime - 2 seconds 280 : : * ctime 281 : : * msdos - 2 seconds 282 : : * vfat - 10 milliseconds 283 : : * atime - 24 hours (00:00:00 in local timezone) 284 : : */ 285 : 0 : int fat_truncate_time(struct inode *inode, struct timespec64 *now, int flags) 286 : : { 287 : 0 : struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); 288 : : struct timespec64 ts; 289 : : 290 : 0 : if (inode->i_ino == MSDOS_ROOT_INO) 291 : : return 0; 292 : : 293 : 0 : if (now == NULL) { 294 : : now = &ts; 295 : 0 : ts = current_time(inode); 296 : : } 297 : : 298 : 0 : if (flags & S_ATIME) { 299 : : /* to localtime */ 300 : 0 : time64_t seconds = now->tv_sec - fat_tz_offset(sbi); 301 : : s32 remainder; 302 : : 303 : 0 : div_s64_rem(seconds, SECS_PER_DAY, &remainder); 304 : : /* to day boundary, and back to unix time */ 305 : 0 : seconds = seconds + fat_tz_offset(sbi) - remainder; 306 : : 307 : 0 : inode->i_atime = (struct timespec64){ seconds, 0 }; 308 : : } 309 : 0 : if (flags & S_CTIME) { 310 : 0 : if (sbi->options.isvfat) 311 : 0 : inode->i_ctime = timespec64_trunc(*now, 10000000); 312 : : else 313 : 0 : inode->i_ctime = fat_timespec64_trunc_2secs(*now); 314 : : } 315 : 0 : if (flags & S_MTIME) 316 : 0 : inode->i_mtime = fat_timespec64_trunc_2secs(*now); 317 : : 318 : : return 0; 319 : : } 320 : : EXPORT_SYMBOL_GPL(fat_truncate_time); 321 : : 322 : 0 : int fat_update_time(struct inode *inode, struct timespec64 *now, int flags) 323 : : { 324 : : int iflags = I_DIRTY_TIME; 325 : : bool dirty = false; 326 : : 327 : 0 : if (inode->i_ino == MSDOS_ROOT_INO) 328 : : return 0; 329 : : 330 : 0 : fat_truncate_time(inode, now, flags); 331 : 0 : if (flags & S_VERSION) 332 : 0 : dirty = inode_maybe_inc_iversion(inode, false); 333 : 0 : if ((flags & (S_ATIME | S_CTIME | S_MTIME)) && 334 : 0 : !(inode->i_sb->s_flags & SB_LAZYTIME)) 335 : : dirty = true; 336 : : 337 : 0 : if (dirty) 338 : : iflags |= I_DIRTY_SYNC; 339 : 0 : __mark_inode_dirty(inode, iflags); 340 : 0 : return 0; 341 : : } 342 : : EXPORT_SYMBOL_GPL(fat_update_time); 343 : : 344 : 0 : int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) 345 : : { 346 : : int i, err = 0; 347 : : 348 : 0 : for (i = 0; i < nr_bhs; i++) 349 : 0 : write_dirty_buffer(bhs[i], 0); 350 : : 351 : 0 : for (i = 0; i < nr_bhs; i++) { 352 : 0 : wait_on_buffer(bhs[i]); 353 : 0 : if (!err && !buffer_uptodate(bhs[i])) 354 : : err = -EIO; 355 : : } 356 : 0 : return err; 357 : : }