Whamcloud - gitweb
Many files:
[tools/e2fsprogs.git] / lib / e2p / ls.c
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
23 /*
24  * The ext2fs library private definition of the ext2 superblock, so we
25  * don't have to depend on the kernel's definition of the superblock,
26  * which might not have the latest features.
27  */
28 struct ext2fs_sb {
29         __u32   s_inodes_count;         /* Inodes count */
30         __u32   s_blocks_count;         /* Blocks count */
31         __u32   s_r_blocks_count;       /* Reserved blocks count */
32         __u32   s_free_blocks_count;    /* Free blocks count */
33         __u32   s_free_inodes_count;    /* Free inodes count */
34         __u32   s_first_data_block;     /* First Data Block */
35         __u32   s_log_block_size;       /* Block size */
36         __s32   s_log_frag_size;        /* Fragment size */
37         __u32   s_blocks_per_group;     /* # Blocks per group */
38         __u32   s_frags_per_group;      /* # Fragments per group */
39         __u32   s_inodes_per_group;     /* # Inodes per group */
40         __u32   s_mtime;                /* Mount time */
41         __u32   s_wtime;                /* Write time */
42         __u16   s_mnt_count;            /* Mount count */
43         __s16   s_max_mnt_count;        /* Maximal mount count */
44         __u16   s_magic;                /* Magic signature */
45         __u16   s_state;                /* File system state */
46         __u16   s_errors;               /* Behaviour when detecting errors */
47         __u16   s_minor_rev_level;      /* minor revision level */
48         __u32   s_lastcheck;            /* time of last check */
49         __u32   s_checkinterval;        /* max. time between checks */
50         __u32   s_creator_os;           /* OS */
51         __u32   s_rev_level;            /* Revision level */
52         __u16   s_def_resuid;           /* Default uid for reserved blocks */
53         __u16   s_def_resgid;           /* Default gid for reserved blocks */
54         /*
55          * These fields are for EXT2_DYNAMIC_REV superblocks only.
56          *
57          * Note: the difference between the compatible feature set and
58          * the incompatible feature set is that if there is a bit set
59          * in the incompatible feature set that the kernel doesn't
60          * know about, it should refuse to mount the filesystem.
61          * 
62          * e2fsck's requirements are more strict; if it doesn't know
63          * about a feature in either the compatible or incompatible
64          * feature set, it must abort and not try to meddle with
65          * things it doesn't understand...
66          */
67         __u32   s_first_ino;            /* First non-reserved inode */
68         __u16   s_inode_size;           /* size of inode structure */
69         __u16   s_block_group_nr;       /* block group # of this superblock */
70         __u32   s_feature_compat;       /* compatible feature set */
71         __u32   s_feature_incompat;     /* incompatible feature set */
72         __u32   s_feature_ro_compat;    /* readonly-compatible feature set */
73         __u8    s_uuid[16];             /* 128-bit uuid for volume */
74         char    s_volume_name[16];      /* volume name */
75         char    s_last_mounted[64];     /* directory where last mounted */
76         __u32   s_reserved[206];        /* Padding to the end of the block */
77 };
78
79 #ifndef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER
80 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER     0x0001
81 #endif
82
83 static void print_user (unsigned short uid)
84 {
85         struct passwd *pw;
86
87         printf ("%u ", uid);
88         pw = getpwuid (uid);
89         if (pw == NULL)
90                 printf ("(user unknown)\n");
91         else
92                 printf ("(user %s)\n", pw->pw_name);
93 }
94
95 static void print_group (unsigned short gid)
96 {
97         struct group *gr;
98
99         printf ("%u ", gid);
100         gr = getgrgid (gid);
101         if (gr == NULL)
102                 printf ("(group unknown)\n");
103         else
104                 printf ("(group %s)\n", gr->gr_name);
105 }
106
107 #define MONTH_INT (86400 * 30)
108 #define WEEK_INT (86400 * 7)
109 #define DAY_INT (86400)
110 #define HOUR_INT (60 * 60)
111 #define MINUTE_INT (60)
112
113 static const char *interval_string(unsigned int secs)
114 {
115         static char buf[256], tmp[80];
116         int             hr, min, num;
117
118         buf[0] = 0;
119
120         if (secs == 0)
121                 return "<none>";
122
123         if (secs >= MONTH_INT) {
124                 num = secs / MONTH_INT;
125                 secs -= num*MONTH_INT;
126                 sprintf(buf, "%d month%s", num, (num>1) ? "s" : "");
127         }
128         if (secs >= WEEK_INT) {
129                 num = secs / WEEK_INT;
130                 secs -= num*WEEK_INT;
131                 sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "",
132                         num, (num>1) ? "s" : "");
133                 strcat(buf, tmp);
134         }
135         if (secs >= DAY_INT) {
136                 num = secs / DAY_INT;
137                 secs -= num*DAY_INT;
138                 sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "",
139                         num, (num>1) ? "s" : "");
140                 strcat(buf, tmp);
141         }
142         if (secs > 0) {
143                 hr = secs / HOUR_INT;
144                 secs -= hr*HOUR_INT;
145                 min = secs / MINUTE_INT;
146                 secs -= min*MINUTE_INT;
147                 sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "",
148                         hr, min, secs);
149                 strcat(buf, tmp);
150         }
151         return buf;
152 }
153
154
155 #ifndef EXT2_INODE_SIZE
156 #define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)
157 #endif
158
159 #ifndef EXT2_GOOD_OLD_REV
160 #define EXT2_GOOD_OLD_REV 0
161 #endif
162
163 void list_super (struct ext2_super_block * s)
164 {
165         int inode_blocks_per_group;
166         struct ext2fs_sb *sb = (struct ext2fs_sb *) s;
167         char buf[80];
168         const char *os;
169         time_t  tm;
170
171         inode_blocks_per_group = (((s->s_inodes_per_group *
172                                     EXT2_INODE_SIZE(s)) +
173                                    EXT2_BLOCK_SIZE(s) - 1) /
174                                   EXT2_BLOCK_SIZE(s));
175         if (sb->s_volume_name[0]) {
176                 memset(buf, 0, sizeof(buf));
177                 strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
178         } else
179                 strcpy(buf, "<none>");
180         printf("Filesystem volume name:   %s\n", buf);
181         if (sb->s_last_mounted[0]) {
182                 memset(buf, 0, sizeof(buf));
183                 strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted));
184         } else
185                 strcpy(buf, "<not available>");
186         printf("Last mounted on:          %s\n", buf);
187         if (!e2p_is_null_uuid(sb->s_uuid)) {
188                 e2p_uuid_to_str(sb->s_uuid, buf);
189         } else
190                 strcpy(buf, "<none>");
191         printf("Filesystem UUID:          %s\n", buf);
192         printf ("Filesystem magic number:  0x%04X\n", s->s_magic);
193         printf ("Filesystem revision #:    %d", s->s_rev_level);
194         if (s->s_rev_level == EXT2_GOOD_OLD_REV) {
195                 printf(" (original)\n");
196 #ifdef EXT2_DYNAMIC_REV
197         } else if (s->s_rev_level == EXT2_DYNAMIC_REV) {
198                 printf(" (dynamic)\n");
199 #endif
200         } else
201                 printf("\n");
202 #ifdef EXT2_DYNAMIC_REV
203         printf ("Filesystem features:      ");
204         if (s->s_feature_ro_compat & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
205                 printf("sparse_super");
206         else
207                 printf("(none)");
208         printf("\n");
209 #endif
210         printf ("Filesystem state:        ");
211         print_fs_state (stdout, s->s_state);
212         printf ("\n");
213         printf ("Errors behavior:          ");
214         print_fs_errors (stdout, s->s_errors);
215         printf ("\n");
216         switch (s->s_creator_os) {
217             case EXT2_OS_LINUX: os = "Linux"; break;
218             case EXT2_OS_HURD:  os = "GNU"; break;
219             case EXT2_OS_MASIX: os = "Masix"; break;
220             default:            os = "unknown"; break;
221         }
222         printf("Filesystem OS type:       %s\n", os);
223         printf("Inode count:              %u\n", s->s_inodes_count);
224         printf("Block count:              %u\n", s->s_blocks_count);
225         printf("Reserved block count:     %u\n", s->s_r_blocks_count);
226         printf("Free blocks:              %u\n", s->s_free_blocks_count);
227         printf("Free inodes:              %u\n", s->s_free_inodes_count);
228         printf("First block:              %u\n", s->s_first_data_block);
229         printf("Block size:               %u\n", EXT2_BLOCK_SIZE(s));
230         printf("Fragment size:            %u\n", EXT2_FRAG_SIZE(s));
231         printf("Blocks per group:         %u\n", s->s_blocks_per_group);
232         printf("Fragments per group:      %u\n", s->s_frags_per_group);
233         printf("Inodes per group:         %u\n", s->s_inodes_per_group);
234         printf("Inode blocks per group:   %u\n", inode_blocks_per_group);
235         tm = s->s_mtime;
236         printf("Last mount time:          %s", ctime(&tm));
237         tm = s->s_wtime;
238         printf("Last write time:          %s", ctime(&tm));
239         printf("Mount count:              %u\n", s->s_mnt_count);
240         printf("Maximum mount count:      %d\n", s->s_max_mnt_count);
241         tm = s->s_lastcheck;
242         printf("Last checked:             %s", ctime(&tm));
243         printf("Check interval:           %u (%s)\n", s->s_checkinterval,
244                interval_string(s->s_checkinterval));
245         if (s->s_checkinterval)
246         {
247                 time_t next;
248
249                 next = s->s_lastcheck + s->s_checkinterval;
250                 printf("Next check after:         %s", ctime(&next));
251         }
252 #ifdef  EXT2_DEF_RESUID
253         printf("Reserved blocks uid:      ");
254         print_user(s->s_def_resuid);
255         printf("Reserved blocks gid:      ");
256         print_group(s->s_def_resgid);
257 #endif
258 #ifdef EXT2_DYNAMIC_REV
259         if (s->s_rev_level >= EXT2_DYNAMIC_REV) {
260                 printf("First inode:              %d\n", s->s_first_ino);
261                 printf("Inode size:               %d\n", s->s_inode_size);
262         }
263 #endif
264 }
265
266
267
268