ls.c revision a435ec3449694a8fa299337197cc09624960a3a6
1/* 2 * ls.c - List the contents of an ext2fs superblock 3 * 4 * Copyright (C) 1992, 1993, 1994 Remy Card <card@masi.ibp.fr> 5 * Laboratoire MASI, Institut Blaise Pascal 6 * Universite Pierre et Marie Curie (Paris VI) 7 * 8 * Copyright (C) 1995, 1996, 1997 Theodore Ts'o <tytso@mit.edu> 9 * 10 * This file can be redistributed under the terms of the GNU Library General 11 * Public License 12 */ 13 14#include <stdio.h> 15#include <sys/types.h> 16#include <string.h> 17#include <grp.h> 18#include <pwd.h> 19#include <time.h> 20 21#include "e2p.h" 22 23static void print_user (unsigned short uid, FILE *f) 24{ 25 struct passwd *pw; 26 27 fprintf(f, "%u ", uid); 28 pw = getpwuid (uid); 29 if (pw == NULL) 30 fprintf(f, "(user unknown)\n"); 31 else 32 fprintf(f, "(user %s)\n", pw->pw_name); 33} 34 35static void print_group (unsigned short gid, FILE *f) 36{ 37 struct group *gr; 38 39 fprintf(f, "%u ", gid); 40 gr = getgrgid (gid); 41 if (gr == NULL) 42 fprintf(f, "(group unknown)\n"); 43 else 44 fprintf(f, "(group %s)\n", gr->gr_name); 45} 46 47#define MONTH_INT (86400 * 30) 48#define WEEK_INT (86400 * 7) 49#define DAY_INT (86400) 50#define HOUR_INT (60 * 60) 51#define MINUTE_INT (60) 52 53static const char *interval_string(unsigned int secs) 54{ 55 static char buf[256], tmp[80]; 56 int hr, min, num; 57 58 buf[0] = 0; 59 60 if (secs == 0) 61 return "<none>"; 62 63 if (secs >= MONTH_INT) { 64 num = secs / MONTH_INT; 65 secs -= num*MONTH_INT; 66 sprintf(buf, "%d month%s", num, (num>1) ? "s" : ""); 67 } 68 if (secs >= WEEK_INT) { 69 num = secs / WEEK_INT; 70 secs -= num*WEEK_INT; 71 sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "", 72 num, (num>1) ? "s" : ""); 73 strcat(buf, tmp); 74 } 75 if (secs >= DAY_INT) { 76 num = secs / DAY_INT; 77 secs -= num*DAY_INT; 78 sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "", 79 num, (num>1) ? "s" : ""); 80 strcat(buf, tmp); 81 } 82 if (secs > 0) { 83 hr = secs / HOUR_INT; 84 secs -= hr*HOUR_INT; 85 min = secs / MINUTE_INT; 86 secs -= min*MINUTE_INT; 87 sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "", 88 hr, min, secs); 89 strcat(buf, tmp); 90 } 91 return buf; 92} 93 94static void print_features(struct ext2_super_block * s, FILE *f) 95{ 96#ifdef EXT2_DYNAMIC_REV 97 int i, j, printed=0; 98 __u32 *mask = &s->s_feature_compat, m; 99 100 fprintf(f, "Filesystem features: "); 101 for (i=0; i <3; i++,mask++) { 102 for (j=0,m=1; j < 32; j++, m<<=1) { 103 if (*mask & m) { 104 fprintf(f, " %s", e2p_feature2string(i, m)); 105 printed++; 106 } 107 } 108 } 109 if (printed == 0) 110 fprintf(f, " (none)"); 111 fprintf(f, "\n"); 112#endif 113} 114 115static void print_mntopts(struct ext2_super_block * s, FILE *f) 116{ 117#ifdef EXT2_DYNAMIC_REV 118 int i, printed=0; 119 __u32 mask = s->s_default_mount_opts, m; 120 121 fprintf(f, "Default mount options: "); 122 if (mask & EXT3_DEFM_JMODE) { 123 fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE)); 124 printed++; 125 } 126 for (i=0,m=1; i < 32; i++, m<<=1) { 127 if (m & EXT3_DEFM_JMODE) 128 continue; 129 if (mask & m) { 130 fprintf(f, " %s", e2p_mntopt2string(m)); 131 printed++; 132 } 133 } 134 if (printed == 0) 135 fprintf(f, " (none)"); 136 fprintf(f, "\n"); 137#endif 138} 139 140 141#ifndef EXT2_INODE_SIZE 142#define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode) 143#endif 144 145#ifndef EXT2_GOOD_OLD_REV 146#define EXT2_GOOD_OLD_REV 0 147#endif 148 149void list_super2(struct ext2_super_block * sb, FILE *f) 150{ 151 int inode_blocks_per_group; 152 char buf[80]; 153 const char *os; 154 time_t tm; 155 156 inode_blocks_per_group = (((sb->s_inodes_per_group * 157 EXT2_INODE_SIZE(sb)) + 158 EXT2_BLOCK_SIZE(sb) - 1) / 159 EXT2_BLOCK_SIZE(sb)); 160 if (sb->s_volume_name[0]) { 161 memset(buf, 0, sizeof(buf)); 162 strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name)); 163 } else 164 strcpy(buf, "<none>"); 165 fprintf(f, "Filesystem volume name: %s\n", buf); 166 if (sb->s_last_mounted[0]) { 167 memset(buf, 0, sizeof(buf)); 168 strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted)); 169 } else 170 strcpy(buf, "<not available>"); 171 fprintf(f, "Last mounted on: %s\n", buf); 172 fprintf(f, "Filesystem UUID: %s\n", e2p_uuid2str(sb->s_uuid)); 173 fprintf(f, "Filesystem magic number: 0x%04X\n", sb->s_magic); 174 fprintf(f, "Filesystem revision #: %d", sb->s_rev_level); 175 if (sb->s_rev_level == EXT2_GOOD_OLD_REV) { 176 fprintf(f, " (original)\n"); 177#ifdef EXT2_DYNAMIC_REV 178 } else if (sb->s_rev_level == EXT2_DYNAMIC_REV) { 179 fprintf(f, " (dynamic)\n"); 180#endif 181 } else 182 fprintf(f, " (unknown)\n"); 183 print_features(sb, f); 184 print_mntopts(sb, f); 185 fprintf(f, "Filesystem state: "); 186 print_fs_state (f, sb->s_state); 187 fprintf(f, "\n"); 188 fprintf(f, "Errors behavior: "); 189 print_fs_errors(f, sb->s_errors); 190 fprintf(f, "\n"); 191 switch (sb->s_creator_os) { 192 case EXT2_OS_LINUX: os = "Linux"; break; 193 case EXT2_OS_HURD: os = "GNU/Hurd"; break; 194 case EXT2_OS_MASIX: os = "Masix"; break; 195 default: os = "unknown"; break; 196 } 197 fprintf(f, "Filesystem OS type: %s\n", os); 198 fprintf(f, "Inode count: %u\n", sb->s_inodes_count); 199 fprintf(f, "Block count: %u\n", sb->s_blocks_count); 200 fprintf(f, "Reserved block count: %u\n", sb->s_r_blocks_count); 201 fprintf(f, "Free blocks: %u\n", sb->s_free_blocks_count); 202 fprintf(f, "Free inodes: %u\n", sb->s_free_inodes_count); 203 fprintf(f, "First block: %u\n", sb->s_first_data_block); 204 fprintf(f, "Block size: %u\n", EXT2_BLOCK_SIZE(sb)); 205 fprintf(f, "Fragment size: %u\n", EXT2_FRAG_SIZE(sb)); 206 fprintf(f, "Blocks per group: %u\n", sb->s_blocks_per_group); 207 fprintf(f, "Fragments per group: %u\n", sb->s_frags_per_group); 208 fprintf(f, "Inodes per group: %u\n", sb->s_inodes_per_group); 209 fprintf(f, "Inode blocks per group: %u\n", inode_blocks_per_group); 210 if (sb->s_first_meta_bg) 211 fprintf(f, "First meta block group: %u\n", 212 sb->s_first_meta_bg); 213 if (sb->s_mkfs_time) { 214 tm = sb->s_mkfs_time; 215 fprintf(f, "Filesystem created: %s", ctime(&tm)); 216 } 217 tm = sb->s_mtime; 218 fprintf(f, "Last mount time: %s", 219 sb->s_mtime ? ctime(&tm) : "n/a\n"); 220 tm = sb->s_wtime; 221 fprintf(f, "Last write time: %s", ctime(&tm)); 222 fprintf(f, "Mount count: %u\n", sb->s_mnt_count); 223 fprintf(f, "Maximum mount count: %d\n", sb->s_max_mnt_count); 224 tm = sb->s_lastcheck; 225 fprintf(f, "Last checked: %s", ctime(&tm)); 226 fprintf(f, "Check interval: %u (%s)\n", sb->s_checkinterval, 227 interval_string(sb->s_checkinterval)); 228 if (sb->s_checkinterval) 229 { 230 time_t next; 231 232 next = sb->s_lastcheck + sb->s_checkinterval; 233 fprintf(f, "Next check after: %s", ctime(&next)); 234 } 235 fprintf(f, "Reserved blocks uid: "); 236 print_user(sb->s_def_resuid, f); 237 fprintf(f, "Reserved blocks gid: "); 238 print_group(sb->s_def_resgid, f); 239 if (sb->s_rev_level >= EXT2_DYNAMIC_REV) { 240 fprintf(f, "First inode: %d\n", sb->s_first_ino); 241 fprintf(f, "Inode size: %d\n", sb->s_inode_size); 242 } 243 if (!e2p_is_null_uuid(sb->s_journal_uuid)) 244 fprintf(f, "Journal UUID: %s\n", 245 e2p_uuid2str(sb->s_journal_uuid)); 246 if (sb->s_journal_inum) 247 fprintf(f, "Journal inode: %u\n", 248 sb->s_journal_inum); 249 if (sb->s_journal_dev) 250 fprintf(f, "Journal device: 0x%04x\n", 251 sb->s_journal_dev); 252 if (sb->s_last_orphan) 253 fprintf(f, "First orphan inode: %u\n", 254 sb->s_last_orphan); 255 if ((sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) || 256 sb->s_def_hash_version) 257 fprintf(f, "Default directory hash: %s\n", 258 e2p_hash2string(sb->s_def_hash_version)); 259 if (!e2p_is_null_uuid(sb->s_hash_seed)) 260 fprintf(f, "Directory Hash Seed: %s\n", 261 e2p_uuid2str(sb->s_hash_seed)); 262 if (sb->s_jnl_backup_type) { 263 fprintf(f, "Journal backup: "); 264 switch (sb->s_jnl_backup_type) { 265 case 1: 266 fprintf(f, "inode blocks\n"); 267 break; 268 default: 269 fprintf(f, "type %u\n", sb->s_jnl_backup_type); 270 } 271 } 272} 273 274void list_super (struct ext2_super_block * s) 275{ 276 list_super2(s, stdout); 277} 278 279