0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/fs.h>
0009
0010 #include "debug.h"
0011 #include "ntfs.h"
0012 #include "ntfs_fs.h"
0013
0014 static inline int compare_attr(const struct ATTRIB *left, enum ATTR_TYPE type,
0015 const __le16 *name, u8 name_len,
0016 const u16 *upcase)
0017 {
0018
0019 int diff = le32_to_cpu(left->type) - le32_to_cpu(type);
0020
0021 if (diff)
0022 return diff;
0023
0024
0025 return ntfs_cmp_names(attr_name(left), left->name_len, name, name_len,
0026 upcase, true);
0027 }
0028
0029
0030
0031
0032
0033
0034 static __le16 mi_new_attt_id(struct mft_inode *mi)
0035 {
0036 u16 free_id, max_id, t16;
0037 struct MFT_REC *rec = mi->mrec;
0038 struct ATTRIB *attr;
0039 __le16 id;
0040
0041 id = rec->next_attr_id;
0042 free_id = le16_to_cpu(id);
0043 if (free_id < 0x7FFF) {
0044 rec->next_attr_id = cpu_to_le16(free_id + 1);
0045 return id;
0046 }
0047
0048
0049 free_id = 0;
0050 max_id = 0;
0051
0052 attr = NULL;
0053
0054 for (;;) {
0055 attr = mi_enum_attr(mi, attr);
0056 if (!attr) {
0057 rec->next_attr_id = cpu_to_le16(max_id + 1);
0058 mi->dirty = true;
0059 return cpu_to_le16(free_id);
0060 }
0061
0062 t16 = le16_to_cpu(attr->id);
0063 if (t16 == free_id) {
0064 free_id += 1;
0065 attr = NULL;
0066 } else if (max_id < t16)
0067 max_id = t16;
0068 }
0069 }
0070
0071 int mi_get(struct ntfs_sb_info *sbi, CLST rno, struct mft_inode **mi)
0072 {
0073 int err;
0074 struct mft_inode *m = kzalloc(sizeof(struct mft_inode), GFP_NOFS);
0075
0076 if (!m)
0077 return -ENOMEM;
0078
0079 err = mi_init(m, sbi, rno);
0080 if (err) {
0081 kfree(m);
0082 return err;
0083 }
0084
0085 err = mi_read(m, false);
0086 if (err) {
0087 mi_put(m);
0088 return err;
0089 }
0090
0091 *mi = m;
0092 return 0;
0093 }
0094
0095 void mi_put(struct mft_inode *mi)
0096 {
0097 mi_clear(mi);
0098 kfree(mi);
0099 }
0100
0101 int mi_init(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno)
0102 {
0103 mi->sbi = sbi;
0104 mi->rno = rno;
0105 mi->mrec = kmalloc(sbi->record_size, GFP_NOFS);
0106 if (!mi->mrec)
0107 return -ENOMEM;
0108
0109 return 0;
0110 }
0111
0112
0113
0114
0115 int mi_read(struct mft_inode *mi, bool is_mft)
0116 {
0117 int err;
0118 struct MFT_REC *rec = mi->mrec;
0119 struct ntfs_sb_info *sbi = mi->sbi;
0120 u32 bpr = sbi->record_size;
0121 u64 vbo = (u64)mi->rno << sbi->record_bits;
0122 struct ntfs_inode *mft_ni = sbi->mft.ni;
0123 struct runs_tree *run = mft_ni ? &mft_ni->file.run : NULL;
0124 struct rw_semaphore *rw_lock = NULL;
0125
0126 if (is_mounted(sbi)) {
0127 if (!is_mft) {
0128 rw_lock = &mft_ni->file.run_lock;
0129 down_read(rw_lock);
0130 }
0131 }
0132
0133 err = ntfs_read_bh(sbi, run, vbo, &rec->rhdr, bpr, &mi->nb);
0134 if (rw_lock)
0135 up_read(rw_lock);
0136 if (!err)
0137 goto ok;
0138
0139 if (err == -E_NTFS_FIXUP) {
0140 mi->dirty = true;
0141 goto ok;
0142 }
0143
0144 if (err != -ENOENT)
0145 goto out;
0146
0147 if (rw_lock) {
0148 ni_lock(mft_ni);
0149 down_write(rw_lock);
0150 }
0151 err = attr_load_runs_vcn(mft_ni, ATTR_DATA, NULL, 0, &mft_ni->file.run,
0152 vbo >> sbi->cluster_bits);
0153 if (rw_lock) {
0154 up_write(rw_lock);
0155 ni_unlock(mft_ni);
0156 }
0157 if (err)
0158 goto out;
0159
0160 if (rw_lock)
0161 down_read(rw_lock);
0162 err = ntfs_read_bh(sbi, run, vbo, &rec->rhdr, bpr, &mi->nb);
0163 if (rw_lock)
0164 up_read(rw_lock);
0165
0166 if (err == -E_NTFS_FIXUP) {
0167 mi->dirty = true;
0168 goto ok;
0169 }
0170 if (err)
0171 goto out;
0172
0173 ok:
0174
0175 if (le32_to_cpu(rec->total) != bpr) {
0176 err = -EINVAL;
0177 goto out;
0178 }
0179
0180 return 0;
0181
0182 out:
0183 return err;
0184 }
0185
0186 struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)
0187 {
0188 const struct MFT_REC *rec = mi->mrec;
0189 u32 used = le32_to_cpu(rec->used);
0190 u32 t32, off, asize;
0191 u16 t16;
0192
0193 if (!attr) {
0194 u32 total = le32_to_cpu(rec->total);
0195
0196 off = le16_to_cpu(rec->attr_off);
0197
0198 if (used > total)
0199 return NULL;
0200
0201 if (off >= used || off < MFTRECORD_FIXUP_OFFSET_1 ||
0202 !IS_ALIGNED(off, 4)) {
0203 return NULL;
0204 }
0205
0206
0207 if (!is_rec_inuse(rec))
0208 return NULL;
0209
0210 attr = Add2Ptr(rec, off);
0211 } else {
0212
0213 off = PtrOffset(rec, attr);
0214 if (off >= used)
0215 return NULL;
0216
0217 asize = le32_to_cpu(attr->size);
0218 if (asize < SIZEOF_RESIDENT) {
0219
0220 return NULL;
0221 }
0222
0223 attr = Add2Ptr(attr, asize);
0224 off += asize;
0225 }
0226
0227 asize = le32_to_cpu(attr->size);
0228
0229
0230 if (off + 8 > used) {
0231 static_assert(ALIGN(sizeof(enum ATTR_TYPE), 8) == 8);
0232 return NULL;
0233 }
0234
0235 if (attr->type == ATTR_END) {
0236
0237 return NULL;
0238 }
0239
0240
0241 t32 = le32_to_cpu(attr->type);
0242 if ((t32 & 0xf) || (t32 > 0x100))
0243 return NULL;
0244
0245
0246 if (off + asize > used)
0247 return NULL;
0248
0249
0250 if (!attr->non_res) {
0251 if (asize < SIZEOF_RESIDENT)
0252 return NULL;
0253
0254 t16 = le16_to_cpu(attr->res.data_off);
0255
0256 if (t16 > asize)
0257 return NULL;
0258
0259 t32 = le32_to_cpu(attr->res.data_size);
0260 if (t16 + t32 > asize)
0261 return NULL;
0262
0263 return attr;
0264 }
0265
0266
0267 if (attr->name_len &&
0268 le16_to_cpu(attr->name_off) + sizeof(short) * attr->name_len >
0269 le16_to_cpu(attr->nres.run_off)) {
0270 return NULL;
0271 }
0272
0273 if (attr->nres.svcn || !is_attr_ext(attr)) {
0274 if (asize + 8 < SIZEOF_NONRESIDENT)
0275 return NULL;
0276
0277 if (attr->nres.c_unit)
0278 return NULL;
0279 } else if (asize + 8 < SIZEOF_NONRESIDENT_EX)
0280 return NULL;
0281
0282 return attr;
0283 }
0284
0285
0286
0287
0288 struct ATTRIB *mi_find_attr(struct mft_inode *mi, struct ATTRIB *attr,
0289 enum ATTR_TYPE type, const __le16 *name,
0290 size_t name_len, const __le16 *id)
0291 {
0292 u32 type_in = le32_to_cpu(type);
0293 u32 atype;
0294
0295 next_attr:
0296 attr = mi_enum_attr(mi, attr);
0297 if (!attr)
0298 return NULL;
0299
0300 atype = le32_to_cpu(attr->type);
0301 if (atype > type_in)
0302 return NULL;
0303
0304 if (atype < type_in)
0305 goto next_attr;
0306
0307 if (attr->name_len != name_len)
0308 goto next_attr;
0309
0310 if (name_len && memcmp(attr_name(attr), name, name_len * sizeof(short)))
0311 goto next_attr;
0312
0313 if (id && *id != attr->id)
0314 goto next_attr;
0315
0316 return attr;
0317 }
0318
0319 int mi_write(struct mft_inode *mi, int wait)
0320 {
0321 struct MFT_REC *rec;
0322 int err;
0323 struct ntfs_sb_info *sbi;
0324
0325 if (!mi->dirty)
0326 return 0;
0327
0328 sbi = mi->sbi;
0329 rec = mi->mrec;
0330
0331 err = ntfs_write_bh(sbi, &rec->rhdr, &mi->nb, wait);
0332 if (err)
0333 return err;
0334
0335 if (mi->rno < sbi->mft.recs_mirr)
0336 sbi->flags |= NTFS_FLAGS_MFTMIRR;
0337
0338 mi->dirty = false;
0339
0340 return 0;
0341 }
0342
0343 int mi_format_new(struct mft_inode *mi, struct ntfs_sb_info *sbi, CLST rno,
0344 __le16 flags, bool is_mft)
0345 {
0346 int err;
0347 u16 seq = 1;
0348 struct MFT_REC *rec;
0349 u64 vbo = (u64)rno << sbi->record_bits;
0350
0351 err = mi_init(mi, sbi, rno);
0352 if (err)
0353 return err;
0354
0355 rec = mi->mrec;
0356
0357 if (rno == MFT_REC_MFT) {
0358 ;
0359 } else if (rno < MFT_REC_FREE) {
0360 seq = rno;
0361 } else if (rno >= sbi->mft.used) {
0362 ;
0363 } else if (mi_read(mi, is_mft)) {
0364 ;
0365 } else if (rec->rhdr.sign == NTFS_FILE_SIGNATURE) {
0366
0367 seq = le16_to_cpu(rec->seq) + 1;
0368 if (!seq)
0369 seq = 1;
0370 }
0371
0372 memcpy(rec, sbi->new_rec, sbi->record_size);
0373
0374 rec->seq = cpu_to_le16(seq);
0375 rec->flags = RECORD_FLAG_IN_USE | flags;
0376
0377 mi->dirty = true;
0378
0379 if (!mi->nb.nbufs) {
0380 struct ntfs_inode *ni = sbi->mft.ni;
0381 bool lock = false;
0382
0383 if (is_mounted(sbi) && !is_mft) {
0384 down_read(&ni->file.run_lock);
0385 lock = true;
0386 }
0387
0388 err = ntfs_get_bh(sbi, &ni->file.run, vbo, sbi->record_size,
0389 &mi->nb);
0390 if (lock)
0391 up_read(&ni->file.run_lock);
0392 }
0393
0394 return err;
0395 }
0396
0397
0398
0399
0400
0401
0402 struct ATTRIB *mi_insert_attr(struct mft_inode *mi, enum ATTR_TYPE type,
0403 const __le16 *name, u8 name_len, u32 asize,
0404 u16 name_off)
0405 {
0406 size_t tail;
0407 struct ATTRIB *attr;
0408 __le16 id;
0409 struct MFT_REC *rec = mi->mrec;
0410 struct ntfs_sb_info *sbi = mi->sbi;
0411 u32 used = le32_to_cpu(rec->used);
0412 const u16 *upcase = sbi->upcase;
0413 int diff;
0414
0415
0416 if (used + asize > mi->sbi->record_size)
0417 return NULL;
0418
0419
0420
0421
0422
0423 attr = NULL;
0424 while ((attr = mi_enum_attr(mi, attr))) {
0425 diff = compare_attr(attr, type, name, name_len, upcase);
0426
0427 if (diff < 0)
0428 continue;
0429
0430 if (!diff && !is_attr_indexed(attr))
0431 return NULL;
0432 break;
0433 }
0434
0435 if (!attr) {
0436 tail = 8;
0437 attr = Add2Ptr(rec, used - 8);
0438 } else {
0439 tail = used - PtrOffset(rec, attr);
0440 }
0441
0442 id = mi_new_attt_id(mi);
0443
0444 memmove(Add2Ptr(attr, asize), attr, tail);
0445 memset(attr, 0, asize);
0446
0447 attr->type = type;
0448 attr->size = cpu_to_le32(asize);
0449 attr->name_len = name_len;
0450 attr->name_off = cpu_to_le16(name_off);
0451 attr->id = id;
0452
0453 memmove(Add2Ptr(attr, name_off), name, name_len * sizeof(short));
0454 rec->used = cpu_to_le32(used + asize);
0455
0456 mi->dirty = true;
0457
0458 return attr;
0459 }
0460
0461
0462
0463
0464
0465
0466 bool mi_remove_attr(struct ntfs_inode *ni, struct mft_inode *mi,
0467 struct ATTRIB *attr)
0468 {
0469 struct MFT_REC *rec = mi->mrec;
0470 u32 aoff = PtrOffset(rec, attr);
0471 u32 used = le32_to_cpu(rec->used);
0472 u32 asize = le32_to_cpu(attr->size);
0473
0474 if (aoff + asize > used)
0475 return false;
0476
0477 if (ni && is_attr_indexed(attr)) {
0478 le16_add_cpu(&ni->mi.mrec->hard_links, -1);
0479 ni->mi.dirty = true;
0480 }
0481
0482 used -= asize;
0483 memmove(attr, Add2Ptr(attr, asize), used - aoff);
0484 rec->used = cpu_to_le32(used);
0485 mi->dirty = true;
0486
0487 return true;
0488 }
0489
0490
0491 bool mi_resize_attr(struct mft_inode *mi, struct ATTRIB *attr, int bytes)
0492 {
0493 struct MFT_REC *rec = mi->mrec;
0494 u32 aoff = PtrOffset(rec, attr);
0495 u32 total, used = le32_to_cpu(rec->used);
0496 u32 nsize, asize = le32_to_cpu(attr->size);
0497 u32 rsize = le32_to_cpu(attr->res.data_size);
0498 int tail = (int)(used - aoff - asize);
0499 int dsize;
0500 char *next;
0501
0502 if (tail < 0 || aoff >= used)
0503 return false;
0504
0505 if (!bytes)
0506 return true;
0507
0508 total = le32_to_cpu(rec->total);
0509 next = Add2Ptr(attr, asize);
0510
0511 if (bytes > 0) {
0512 dsize = ALIGN(bytes, 8);
0513 if (used + dsize > total)
0514 return false;
0515 nsize = asize + dsize;
0516
0517 memmove(next + dsize, next, tail);
0518 memset(next, 0, dsize);
0519 used += dsize;
0520 rsize += dsize;
0521 } else {
0522 dsize = ALIGN(-bytes, 8);
0523 if (dsize > asize)
0524 return false;
0525 nsize = asize - dsize;
0526 memmove(next - dsize, next, tail);
0527 used -= dsize;
0528 rsize -= dsize;
0529 }
0530
0531 rec->used = cpu_to_le32(used);
0532 attr->size = cpu_to_le32(nsize);
0533 if (!attr->non_res)
0534 attr->res.data_size = cpu_to_le32(rsize);
0535 mi->dirty = true;
0536
0537 return true;
0538 }
0539
0540 int mi_pack_runs(struct mft_inode *mi, struct ATTRIB *attr,
0541 struct runs_tree *run, CLST len)
0542 {
0543 int err = 0;
0544 struct ntfs_sb_info *sbi = mi->sbi;
0545 u32 new_run_size;
0546 CLST plen;
0547 struct MFT_REC *rec = mi->mrec;
0548 CLST svcn = le64_to_cpu(attr->nres.svcn);
0549 u32 used = le32_to_cpu(rec->used);
0550 u32 aoff = PtrOffset(rec, attr);
0551 u32 asize = le32_to_cpu(attr->size);
0552 char *next = Add2Ptr(attr, asize);
0553 u16 run_off = le16_to_cpu(attr->nres.run_off);
0554 u32 run_size = asize - run_off;
0555 u32 tail = used - aoff - asize;
0556 u32 dsize = sbi->record_size - used;
0557
0558
0559 memmove(next + dsize, next, tail);
0560
0561
0562 err = run_pack(run, svcn, len, Add2Ptr(attr, run_off), run_size + dsize,
0563 &plen);
0564 if (err < 0) {
0565 memmove(next, next + dsize, tail);
0566 return err;
0567 }
0568
0569 new_run_size = ALIGN(err, 8);
0570
0571 memmove(next + new_run_size - run_size, next + dsize, tail);
0572
0573 attr->size = cpu_to_le32(asize + new_run_size - run_size);
0574 attr->nres.evcn = cpu_to_le64(svcn + plen - 1);
0575 rec->used = cpu_to_le32(used + new_run_size - run_size);
0576 mi->dirty = true;
0577
0578 return 0;
0579 }