L4Re/departure

libext2fs/lib/libe2p/ls.c

617:2733e5770ee9
9 months ago Paul Boddie Made the run command wait for completion, introducing the spawn command to run programs in the background. Introduced conveniences for waiting for the last job to be initiated and for piping from the last job, also subscribing to signals from pipe-supplying jobs so that they may be transparently removed from the job list upon completion. Augmented the job listing with the "+" notation familiar from Unix. Prevented new jobs from being started when no job slots are available.
     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  * %Begin-Header%    11  * This file may be redistributed under the terms of the GNU Library    12  * General Public License, version 2.    13  * %End-Header%    14  */    15     16 #include "config.h"    17 #include <stdio.h>    18 #include <stdlib.h>    19 #include <sys/types.h>    20 #include <string.h>    21 #include <grp.h>    22 #include <pwd.h>    23 #include <time.h>    24     25 #include "e2p.h"    26 #include "support/quotaio.h"    27     28 static void print_user (unsigned short uid, FILE *f)    29 {    30 	struct passwd *pw;    31     32 	fprintf(f, "%u ", uid);    33 	pw = getpwuid (uid);    34 	if (pw == NULL)    35 		fprintf(f, "(user unknown)\n");    36 	else    37 		fprintf(f, "(user %s)\n", pw->pw_name);    38 }    39     40 static void print_group (unsigned short gid, FILE *f)    41 {    42 	struct group *gr;    43     44 	fprintf(f, "%u ", gid);    45 	gr = getgrgid (gid);    46 	if (gr == NULL)    47 		fprintf(f, "(group unknown)\n");    48 	else    49 		fprintf(f, "(group %s)\n", gr->gr_name);    50 }    51     52 #define MONTH_INT (86400 * 30)    53 #define WEEK_INT (86400 * 7)    54 #define DAY_INT	(86400)    55 #define HOUR_INT (60 * 60)    56 #define MINUTE_INT (60)    57     58 static const char *interval_string(unsigned int secs)    59 {    60 	static char buf[256], tmp[80];    61 	int		hr, min, num;    62     63 	buf[0] = 0;    64     65 	if (secs == 0)    66 		return "<none>";    67     68 	if (secs >= MONTH_INT) {    69 		num = secs / MONTH_INT;    70 		secs -= num*MONTH_INT;    71 		sprintf(buf, "%d month%s", num, (num>1) ? "s" : "");    72 	}    73 	if (secs >= WEEK_INT) {    74 		num = secs / WEEK_INT;    75 		secs -= num*WEEK_INT;    76 		sprintf(tmp, "%s%d week%s", buf[0] ? ", " : "",    77 			num, (num>1) ? "s" : "");    78 		strcat(buf, tmp);    79 	}    80 	if (secs >= DAY_INT) {    81 		num = secs / DAY_INT;    82 		secs -= num*DAY_INT;    83 		sprintf(tmp, "%s%d day%s", buf[0] ? ", " : "",    84 			num, (num>1) ? "s" : "");    85 		strcat(buf, tmp);    86 	}    87 	if (secs > 0) {    88 		hr = secs / HOUR_INT;    89 		secs -= hr*HOUR_INT;    90 		min = secs / MINUTE_INT;    91 		secs -= min*MINUTE_INT;    92 		sprintf(tmp, "%s%d:%02d:%02d", buf[0] ? ", " : "",    93 			hr, min, secs);    94 		strcat(buf, tmp);    95 	}    96 	return buf;    97 }    98     99 static void print_features(struct ext2_super_block * s, FILE *f)   100 {   101 #ifdef EXT2_DYNAMIC_REV   102 	int	i, j, printed=0;   103 	__u32	*mask = &s->s_feature_compat, m;   104    105 	fprintf(f, "Filesystem features:     ");   106 	for (i=0; i <3; i++,mask++) {   107 		for (j=0,m=1; j < 32; j++, m<<=1) {   108 			if (*mask & m) {   109 				fprintf(f, " %s", e2p_feature2string(i, m));   110 				printed++;   111 			}   112 		}   113 	}   114 	if (printed == 0)   115 		fprintf(f, " (none)");   116 	fprintf(f, "\n");   117 #endif   118 }   119    120 static void print_mntopts(struct ext2_super_block * s, FILE *f)   121 {   122 #ifdef EXT2_DYNAMIC_REV   123 	int	i, printed=0;   124 	__u32	mask = s->s_default_mount_opts, m;   125    126 	fprintf(f, "Default mount options:   ");   127 	if (mask & EXT3_DEFM_JMODE) {   128 		fprintf(f, " %s", e2p_mntopt2string(mask & EXT3_DEFM_JMODE));   129 		printed++;   130 	}   131 	for (i=0,m=1; i < 32; i++, m<<=1) {   132 		if (m & EXT3_DEFM_JMODE)   133 			continue;   134 		if (mask & m) {   135 			fprintf(f, " %s", e2p_mntopt2string(m));   136 			printed++;   137 		}   138 	}   139 	if (printed == 0)   140 		fprintf(f, " (none)");   141 	fprintf(f, "\n");   142 #endif   143 }   144    145 static void print_super_flags(struct ext2_super_block * s, FILE *f)   146 {   147 	int	flags_found = 0;   148    149 	if (s->s_flags == 0)   150 		return;   151    152 	fputs("Filesystem flags:         ", f);   153 	if (s->s_flags & EXT2_FLAGS_SIGNED_HASH) {   154 		fputs("signed_directory_hash ", f);   155 		flags_found++;   156 	}   157 	if (s->s_flags & EXT2_FLAGS_UNSIGNED_HASH) {   158 		fputs("unsigned_directory_hash ", f);   159 		flags_found++;   160 	}   161 	if (s->s_flags & EXT2_FLAGS_TEST_FILESYS) {   162 		fputs("test_filesystem ", f);   163 		flags_found++;   164 	}   165 	if (flags_found)   166 		fputs("\n", f);   167 	else   168 		fputs("(none)\n", f);   169 }   170    171 static __u64 e2p_blocks_count(struct ext2_super_block *super)   172 {   173 	return super->s_blocks_count |   174 		(ext2fs_has_feature_64bit(super) ?   175 		(__u64) super->s_blocks_count_hi << 32 : 0);   176 }   177    178 static __u64 e2p_r_blocks_count(struct ext2_super_block *super)   179 {   180 	return super->s_r_blocks_count |   181 		(ext2fs_has_feature_64bit(super) ?   182 		(__u64) super->s_r_blocks_count_hi << 32 : 0);   183 }   184    185 static __u64 e2p_free_blocks_count(struct ext2_super_block *super)   186 {   187 	return super->s_free_blocks_count |   188 		(ext2fs_has_feature_64bit(super) ?   189 		(__u64) super->s_free_blocks_hi << 32 : 0);   190 }   191    192 #ifndef EXT2_INODE_SIZE   193 #define EXT2_INODE_SIZE(s) sizeof(struct ext2_inode)   194 #endif   195    196 #ifndef EXT2_GOOD_OLD_REV   197 #define EXT2_GOOD_OLD_REV 0   198 #endif   199    200 static const char *checksum_type(__u8 type)   201 {   202 	switch (type) {   203 	case EXT2_CRC32C_CHKSUM:   204 		return "crc32c";   205 	default:   206 		return "unknown";   207 	}   208 }   209    210 static const char *quota_prefix[MAXQUOTAS] = {   211 	[USRQUOTA] = "User quota inode:",   212 	[GRPQUOTA] = "Group quota inode:",   213 	[PRJQUOTA] = "Project quota inode:",   214 };   215    216 /**   217  * Convert type of quota to written representation   218  */   219 static const char *quota_type2prefix(enum quota_type qtype)   220 {   221 	return quota_prefix[qtype];   222 }   223    224 void list_super2(struct ext2_super_block * sb, FILE *f)   225 {   226 	int inode_blocks_per_group;   227 	char *str;   228 	time_t	tm;   229 	enum quota_type qtype;   230    231 	inode_blocks_per_group = (((sb->s_inodes_per_group *   232 				    EXT2_INODE_SIZE(sb)) +   233 				   EXT2_BLOCK_SIZE(sb) - 1) /   234 				  EXT2_BLOCK_SIZE(sb));   235 	if (sb->s_volume_name[0])   236 		fprintf(f, "Filesystem volume name:   %.*s\n",   237 			EXT2_LEN_STR(sb->s_volume_name));   238 	else   239 		fprintf(f, "Filesystem volume name:   <none>\n");   240 	if (sb->s_last_mounted[0])   241 		fprintf(f, "Last mounted on:          %.*s\n",   242 			EXT2_LEN_STR(sb->s_last_mounted));   243 	else   244 		fprintf(f, "Last mounted on:          <not available>\n");   245 	fprintf(f, "Filesystem UUID:          %s\n", e2p_uuid2str(sb->s_uuid));   246 	fprintf(f, "Filesystem magic number:  0x%04X\n", sb->s_magic);   247 	fprintf(f, "Filesystem revision #:    %d", sb->s_rev_level);   248 	if (sb->s_rev_level == EXT2_GOOD_OLD_REV) {   249 		fprintf(f, " (original)\n");   250 #ifdef EXT2_DYNAMIC_REV   251 	} else if (sb->s_rev_level == EXT2_DYNAMIC_REV) {   252 		fprintf(f, " (dynamic)\n");   253 #endif   254 	} else   255 		fprintf(f, " (unknown)\n");   256 	print_features(sb, f);   257 	print_super_flags(sb, f);   258 	print_mntopts(sb, f);   259 	if (sb->s_mount_opts[0])   260 		fprintf(f, "Mount options:            %.*s\n",   261 			EXT2_LEN_STR(sb->s_mount_opts));   262 	fprintf(f, "Filesystem state:        ");   263 	print_fs_state (f, sb->s_state);   264 	fprintf(f, "\n");   265 	fprintf(f, "Errors behavior:          ");   266 	print_fs_errors(f, sb->s_errors);   267 	fprintf(f, "\n");   268 	str = e2p_os2string(sb->s_creator_os);   269 	fprintf(f, "Filesystem OS type:       %s\n", str);   270 	free(str);   271 	fprintf(f, "Inode count:              %u\n", sb->s_inodes_count);   272 	fprintf(f, "Block count:              %llu\n",   273 		(unsigned long long) e2p_blocks_count(sb));   274 	fprintf(f, "Reserved block count:     %llu\n",   275 		(unsigned long long) e2p_r_blocks_count(sb));   276 	if (sb->s_overhead_clusters)   277 		fprintf(f, "Overhead clusters:        %u\n",   278 			sb->s_overhead_clusters);   279 	fprintf(f, "Free blocks:              %llu\n",   280 		(unsigned long long) e2p_free_blocks_count(sb));   281 	fprintf(f, "Free inodes:              %u\n", sb->s_free_inodes_count);   282 	fprintf(f, "First block:              %u\n", sb->s_first_data_block);   283 	fprintf(f, "Block size:               %u\n", EXT2_BLOCK_SIZE(sb));   284 	if (ext2fs_has_feature_bigalloc(sb))   285 		fprintf(f, "Cluster size:             %u\n",   286 			EXT2_CLUSTER_SIZE(sb));   287 	else   288 		fprintf(f, "Fragment size:            %u\n",   289 			EXT2_CLUSTER_SIZE(sb));   290 	if (ext2fs_has_feature_64bit(sb))   291 		fprintf(f, "Group descriptor size:    %u\n", sb->s_desc_size);   292 	if (sb->s_reserved_gdt_blocks)   293 		fprintf(f, "Reserved GDT blocks:      %u\n",   294 			sb->s_reserved_gdt_blocks);   295 	fprintf(f, "Blocks per group:         %u\n", sb->s_blocks_per_group);   296 	if (ext2fs_has_feature_bigalloc(sb))   297 		fprintf(f, "Clusters per group:       %u\n",   298 			sb->s_clusters_per_group);   299 	else   300 		fprintf(f, "Fragments per group:      %u\n",   301 			sb->s_clusters_per_group);   302 	fprintf(f, "Inodes per group:         %u\n", sb->s_inodes_per_group);   303 	fprintf(f, "Inode blocks per group:   %u\n", inode_blocks_per_group);   304 	if (sb->s_raid_stride)   305 		fprintf(f, "RAID stride:              %u\n",   306 			sb->s_raid_stride);   307 	if (sb->s_raid_stripe_width)   308 		fprintf(f, "RAID stripe width:        %u\n",   309 			sb->s_raid_stripe_width);   310 	if (sb->s_first_meta_bg)   311 		fprintf(f, "First meta block group:   %u\n",   312 			sb->s_first_meta_bg);   313 	if (sb->s_log_groups_per_flex)   314 		fprintf(f, "Flex block group size:    %u\n",   315 			1 << sb->s_log_groups_per_flex);   316 	if (sb->s_mkfs_time) {   317 		tm = sb->s_mkfs_time;   318 		fprintf(f, "Filesystem created:       %s", ctime(&tm));   319 	}   320 	tm = sb->s_mtime;   321 	fprintf(f, "Last mount time:          %s",   322 		sb->s_mtime ? ctime(&tm) : "n/a\n");   323 	tm = sb->s_wtime;   324 	fprintf(f, "Last write time:          %s", ctime(&tm));   325 	fprintf(f, "Mount count:              %u\n", sb->s_mnt_count);   326 	fprintf(f, "Maximum mount count:      %d\n", sb->s_max_mnt_count);   327 	tm = sb->s_lastcheck;   328 	fprintf(f, "Last checked:             %s", ctime(&tm));   329 	fprintf(f, "Check interval:           %u (%s)\n", sb->s_checkinterval,   330 	       interval_string(sb->s_checkinterval));   331 	if (sb->s_checkinterval)   332 	{   333 		time_t next;   334    335 		next = sb->s_lastcheck + sb->s_checkinterval;   336 		fprintf(f, "Next check after:         %s", ctime(&next));   337 	}   338 #define POW2(x) ((__u64) 1 << (x))   339 	if (sb->s_kbytes_written) {   340 		fprintf(f, "Lifetime writes:          ");   341 		if (sb->s_kbytes_written < POW2(13))   342 			fprintf(f, "%llu kB\n",   343 				(unsigned long long) sb->s_kbytes_written);   344 		else if (sb->s_kbytes_written < POW2(23))   345 		  fprintf(f, "%llu MB\n", (unsigned long long)   346 			  (sb->s_kbytes_written + POW2(9)) >> 10);   347 		else if (sb->s_kbytes_written < POW2(33))   348 		  fprintf(f, "%llu GB\n", (unsigned long long)   349 				(sb->s_kbytes_written + POW2(19)) >> 20);   350 		else if (sb->s_kbytes_written < POW2(43))   351 			fprintf(f, "%llu TB\n", (unsigned long long)   352 				(sb->s_kbytes_written + POW2(29)) >> 30);   353 		else   354 			fprintf(f, "%llu PB\n", (unsigned long long)   355 				(sb->s_kbytes_written + POW2(39)) >> 40);   356 	}   357 	fprintf(f, "Reserved blocks uid:      ");   358 	print_user(sb->s_def_resuid, f);   359 	fprintf(f, "Reserved blocks gid:      ");   360 	print_group(sb->s_def_resgid, f);   361 	if (sb->s_rev_level >= EXT2_DYNAMIC_REV) {   362 		fprintf(f, "First inode:              %d\n", sb->s_first_ino);   363 		fprintf(f, "Inode size:	          %d\n", sb->s_inode_size);   364 		if (sb->s_min_extra_isize)   365 			fprintf(f, "Required extra isize:     %d\n",   366 				sb->s_min_extra_isize);   367 		if (sb->s_want_extra_isize)   368 			fprintf(f, "Desired extra isize:      %d\n",   369 				sb->s_want_extra_isize);   370 	}   371 	if (!e2p_is_null_uuid(sb->s_journal_uuid))   372 		fprintf(f, "Journal UUID:             %s\n",   373 			e2p_uuid2str(sb->s_journal_uuid));   374 	if (sb->s_journal_inum)   375 		fprintf(f, "Journal inode:            %u\n",   376 			sb->s_journal_inum);   377 	if (sb->s_journal_dev)   378 		fprintf(f, "Journal device:	          0x%04x\n",   379 			sb->s_journal_dev);   380 	if (sb->s_last_orphan)   381 		fprintf(f, "First orphan inode:       %u\n",   382 			sb->s_last_orphan);   383 	if (ext2fs_has_feature_dir_index(sb) ||   384 	    sb->s_def_hash_version)   385 		fprintf(f, "Default directory hash:   %s\n",   386 			e2p_hash2string(sb->s_def_hash_version));   387 	if (!e2p_is_null_uuid(sb->s_hash_seed))   388 		fprintf(f, "Directory Hash Seed:      %s\n",   389 			e2p_uuid2str(sb->s_hash_seed));   390 	if (sb->s_jnl_backup_type) {   391 		fprintf(f, "Journal backup:           ");   392 		switch (sb->s_jnl_backup_type) {   393 		case 1:   394 			fprintf(f, "inode blocks\n");   395 			break;   396 		default:   397 			fprintf(f, "type %u\n", sb->s_jnl_backup_type);   398 		}   399 	}   400 	if (sb->s_backup_bgs[0] || sb->s_backup_bgs[1]) {   401 		fprintf(f, "Backup block groups:      ");   402 		if (sb->s_backup_bgs[0])   403 			fprintf(f, "%u ", sb->s_backup_bgs[0]);   404 		if (sb->s_backup_bgs[1])   405 			fprintf(f, "%u ", sb->s_backup_bgs[1]);   406 		fputc('\n', f);   407 	}   408 	if (sb->s_snapshot_inum) {   409 		fprintf(f, "Snapshot inode:           %u\n",   410 			sb->s_snapshot_inum);   411 		fprintf(f, "Snapshot ID:              %u\n",   412 			sb->s_snapshot_id);   413 		fprintf(f, "Snapshot reserved blocks: %llu\n",   414 			(unsigned long long) sb->s_snapshot_r_blocks_count);   415 	}   416 	if (sb->s_snapshot_list)   417 		fprintf(f, "Snapshot list head:       %u\n",   418 			sb->s_snapshot_list);   419 	if (sb->s_error_count)   420 		fprintf(f, "FS Error count:           %u\n",   421 			sb->s_error_count);   422 	if (sb->s_first_error_time) {   423 		tm = sb->s_first_error_time;   424 		fprintf(f, "First error time:         %s", ctime(&tm));   425 		fprintf(f, "First error function:     %.*s\n",   426 			EXT2_LEN_STR(sb->s_first_error_func));   427 		fprintf(f, "First error line #:       %u\n",   428 			sb->s_first_error_line);   429 		if (sb->s_first_error_ino)   430 			fprintf(f, "First error inode #:      %u\n",   431 				sb->s_first_error_ino);   432 		if (sb->s_first_error_block)   433 			fprintf(f, "First error block #:      %llu\n",   434 				(unsigned long long) sb->s_first_error_block);   435 		if (sb->s_first_error_errcode)   436 			fprintf(f, "First error err:          %s\n",   437 				e2p_errcode2str(sb->s_first_error_errcode));   438 	}   439 	if (sb->s_last_error_time) {   440 		tm = sb->s_last_error_time;   441 		fprintf(f, "Last error time:          %s", ctime(&tm));   442 		fprintf(f, "Last error function:      %.*s\n",   443 			EXT2_LEN_STR(sb->s_last_error_func));   444 		fprintf(f, "Last error line #:        %u\n",   445 			sb->s_last_error_line);   446 		if (sb->s_last_error_ino)   447 			fprintf(f, "Last error inode #:       %u\n",   448 				sb->s_last_error_ino);   449 		if (sb->s_last_error_block)   450 			fprintf(f, "Last error block #:       %llu\n",   451 				(unsigned long long) sb->s_last_error_block);   452 		if (sb->s_last_error_errcode)   453 			fprintf(f, "Last error err:           %s\n",   454 				e2p_errcode2str(sb->s_last_error_errcode));   455 	}   456 	if (ext2fs_has_feature_mmp(sb)) {   457 		fprintf(f, "MMP block number:         %llu\n",   458 			(unsigned long long) sb->s_mmp_block);   459 		fprintf(f, "MMP update interval:      %u\n",   460 			sb->s_mmp_update_interval);   461 	}   462 	for (qtype = 0; qtype < MAXQUOTAS; qtype++) {   463 		if (*quota_sb_inump(sb, qtype) != 0)   464 			fprintf(f, "%-26s%u\n",   465 				quota_type2prefix(qtype),   466 				*quota_sb_inump(sb, qtype));   467 	}   468    469 	if (ext2fs_has_feature_metadata_csum(sb)) {   470 		fprintf(f, "Checksum type:            %s\n",   471 			checksum_type(sb->s_checksum_type));   472 		fprintf(f, "Checksum:                 0x%08x\n",   473 			sb->s_checksum);   474 	}   475 	if (!e2p_is_null_uuid(sb->s_encrypt_pw_salt))   476 		fprintf(f, "Encryption PW Salt:       %s\n",   477 			e2p_uuid2str(sb->s_encrypt_pw_salt));   478    479 	if (ext2fs_has_feature_csum_seed(sb))   480 		fprintf(f, "Checksum seed:            0x%08x\n",   481 			sb->s_checksum_seed);   482 	if (ext2fs_has_feature_casefold(sb))   483 		fprintf(f, "Character encoding:       %s\n",   484 			e2p_encoding2str(sb->s_encoding));   485 }   486    487 void list_super (struct ext2_super_block * s)   488 {   489 	list_super2(s, stdout);   490 }   491