1f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o/* 2e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o * lsdel.c --- routines to try to help a user recover a deleted file. 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 4e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 5e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o * Theodore Ts'o. This file may be redistributed under the terms of 6e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o * the GNU Public License. 7f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o */ 8f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 9f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <stdio.h> 10f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <unistd.h> 11f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <stdlib.h> 12f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <ctype.h> 13f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <string.h> 14f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <time.h> 1550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_ERRNO_H 1650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <errno.h> 1750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif 18f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/types.h> 19f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include <sys/stat.h> 20f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 21f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#include "debugfs.h" 22f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 23f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostruct deleted_info { 24b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o ext2_ino_t ino; 25b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o unsigned short mode; 265113a6e32b298671c86ae7da097bcd24540cebc9Eric Sandeen __u32 uid; 27b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o __u64 size; 28b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o time_t dtime; 29b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o e2_blkcnt_t num_blocks; 30b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o e2_blkcnt_t free_blocks; 31f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o}; 32f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 33f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ostruct lsdel_struct { 34b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o ext2_ino_t inode; 35b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o e2_blkcnt_t num_blocks; 36b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o e2_blkcnt_t free_blocks; 37b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o e2_blkcnt_t bad_blocks; 38f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o}; 39f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 4050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'ostatic int deleted_info_compare(const void *a, const void *b) 41f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{ 4250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o const struct deleted_info *arg1, *arg2; 43f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 4450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o arg1 = (const struct deleted_info *) a; 4550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o arg2 = (const struct deleted_info *) b; 46f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 47f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return arg1->dtime - arg2->dtime; 48f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o} 49f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 5050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'ostatic int lsdel_proc(ext2_filsys fs, 51e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t *block_nr, 52b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o e2_blkcnt_t blockcnt EXT2FS_ATTR((unused)), 53e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t ref_block EXT2FS_ATTR((unused)), 54b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), 5550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o void *private) 56f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{ 57f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o struct lsdel_struct *lsd = (struct lsdel_struct *) private; 58f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 59f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o lsd->num_blocks++; 60f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 61f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (*block_nr < fs->super->s_first_data_block || 62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *block_nr >= ext2fs_blocks_count(fs->super)) { 63f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o lsd->bad_blocks++; 64f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return BLOCK_ABORT; 65f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 66f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!ext2fs_test_block_bitmap2(fs->block_map,*block_nr)) 68f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o lsd->free_blocks++; 69f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 70f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return 0; 71f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o} 72f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 73f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'ovoid do_lsdel(int argc, char **argv) 74f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{ 75f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o struct lsdel_struct lsd; 76f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o struct deleted_info *delarray; 77f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o int num_delarray, max_delarray; 78f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2_inode_scan scan = 0; 79b044c2e02af46c54206f0f6e29896ab32681a7dbTheodore Ts'o ext2_ino_t ino; 80f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o struct ext2_inode inode; 81f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o errcode_t retval; 82f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o char *block_buf; 83f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o int i; 84e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o long secs = 0; 85e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o char *tmp; 866cab406d2b687f251ae533951c78fbe484cff0dfTheodore Ts'o time_t now; 877380ac903316c0fe91ed6706eb4d84249a9b348dTheodore Ts'o FILE *out; 88efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (common_args_process(argc, argv, 1, 2, "list_deleted_inodes", 90e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o "[secs]", 0)) 91f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return; 926cab406d2b687f251ae533951c78fbe484cff0dfTheodore Ts'o 93e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o if (argc > 1) { 94e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o secs = strtol(argv[1],&tmp,0); 95e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o if (*tmp) { 96e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o com_err(argv[0], 0, "Bad time - %s",argv[1]); 97e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o return; 98e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o } 99f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 100f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1016cab406d2b687f251ae533951c78fbe484cff0dfTheodore Ts'o now = current_fs->now ? current_fs->now : time(0); 102f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o max_delarray = 100; 103f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_delarray = 0; 104f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o delarray = malloc(max_delarray * sizeof(struct deleted_info)); 105f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (!delarray) { 106f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err("ls_deleted_inodes", ENOMEM, 107f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "while allocating deleted information storage"); 108f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o exit(1); 109f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 110f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 111fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o block_buf = malloc(current_fs->blocksize * 3); 112f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (!block_buf) { 113f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err("ls_deleted_inodes", ENOMEM, "while allocating block buffer"); 114f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o goto error_out; 115f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 116f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 117fc6d9d519aef67735918bf02c0fa8c9222008f76Theodore Ts'o retval = ext2fs_open_inode_scan(current_fs, 0, &scan); 118f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (retval) { 119f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err("ls_deleted_inodes", retval, 120f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "while opening inode scan"); 121f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o goto error_out; 122f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 123f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1243e025efc0fb0de0f62be3421aa61c75eedf0d913Theodore Ts'o do { 1253e025efc0fb0de0f62be3421aa61c75eedf0d913Theodore Ts'o retval = ext2fs_get_next_inode(scan, &ino, &inode); 1263e025efc0fb0de0f62be3421aa61c75eedf0d913Theodore Ts'o } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); 127f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (retval) { 128f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err("ls_deleted_inodes", retval, 129f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "while starting inode scan"); 130f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o goto error_out; 131f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 132efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 133f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o while (ino) { 134e1018eeaa3285cd0ca26986d929194c1b577d211Theodore Ts'o if ((inode.i_dtime == 0) || 135544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o (secs && ((unsigned) abs(now - secs) > inode.i_dtime))) 136f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o goto next; 137f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 138f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o lsd.inode = ino; 139f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o lsd.num_blocks = 0; 140f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o lsd.free_blocks = 0; 141f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o lsd.bad_blocks = 0; 142efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 143e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_block_iterate3(current_fs, ino, 14443323be95742298b8229be728c3812e95c90629cTheodore Ts'o BLOCK_FLAG_READ_ONLY, block_buf, 145b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o lsdel_proc, &lsd); 146f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (retval) { 147f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err("ls_deleted_inodes", retval, 148b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o "while calling ext2fs_block_iterate2"); 149f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o goto next; 150f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 151f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (lsd.free_blocks && !lsd.bad_blocks) { 152f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (num_delarray >= max_delarray) { 153f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o max_delarray += 50; 154f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o delarray = realloc(delarray, 155f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o max_delarray * sizeof(struct deleted_info)); 156f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (!delarray) { 157f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err("ls_deleted_inodes", 158f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ENOMEM, 159f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "while reallocating array"); 160f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o exit(1); 161f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 162f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 163efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 164f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o delarray[num_delarray].ino = ino; 165f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o delarray[num_delarray].mode = inode.i_mode; 1665113a6e32b298671c86ae7da097bcd24540cebc9Eric Sandeen delarray[num_delarray].uid = inode_uid(inode); 167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall delarray[num_delarray].size = EXT2_I_SIZE(&inode); 168f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o delarray[num_delarray].dtime = inode.i_dtime; 169f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o delarray[num_delarray].num_blocks = lsd.num_blocks; 170f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o delarray[num_delarray].free_blocks = lsd.free_blocks; 171f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o num_delarray++; 172f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 173efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 174f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o next: 1753e025efc0fb0de0f62be3421aa61c75eedf0d913Theodore Ts'o do { 176ee753091cf6df32010c5f3ab37bf1326eef18d08Theodore Ts'o retval = ext2fs_get_next_inode(scan, &ino, &inode); 1773e025efc0fb0de0f62be3421aa61c75eedf0d913Theodore Ts'o } while (retval == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE); 178f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (retval) { 179f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o com_err("ls_deleted_inodes", retval, 180f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o "while doing inode scan"); 181f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o goto error_out; 182f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 183f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 184f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 1857380ac903316c0fe91ed6706eb4d84249a9b348dTheodore Ts'o out = open_pager(); 186efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 187b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o fprintf(out, " Inode Owner Mode Size Blocks Time deleted\n"); 188efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 189f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o qsort(delarray, num_delarray, sizeof(struct deleted_info), 190f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o deleted_info_compare); 191efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 192f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o for (i = 0; i < num_delarray; i++) { 193efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o fprintf(out, "%6u %6d %6o %6llu %6lld/%6lld %s", 194b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o delarray[i].ino, 195b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o delarray[i].uid, delarray[i].mode, delarray[i].size, 196efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o delarray[i].free_blocks, delarray[i].num_blocks, 197b05d4ab635196f1e45bb7a11914edb2b0877274cTheodore Ts'o time_to_string(delarray[i].dtime)); 198f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 1997380ac903316c0fe91ed6706eb4d84249a9b348dTheodore Ts'o fprintf(out, "%d deleted inodes found.\n", num_delarray); 2007380ac903316c0fe91ed6706eb4d84249a9b348dTheodore Ts'o close_pager(out); 201efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 202f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'oerror_out: 203f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o free(block_buf); 204f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o free(delarray); 205f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (scan) 206f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_close_inode_scan(scan); 207f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o return; 208f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o} 209f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 210f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 211f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o 212