+ struct exfat *exfat = fsck->exfat;
+ struct exfat_inode *lostfound;
+ bitmap_t *disk_b, *alloc_b, *ohead_b;
+ struct exfat_dentry *dset;
+ clus_t clu_count, clu, s_clu, e_clu;
+ int err, dcount;
+ unsigned int i;
+ char name[] = "FILE0000000.CHK";
+ struct exfat_dentry_loc loc;
+ struct exfat_lookup_filter lf = {
+ .in.type = EXFAT_INVAL,
+ .in.dentry_count = 0,
+ .in.filter = NULL,
+ };
+
+ clu_count = le32_to_cpu(exfat->bs->bsx.clu_count);
+
+ /* find clusters which are not marked as free, but not allocated to
+ * any files.
+ */
+ disk_b = (bitmap_t *)exfat->disk_bitmap;
+ alloc_b = (bitmap_t *)exfat->alloc_bitmap;
+ ohead_b = (bitmap_t *)exfat->ohead_bitmap;
+ for (i = 0; i < EXFAT_BITMAP_SIZE(clu_count) / sizeof(bitmap_t); i++)
+ ohead_b[i] = disk_b[i] & ~alloc_b[i];
+
+ /* no orphan clusters */
+ if (exfat_bitmap_find_one(exfat, exfat->ohead_bitmap,
+ EXFAT_FIRST_CLUSTER, &s_clu))
+ return 0;
+
+ err = exfat_create_file(exfat_fsck.exfat,
+ exfat_fsck.exfat->root,
+ "LOST+FOUND",
+ ATTR_SUBDIR);
+ if (err) {
+ exfat_err("failed to create LOST+FOUND directory\n");
+ return err;
+ }
+
+ if (fsync(exfat_fsck.exfat->blk_dev->dev_fd) != 0) {
+ exfat_err("failed to sync()\n");
+ return -EIO;
+ }
+
+ err = read_lostfound(exfat, &lostfound);
+ if (err) {
+ exfat_err("failed to find LOST+FOUND\n");
+ return err;
+ }
+
+ /* get the last empty region of LOST+FOUND */
+ err = exfat_lookup_dentry_set(exfat, lostfound, &lf);
+ if (err && err != EOF) {
+ exfat_err("failed to find the last empty slot in LOST+FOUND\n");
+ goto out;
+ }
+
+ loc.parent = lostfound;
+ loc.file_offset = lf.out.file_offset;
+ loc.dev_offset = lf.out.dev_offset;
+
+ /* build a template dentry set */
+ err = exfat_build_file_dentry_set(exfat, name, 0, &dset, &dcount);
+ if (err) {
+ exfat_err("failed to create a temporary file in LOST+FOUNDn");
+ goto out;
+ }
+ dset[1].dentry.stream.flags |= EXFAT_SF_CONTIGUOUS;
+
+ /* create temporary files and allocate contiguous orphan clusters
+ * to each file.
+ */
+ for (clu = EXFAT_FIRST_CLUSTER; clu < clu_count + EXFAT_FIRST_CLUSTER &&
+ exfat_bitmap_find_one(exfat, exfat->ohead_bitmap, clu, &s_clu) == 0;) {
+ if (exfat_bitmap_find_zero(exfat, exfat->ohead_bitmap, s_clu, &e_clu))
+ e_clu = clu_count + EXFAT_FIRST_CLUSTER;
+ clu = e_clu;
+
+ snprintf(name, sizeof(name), "FILE%07d.CHK",
+ (unsigned int)(loc.file_offset >> 5));
+ err = exfat_update_file_dentry_set(exfat, dset, dcount,
+ name, s_clu, e_clu - s_clu);
+ if (err)
+ continue;
+ err = exfat_add_dentry_set(exfat, &loc, dset, dcount, true);
+ if (err)
+ continue;
+ }
+
+ free(dset);
+ err = 0;
+out:
+ exfat_free_inode(lostfound);
+ return err;