1e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 2e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * filefrag.c --- display the fragmentation information for a file 3e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * 4e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Copyright (C) 2011 Theodore Ts'o. This file may be redistributed 5e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * under the terms of the GNU Public License. 6e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 7e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 8e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <stdio.h> 9e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <unistd.h> 10e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <stdlib.h> 11e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <ctype.h> 12e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <string.h> 13e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <time.h> 14e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef HAVE_ERRNO_H 15e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <errno.h> 16e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 17e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/types.h> 18e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <sys/stat.h> 19e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <fcntl.h> 20e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <utime.h> 21e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef HAVE_GETOPT_H 22e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <getopt.h> 23e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#else 24e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallextern int optind; 25e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallextern char *optarg; 26e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 27e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 28e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include "debugfs.h" 29e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 30e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define VERBOSE_OPT 0x0001 31e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define DIR_OPT 0x0002 32e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define RECURSIVE_OPT 0x0004 33e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 34e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct dir_list { 35e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *name; 36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t ino; 37e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct dir_list *next; 38e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 39e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 40e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstruct filefrag_struct { 41e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall FILE *f; 42e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const char *name; 43e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall const char *dir_name; 44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int options; 45e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int logical_width; 46e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int physical_width; 47e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ext; 48e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int cont_ext; 49e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall e2_blkcnt_t num; 50e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall e2_blkcnt_t logical_start; 51e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t physical_start; 52e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t expected; 53e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct dir_list *dir_list, *dir_last; 54e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}; 55e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 56e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int int_log10(unsigned long long arg) 57e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int l = 0; 59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall arg = arg / 10; 61e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (arg) { 62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall l++; 63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall arg = arg / 10; 64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return l; 66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void print_header(struct filefrag_struct *fs) 69e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->options & VERBOSE_OPT) { 71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(fs->f, "%4s %*s %*s %*s %*s\n", "ext", 72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->logical_width, "logical", fs->physical_width, 73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "physical", fs->physical_width, "expected", 74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->logical_width, "length"); 75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 76e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 78e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void report_filefrag(struct filefrag_struct *fs) 79e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->num == 0) 81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 82e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->options & VERBOSE_OPT) { 83e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->expected) 84e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(fs->f, "%4d %*lu %*llu %*llu %*lu\n", fs->ext, 85e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->logical_width, 86e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (unsigned long) fs->logical_start, 87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->physical_width, fs->physical_start, 88e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->physical_width, fs->expected, 89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->logical_width, (unsigned long) fs->num); 90e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 91e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(fs->f, "%4d %*lu %*llu %*s %*lu\n", fs->ext, 92e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->logical_width, 93e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (unsigned long) fs->logical_start, 94e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->physical_width, fs->physical_start, 95e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->physical_width, "", 96e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->logical_width, (unsigned long) fs->num); 97e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 98e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->ext++; 99e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 100e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int filefrag_blocks_proc(ext2_filsys ext4_fs EXT2FS_ATTR((unused)), 102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t *blocknr, e2_blkcnt_t blockcnt, 103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t ref_block EXT2FS_ATTR((unused)), 104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int ref_offset EXT2FS_ATTR((unused)), 105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *private) 106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct filefrag_struct *fs = private; 108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blockcnt < 0 || *blocknr == 0) 110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((fs->num == 0) || (blockcnt != fs->logical_start + fs->num) || 113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (*blocknr != fs->physical_start + fs->num)) { 114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall report_filefrag(fs); 115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blockcnt == fs->logical_start + fs->num) 116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->expected = fs->physical_start + fs->num; 117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->expected = 0; 119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->logical_start = blockcnt; 120e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->physical_start = *blocknr; 121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->num = 1; 122e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->cont_ext++; 123e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else 124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->num++; 125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void filefrag(ext2_ino_t ino, struct ext2_inode *inode, 129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct filefrag_struct *fs) 130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 131e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t retval; 132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int blocksize = current_fs->blocksize; 133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 134e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->logical_width = int_log10((EXT2_I_SIZE(inode) + blocksize - 1) / 135e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blocksize) + 1; 136e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->logical_width < 7) 137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->logical_width = 7; 138e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->ext = 0; 139e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->cont_ext = 0; 140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->logical_start = 0; 141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->physical_start = 0; 142e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->num = 0; 143e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 144e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->options & VERBOSE_OPT) { 145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t num_blocks = ext2fs_inode_i_blocks(current_fs, inode); 146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!(current_fs->super->s_feature_ro_compat & 148e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT4_FEATURE_RO_COMPAT_HUGE_FILE) || 149e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !(inode->i_flags & EXT4_HUGE_FILE_FL)) 150e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall num_blocks /= current_fs->blocksize / 512; 151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 152e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(fs->f, "\n%s has %llu block(s), i_size is %llu\n", 153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->name, num_blocks, EXT2_I_SIZE(inode)); 154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_header(fs); 156e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_block_iterate3(current_fs, ino, 157e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall BLOCK_FLAG_READ_ONLY, NULL, 158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall filefrag_blocks_proc, fs); 159e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 160e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err("ext2fs_block_iterate3", retval, 0); 161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 162e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall report_filefrag(fs); 163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(fs->f, "%s: %d contiguous extents%s\n", fs->name, fs->ext, 164e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall LINUX_S_ISDIR(inode->i_mode) ? " (dir)" : ""); 165e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 166e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int filefrag_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)), 168e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int entry, 169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_dir_entry *dirent, 170e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int offset EXT2FS_ATTR((unused)), 171e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int blocksize EXT2FS_ATTR((unused)), 172e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *buf EXT2FS_ATTR((unused)), 173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall void *private) 174e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct filefrag_struct *fs = private; 176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_inode inode; 177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t ino; 178e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char name[EXT2_NAME_LEN + 1]; 179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *cp; 180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int thislen; 181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (entry == DIRENT_DELETED_FILE) 183e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 184e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall thislen = dirent->name_len & 0xFF; 186e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall strncpy(name, dirent->name, thislen); 187e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall name[thislen] = '\0'; 188e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ino = dirent->inode; 189e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 190e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!strcmp(name, ".") || !strcmp(name, "..")) 191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 193e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall cp = malloc(strlen(fs->dir_name) + strlen(name) + 2); 194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!cp) { 195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "Couldn't allocate memory for %s/%s\n", 196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->dir_name, name); 197e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 198e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 199e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 200e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall sprintf(cp, "%s/%s", fs->dir_name, name); 201e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->name = cp; 202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 203e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (debugfs_read_inode(ino, &inode, fs->name)) 204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto errout; 205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall filefrag(ino, &inode, fs); 207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 208e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((fs->options & RECURSIVE_OPT) && LINUX_S_ISDIR(inode.i_mode)) { 209e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct dir_list *p; 210e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 211e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall p = malloc(sizeof(struct dir_list)); 212e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!p) { 213e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "Couldn't allocate dir_list for %s\n", 214e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->name); 215e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto errout; 216e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(p, 0, sizeof(struct dir_list)); 218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall p->name = cp; 219e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall p->ino = ino; 220e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->dir_last) 221e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->dir_last->next = p; 222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->dir_list = p; 224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->dir_last = p; 225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 227e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrout: 228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(cp); 229e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->name = 0; 230e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 231e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 232e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 233e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 234e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic void dir_iterate(ext2_ino_t ino, struct filefrag_struct *fs) 235e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 236e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t retval; 237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct dir_list *p = NULL; 238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->dir_name = fs->name; 240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while (1) { 242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_dir_iterate2(current_fs, ino, 0, 243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 0, filefrag_dir_proc, fs); 244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err("ext2fs_dir_iterate2", retval, 0); 246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (p) { 247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(p->name); 248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->dir_list = p->next; 249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!fs->dir_list) 250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->dir_last = 0; 251e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free(p); 252e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall p = fs->dir_list; 254e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!p) 255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 256e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ino = p->ino; 257e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->dir_name = p->name; 258e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 259e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 260e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid do_filefrag(int argc, char *argv[]) 262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct filefrag_struct fs; 264e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct ext2_inode inode; 265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t ino; 266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int c; 267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(&fs, 0, sizeof(fs)); 269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (check_fs_open(argv[0])) 270e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 271e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 272e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall reset_getopt(); 273e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall while ((c = getopt(argc, argv, "dvr")) != EOF) { 274e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall switch (c) { 275e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall case 'd': 276e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs.options |= DIR_OPT; 277e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall case 'v': 279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs.options |= VERBOSE_OPT; 280e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall case 'r': 282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs.options |= RECURSIVE_OPT; 283e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall break; 284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall default: 285e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto print_usage; 286e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 287e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 288e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 289e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (argc > optind+1) { 290e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_usage: 291e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall com_err(0, 0, "Usage: filefrag [-dvr] file"); 292e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 293e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 294e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 295e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (argc == optind) { 296e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ino = cwd; 297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs.name = "."; 298e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else { 299e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ino = string_to_inode(argv[optind]); 300e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs.name = argv[optind]; 301e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!ino) 303e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 304e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 305e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (debugfs_read_inode(ino, &inode, argv[0])) 306e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 307e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 308e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs.f = open_pager(); 309e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs.physical_width = int_log10(ext2fs_blocks_count(current_fs->super)); 310e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs.physical_width++; 311e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs.physical_width < 8) 312e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs.physical_width = 8; 313e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 314e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!LINUX_S_ISDIR(inode.i_mode) || (fs.options & DIR_OPT)) 315e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall filefrag(ino, &inode, &fs); 316e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 317e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dir_iterate(ino, &fs); 318e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 319e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(fs.f, "\n"); 320e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall close_pager(fs.f); 321e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 322e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 323e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 324