aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2005-04-24 05:07:59 +0000
committerMike Frysinger <vapier@gentoo.org>2005-04-24 05:07:59 +0000
commitd89e629e52c3b525424be958de238ed1dc5a0361 (patch)
tree9aec1ca3d0a479bef39bd63c14f4292061d34675
parent408ae211ceaf33bf758207cd5329903c39e8880c (diff)
downloadbusybox-w32-d89e629e52c3b525424be958de238ed1dc5a0361.tar.gz
busybox-w32-d89e629e52c3b525424be958de238ed1dc5a0361.tar.bz2
busybox-w32-d89e629e52c3b525424be958de238ed1dc5a0361.zip
add new subdir for e2fsprogs
-rw-r--r--Makefile2
-rw-r--r--e2fsprogs/README3
-rw-r--r--e2fsprogs/chattr.c305
-rw-r--r--e2fsprogs/e2fsbb.h38
-rw-r--r--e2fsprogs/e2p/README4
-rw-r--r--e2fsprogs/e2p/e2p.h52
-rw-r--r--e2fsprogs/e2p/feature.c190
-rw-r--r--e2fsprogs/e2p/fgetflags.c92
-rw-r--r--e2fsprogs/e2p/fgetversion.c62
-rw-r--r--e2fsprogs/e2p/fsetflags.c96
-rw-r--r--e2fsprogs/e2p/fsetversion.c60
-rw-r--r--e2fsprogs/e2p/getflags.c66
-rw-r--r--e2fsprogs/e2p/getversion.c37
-rw-r--r--e2fsprogs/e2p/hashstr.c70
-rw-r--r--e2fsprogs/e2p/iod.c72
-rw-r--r--e2fsprogs/e2p/ls.c276
-rw-r--r--e2fsprogs/e2p/mntopts.c136
-rw-r--r--e2fsprogs/e2p/ostype.c73
-rw-r--r--e2fsprogs/e2p/parse_num.c64
-rw-r--r--e2fsprogs/e2p/pe.c37
-rw-r--r--e2fsprogs/e2p/pf.c74
-rw-r--r--e2fsprogs/e2p/ps.c29
-rw-r--r--e2fsprogs/e2p/setflags.c72
-rw-r--r--e2fsprogs/e2p/setversion.c36
-rw-r--r--e2fsprogs/e2p/uuid.c79
-rw-r--r--e2fsprogs/lsattr.c193
-rw-r--r--sysdeps/linux/Config.in2
27 files changed, 2218 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index ecbfcec5e..b1e934754 100644
--- a/Makefile
+++ b/Makefile
@@ -42,7 +42,7 @@ include $(top_builddir)/Rules.mak
42DIRS:=applets archival archival/libunarchive coreutils console-tools \ 42DIRS:=applets archival archival/libunarchive coreutils console-tools \
43 debianutils editors findutils init miscutils modutils networking \ 43 debianutils editors findutils init miscutils modutils networking \
44 networking/libiproute networking/udhcp procps loginutils shell \ 44 networking/libiproute networking/udhcp procps loginutils shell \
45 sysklogd util-linux libpwdgrp coreutils/libcoreutils libbb 45 sysklogd util-linux e2fsprogs libpwdgrp coreutils/libcoreutils libbb
46 46
47SRC_DIRS:=$(patsubst %,$(top_srcdir)/%,$(DIRS)) 47SRC_DIRS:=$(patsubst %,$(top_srcdir)/%,$(DIRS))
48 48
diff --git a/e2fsprogs/README b/e2fsprogs/README
new file mode 100644
index 000000000..fac090193
--- /dev/null
+++ b/e2fsprogs/README
@@ -0,0 +1,3 @@
1This is a pretty straight rip from the e2fsprogs pkg.
2
3See README's in subdirs for specific info.
diff --git a/e2fsprogs/chattr.c b/e2fsprogs/chattr.c
new file mode 100644
index 000000000..7abc83176
--- /dev/null
+++ b/e2fsprogs/chattr.c
@@ -0,0 +1,305 @@
1/*
2 * chattr.c - Change file attributes on an ext2 file system
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
15 * 93/11/13 - Replace stat() calls by lstat() to avoid loops
16 * 94/02/27 - Integrated in Ted's distribution
17 * 98/12/29 - Ignore symlinks when working recursively (G M Sipe)
18 * 98/12/29 - Display version info only when -V specified (G M Sipe)
19 */
20
21#include <sys/types.h>
22#include <dirent.h>
23#include <fcntl.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <unistd.h>
27#include <string.h>
28#include <errno.h>
29#include <sys/param.h>
30#include <sys/stat.h>
31#include <ext2fs/ext2_fs.h>
32
33#ifdef __GNUC__
34#define EXT2FS_ATTR(x) __attribute__(x)
35#else
36#define EXT2FS_ATTR(x)
37#endif
38
39#ifndef S_ISLNK /* So we can compile even with gcc-warn */
40# ifdef __S_IFLNK
41# define S_ISLNK(mode) __S_ISTYPE((mode), __S_IFLNK)
42# else
43# define S_ISLNK(mode) 0
44# endif
45#endif
46
47#include "e2fsbb.h"
48#include "e2p/e2p.h"
49
50static int add;
51static int rem;
52static int set;
53static int set_version;
54
55static unsigned long version;
56
57static int recursive;
58static int verbose;
59
60static unsigned long af;
61static unsigned long rf;
62static unsigned long sf;
63
64#ifdef _LFS64_LARGEFILE
65#define LSTAT lstat64
66#define STRUCT_STAT struct stat64
67#else
68#define LSTAT lstat
69#define STRUCT_STAT struct stat
70#endif
71
72#if 0
73static void fatal_error(const char * fmt_string, int errcode)
74{
75 fprintf (stderr, fmt_string, program_name);
76 exit (errcode);
77}
78
79#define usage() fatal_error(_("usage: %s [-RV] [-+=AacDdijsSu] [-v version] files...\n"), \
80 1)
81#endif
82
83struct flags_char {
84 unsigned long flag;
85 char optchar;
86};
87
88static const struct flags_char flags_array[] = {
89 { EXT2_NOATIME_FL, 'A' },
90 { EXT2_SYNC_FL, 'S' },
91 { EXT2_DIRSYNC_FL, 'D' },
92 { EXT2_APPEND_FL, 'a' },
93 { EXT2_COMPR_FL, 'c' },
94 { EXT2_NODUMP_FL, 'd' },
95 { EXT2_IMMUTABLE_FL, 'i' },
96 { EXT3_JOURNAL_DATA_FL, 'j' },
97 { EXT2_SECRM_FL, 's' },
98 { EXT2_UNRM_FL, 'u' },
99 { EXT2_NOTAIL_FL, 't' },
100 { EXT2_TOPDIR_FL, 'T' },
101 { 0, 0 }
102};
103
104static unsigned long get_flag(char c)
105{
106 const struct flags_char *fp;
107
108 for (fp = flags_array; fp->flag != 0; fp++) {
109 if (fp->optchar == c)
110 return fp->flag;
111 }
112 return 0;
113}
114
115
116static int decode_arg (int * i, int argc, char ** argv)
117{
118 char * p;
119 char * tmp;
120 unsigned long fl;
121
122 switch (argv[*i][0])
123 {
124 case '-':
125 for (p = &argv[*i][1]; *p; p++) {
126 if (*p == 'R') {
127 recursive = 1;
128 continue;
129 }
130 if (*p == 'V') {
131 verbose = 1;
132 continue;
133 }
134 if (*p == 'v') {
135 (*i)++;
136 if (*i >= argc)
137 usage ();
138 version = strtol (argv[*i], &tmp, 0);
139 if (*tmp) {
140 com_err (program_name, 0,
141 _("bad version - %s\n"),
142 argv[*i]);
143 usage ();
144 }
145 set_version = 1;
146 continue;
147 }
148 if ((fl = get_flag(*p)) == 0)
149 usage();
150 rf |= fl;
151 rem = 1;
152 }
153 break;
154 case '+':
155 add = 1;
156 for (p = &argv[*i][1]; *p; p++) {
157 if ((fl = get_flag(*p)) == 0)
158 usage();
159 af |= fl;
160 }
161 break;
162 case '=':
163 set = 1;
164 for (p = &argv[*i][1]; *p; p++) {
165 if ((fl = get_flag(*p)) == 0)
166 usage();
167 sf |= fl;
168 }
169 break;
170 default:
171 return EOF;
172 break;
173 }
174 return 1;
175}
176
177static int chattr_dir_proc (const char *, struct dirent *, void *);
178
179static void change_attributes (const char * name)
180{
181 unsigned long flags;
182 STRUCT_STAT st;
183
184 if (LSTAT (name, &st) == -1) {
185 com_err (program_name, errno, _("while trying to stat %s"),
186 name);
187 return;
188 }
189 if (S_ISLNK(st.st_mode) && recursive)
190 return;
191
192 /* Don't try to open device files, fifos etc. We probably
193 ought to display an error if the file was explicitly given
194 on the command line (whether or not recursive was
195 requested). */
196 if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) &&
197 !S_ISDIR(st.st_mode))
198 return;
199
200 if (set) {
201 if (verbose) {
202 printf (_("Flags of %s set as "), name);
203 print_flags (stdout, sf, 0);
204 printf ("\n");
205 }
206 if (fsetflags (name, sf) == -1)
207 perror (name);
208 } else {
209 if (fgetflags (name, &flags) == -1)
210 com_err (program_name, errno,
211 _("while reading flags on %s"), name);
212 else {
213 if (rem)
214 flags &= ~rf;
215 if (add)
216 flags |= af;
217 if (verbose) {
218 printf (_("Flags of %s set as "), name);
219 print_flags (stdout, flags, 0);
220 printf ("\n");
221 }
222 if (!S_ISDIR(st.st_mode))
223 flags &= ~EXT2_DIRSYNC_FL;
224 if (fsetflags (name, flags) == -1)
225 com_err (program_name, errno,
226 _("while setting flags on %s"), name);
227 }
228 }
229 if (set_version) {
230 if (verbose)
231 printf (_("Version of %s set as %lu\n"), name, version);
232 if (fsetversion (name, version) == -1)
233 com_err (program_name, errno,
234 _("while setting version on %s"), name);
235 }
236 if (S_ISDIR(st.st_mode) && recursive)
237 iterate_on_dir (name, chattr_dir_proc, NULL);
238}
239
240static int chattr_dir_proc (const char * dir_name, struct dirent * de,
241 void * private EXT2FS_ATTR((unused)))
242{
243 if (strcmp (de->d_name, ".") && strcmp (de->d_name, "..")) {
244 char *path;
245
246 path = malloc(strlen (dir_name) + 1 + strlen (de->d_name) + 1);
247 if (!path)
248 fatal_error(_("Couldn't allocate path variable "
249 "in chattr_dir_proc"), 1);
250 sprintf (path, "%s/%s", dir_name, de->d_name);
251 change_attributes (path);
252 free(path);
253 }
254 return 0;
255}
256
257int chattr_main (int argc, char ** argv)
258{
259 int i, j;
260 int end_arg = 0;
261
262#ifdef ENABLE_NLS
263 setlocale(LC_MESSAGES, "");
264 setlocale(LC_CTYPE, "");
265 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
266 textdomain(NLS_CAT_NAME);
267#endif
268#if 0
269 if (argc && *argv)
270 program_name = *argv;
271#endif
272 i = 1;
273 while (i < argc && !end_arg) {
274 /* '--' arg should end option processing */
275 if (strcmp(argv[i], "--") == 0) {
276 i++;
277 end_arg = 1;
278 } else if (decode_arg (&i, argc, argv) == EOF)
279 end_arg = 1;
280 else
281 i++;
282 }
283 if (i >= argc)
284 usage ();
285 if (set && (add || rem)) {
286 fputs(_("= is incompatible with - and +\n"), stderr);
287 exit (1);
288 }
289 if ((rf & af) != 0) {
290 fputs("Can't both set and unset same flag.\n", stderr);
291 exit (1);
292 }
293 if (!(add || rem || set || set_version)) {
294 fputs(_("Must use '-v', =, - or +\n"), stderr);
295 exit (1);
296 }
297#if 0
298 if (verbose)
299 fprintf (stderr, "chattr %s (%s)\n",
300 E2FSPROGS_VERSION, E2FSPROGS_DATE);
301#endif
302 for (j = i; j < argc; j++)
303 change_attributes (argv[j]);
304 exit(0);
305}
diff --git a/e2fsprogs/e2fsbb.h b/e2fsprogs/e2fsbb.h
new file mode 100644
index 000000000..358cfe099
--- /dev/null
+++ b/e2fsprogs/e2fsbb.h
@@ -0,0 +1,38 @@
1/*
2 * File: e2fsbb.h
3 *
4 * Redefine a bunch of e2fsprogs stuff to use busybox routines
5 * instead. This makes upgrade between e2fsprogs versions easy.
6 */
7
8#ifndef __E2FSBB_H__
9#define __E2FSBB_H__ 1
10
11#include "libbb.h"
12
13/* version we've last synced against */
14#define E2FSPROGS_VERSION "1.37"
15#define E2FSPROGS_DATE "21-Mar-2005"
16
17/* make sure com_err.h isnt included before us */
18#ifdef __COM_ERR_H__
19#error You should not have included com_err.h !
20#endif
21#define __COM_ERR_H__
22
23/* com_err crap */
24#define com_err(w, c, fmt, args...) bb_error_msg(fmt, ## args)
25typedef long errcode_t;
26#define ERRCODE_RANGE 8
27#define error_message(code) strerror((int) (code & ((1<<ERRCODE_RANGE)-1)))
28
29/* NLS crap */
30#define _(x) x
31
32/* misc crap */
33#define fputs(msg, fd) bb_error_msg(msg)
34#define fatal_error(msg, err) bb_error_msg_and_die(msg)
35#define usage() bb_show_usage()
36#define perror(msg) bb_perror_msg(msg)
37
38#endif /* __E2FSBB_H__ */
diff --git a/e2fsprogs/e2p/README b/e2fsprogs/e2p/README
new file mode 100644
index 000000000..769947340
--- /dev/null
+++ b/e2fsprogs/e2p/README
@@ -0,0 +1,4 @@
1Simply copy the 'e2p' dir from e2fsprogs/lib/ and then delete the extra
2files we don't need (Makefile.in, e2p.pc.in, etc...). Remove all of the
3_LARGEFILE* define's from the few source files that use it since we'll be
4appending it ourselves to CFLAGS when we compile. All done ! :)
diff --git a/e2fsprogs/e2p/e2p.h b/e2fsprogs/e2p/e2p.h
new file mode 100644
index 000000000..d208b46a8
--- /dev/null
+++ b/e2fsprogs/e2p/e2p.h
@@ -0,0 +1,52 @@
1#include <sys/types.h> /* Needed by dirent.h on netbsd */
2#include <stdio.h>
3#include <dirent.h>
4
5#include <ext2fs/ext2_fs.h>
6
7#define E2P_FEATURE_COMPAT 0
8#define E2P_FEATURE_INCOMPAT 1
9#define E2P_FEATURE_RO_INCOMPAT 2
10
11
12/* `options' for print_flags() */
13
14#define PFOPT_LONG 1 /* Must be 1 for compatibility with `int long_format'. */
15
16
17int fgetflags (const char * name, unsigned long * flags);
18int fgetversion (const char * name, unsigned long * version);
19int fsetflags (const char * name, unsigned long flags);
20int fsetversion (const char * name, unsigned long version);
21int getflags (int fd, unsigned long * flags);
22int getversion (int fd, unsigned long * version);
23int iterate_on_dir (const char * dir_name,
24 int (*func) (const char *, struct dirent *, void *),
25 void * private);
26void list_super(struct ext2_super_block * s);
27void list_super2(struct ext2_super_block * s, FILE *f);
28void print_fs_errors (FILE * f, unsigned short errors);
29void print_flags (FILE * f, unsigned long flags, unsigned options);
30void print_fs_state (FILE * f, unsigned short state);
31int setflags (int fd, unsigned long flags);
32int setversion (int fd, unsigned long version);
33
34const char *e2p_feature2string(int compat, unsigned int mask);
35int e2p_string2feature(char *string, int *compat, unsigned int *mask);
36int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array);
37
38int e2p_is_null_uuid(void *uu);
39void e2p_uuid_to_str(void *uu, char *out);
40const char *e2p_uuid2str(void *uu);
41
42const char *e2p_hash2string(int num);
43int e2p_string2hash(char *string);
44
45const char *e2p_mntopt2string(unsigned int mask);
46int e2p_string2mntopt(char *string, unsigned int *mask);
47int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok);
48
49unsigned long parse_num_blocks(const char *arg, int log_block_size);
50
51char *e2p_os2string(int os_type);
52int e2p_string2os(char *str);
diff --git a/e2fsprogs/e2p/feature.c b/e2fsprogs/e2p/feature.c
new file mode 100644
index 000000000..ef11d93b7
--- /dev/null
+++ b/e2fsprogs/e2p/feature.c
@@ -0,0 +1,190 @@
1/*
2 * feature.c --- convert between features and strings
3 *
4 * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
5 *
6 * This file can be redistributed under the terms of the GNU Library General
7 * Public License
8 *
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <ctype.h>
15#include <errno.h>
16
17#include "e2p.h"
18
19struct feature {
20 int compat;
21 unsigned int mask;
22 const char *string;
23};
24
25static struct feature feature_list[] = {
26 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_PREALLOC,
27 "dir_prealloc" },
28 { E2P_FEATURE_COMPAT, EXT3_FEATURE_COMPAT_HAS_JOURNAL,
29 "has_journal" },
30 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_IMAGIC_INODES,
31 "imagic_inodes" },
32 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_EXT_ATTR,
33 "ext_attr" },
34 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_DIR_INDEX,
35 "dir_index" },
36 { E2P_FEATURE_COMPAT, EXT2_FEATURE_COMPAT_RESIZE_INODE,
37 "resize_inode" },
38 { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER,
39 "sparse_super" },
40 { E2P_FEATURE_RO_INCOMPAT, EXT2_FEATURE_RO_COMPAT_LARGE_FILE,
41 "large_file" },
42 { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_COMPRESSION,
43 "compression" },
44 { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_FILETYPE,
45 "filetype" },
46 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_RECOVER,
47 "needs_recovery" },
48 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_JOURNAL_DEV,
49 "journal_dev" },
50 { E2P_FEATURE_INCOMPAT, EXT3_FEATURE_INCOMPAT_EXTENTS,
51 "extents" },
52 { E2P_FEATURE_INCOMPAT, EXT2_FEATURE_INCOMPAT_META_BG,
53 "meta_bg" },
54 { 0, 0, 0 },
55};
56
57const char *e2p_feature2string(int compat, unsigned int mask)
58{
59 struct feature *f;
60 static char buf[20];
61 char fchar;
62 int fnum;
63
64 for (f = feature_list; f->string; f++) {
65 if ((compat == f->compat) &&
66 (mask == f->mask))
67 return f->string;
68 }
69 switch (compat) {
70 case E2P_FEATURE_COMPAT:
71 fchar = 'C';
72 break;
73 case E2P_FEATURE_INCOMPAT:
74 fchar = 'I';
75 break;
76 case E2P_FEATURE_RO_INCOMPAT:
77 fchar = 'R';
78 break;
79 default:
80 fchar = '?';
81 break;
82 }
83 for (fnum = 0; mask >>= 1; fnum++);
84 sprintf(buf, "FEATURE_%c%d", fchar, fnum);
85 return buf;
86}
87
88int e2p_string2feature(char *string, int *compat_type, unsigned int *mask)
89{
90 struct feature *f;
91 char *eptr;
92 int num;
93
94 for (f = feature_list; f->string; f++) {
95 if (!strcasecmp(string, f->string)) {
96 *compat_type = f->compat;
97 *mask = f->mask;
98 return 0;
99 }
100 }
101 if (strncasecmp(string, "FEATURE_", 8))
102 return 1;
103
104 switch (string[8]) {
105 case 'c':
106 case 'C':
107 *compat_type = E2P_FEATURE_COMPAT;
108 break;
109 case 'i':
110 case 'I':
111 *compat_type = E2P_FEATURE_INCOMPAT;
112 break;
113 case 'r':
114 case 'R':
115 *compat_type = E2P_FEATURE_RO_INCOMPAT;
116 break;
117 default:
118 return 1;
119 }
120 if (string[9] == 0)
121 return 1;
122 num = strtol(string+9, &eptr, 10);
123 if (num > 32 || num < 0)
124 return 1;
125 if (*eptr)
126 return 1;
127 *mask = 1 << num;
128 return 0;
129}
130
131static char *skip_over_blanks(char *cp)
132{
133 while (*cp && isspace(*cp))
134 cp++;
135 return cp;
136}
137
138static char *skip_over_word(char *cp)
139{
140 while (*cp && !isspace(*cp) && *cp != ',')
141 cp++;
142 return cp;
143}
144
145/*
146 * Edit a feature set array as requested by the user. The ok_array,
147 * if set, allows the application to limit what features the user is
148 * allowed to set or clear using this function.
149 */
150int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array)
151{
152 char *cp, *buf, *next;
153 int neg;
154 unsigned int mask;
155 int compat_type;
156
157 buf = malloc(strlen(str)+1);
158 if (!buf)
159 return 1;
160 strcpy(buf, str);
161 cp = buf;
162 while (cp && *cp) {
163 neg = 0;
164 cp = skip_over_blanks(cp);
165 next = skip_over_word(cp);
166 if (*next == 0)
167 next = 0;
168 else
169 *next = 0;
170 switch (*cp) {
171 case '-':
172 case '^':
173 neg++;
174 case '+':
175 cp++;
176 break;
177 }
178 if (e2p_string2feature(cp, &compat_type, &mask))
179 return 1;
180 if (ok_array && !(ok_array[compat_type] & mask))
181 return 1;
182 if (neg)
183 compat_array[compat_type] &= ~mask;
184 else
185 compat_array[compat_type] |= mask;
186 cp = next ? next+1 : 0;
187 }
188 return 0;
189}
190
diff --git a/e2fsprogs/e2p/fgetflags.c b/e2fsprogs/e2p/fgetflags.c
new file mode 100644
index 000000000..6db729e08
--- /dev/null
+++ b/e2fsprogs/e2p/fgetflags.c
@@ -0,0 +1,92 @@
1/*
2 * fgetflags.c - Get a file flags on an ext2 file system
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU Library General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
15 */
16
17#if HAVE_ERRNO_H
18#include <errno.h>
19#endif
20#if HAVE_UNISTD_H
21#include <unistd.h>
22#endif
23#include <sys/types.h>
24#include <sys/stat.h>
25#if HAVE_EXT2_IOCTLS
26#include <fcntl.h>
27#include <sys/ioctl.h>
28#endif
29
30#include "e2p.h"
31
32#ifdef O_LARGEFILE
33#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
34#else
35#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
36#endif
37
38int fgetflags (const char * name, unsigned long * flags)
39{
40 struct stat buf;
41#if HAVE_STAT_FLAGS && !(APPLE_DARWIN && HAVE_EXT2_IOCTLS)
42
43 if (stat (name, &buf) == -1)
44 return -1;
45
46 *flags = 0;
47#ifdef UF_IMMUTABLE
48 if (buf.st_flags & UF_IMMUTABLE)
49 *flags |= EXT2_IMMUTABLE_FL;
50#endif
51#ifdef UF_APPEND
52 if (buf.st_flags & UF_APPEND)
53 *flags |= EXT2_APPEND_FL;
54#endif
55#ifdef UF_NODUMP
56 if (buf.st_flags & UF_NODUMP)
57 *flags |= EXT2_NODUMP_FL;
58#endif
59
60 return 0;
61#else
62#if HAVE_EXT2_IOCTLS
63 int fd, r, f, save_errno = 0;
64
65 if (!stat(name, &buf) &&
66 !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
67 goto notsupp;
68 }
69#if !APPLE_DARWIN
70 fd = open (name, OPEN_FLAGS);
71 if (fd == -1)
72 return -1;
73 r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
74 if (r == -1)
75 save_errno = errno;
76 *flags = f;
77 close (fd);
78 if (save_errno)
79 errno = save_errno;
80 return r;
81#else
82 f = -1;
83 save_errno = syscall(SYS_fsctl, name, EXT2_IOC_GETFLAGS, &f, 0);
84 *flags = f;
85 return (save_errno);
86#endif
87#endif /* HAVE_EXT2_IOCTLS */
88#endif
89notsupp:
90 errno = EOPNOTSUPP;
91 return -1;
92}
diff --git a/e2fsprogs/e2p/fgetversion.c b/e2fsprogs/e2p/fgetversion.c
new file mode 100644
index 000000000..351a7d5d0
--- /dev/null
+++ b/e2fsprogs/e2p/fgetversion.c
@@ -0,0 +1,62 @@
1/*
2 * fgetversion.c - Get a file version on an ext2 file system
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU Library General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
15 */
16
17#if HAVE_ERRNO_H
18#include <errno.h>
19#endif
20#if HAVE_UNISTD_H
21#include <unistd.h>
22#endif
23#include <fcntl.h>
24#include <sys/ioctl.h>
25
26#include "e2p.h"
27
28#ifdef O_LARGEFILE
29#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
30#else
31#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
32#endif
33
34int fgetversion (const char * name, unsigned long * version)
35{
36#if HAVE_EXT2_IOCTLS
37#if !APPLE_DARWIN
38 int fd, r, ver, save_errno = 0;
39
40 fd = open (name, OPEN_FLAGS);
41 if (fd == -1)
42 return -1;
43 r = ioctl (fd, EXT2_IOC_GETVERSION, &ver);
44 if (r == -1)
45 save_errno = errno;
46 *version = ver;
47 close (fd);
48 if (save_errno)
49 errno = save_errno;
50 return r;
51#else
52 int ver=-1, err;
53 err = syscall(SYS_fsctl, name, EXT2_IOC_GETVERSION, &ver, 0);
54 *version = ver;
55 return(err);
56#endif
57#else /* ! HAVE_EXT2_IOCTLS */
58 extern int errno;
59 errno = EOPNOTSUPP;
60 return -1;
61#endif /* ! HAVE_EXT2_IOCTLS */
62}
diff --git a/e2fsprogs/e2p/fsetflags.c b/e2fsprogs/e2p/fsetflags.c
new file mode 100644
index 000000000..40e7292dd
--- /dev/null
+++ b/e2fsprogs/e2p/fsetflags.c
@@ -0,0 +1,96 @@
1/*
2 * fsetflags.c - Set a file flags on an ext2 file system
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU Library General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
15 */
16
17#if HAVE_ERRNO_H
18#include <errno.h>
19#endif
20#if HAVE_UNISTD_H
21#include <unistd.h>
22#endif
23#include <sys/types.h>
24#include <sys/stat.h>
25#if HAVE_EXT2_IOCTLS
26#include <fcntl.h>
27#include <sys/ioctl.h>
28#endif
29
30#include "e2p.h"
31
32/*
33 * Deal with lame glibc's that define this function without actually
34 * implementing it. Can you say "attractive nuisance", boys and girls?
35 * I knew you could!
36 */
37#ifdef __linux__
38#undef HAVE_CHFLAGS
39#endif
40
41#ifdef O_LARGEFILE
42#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
43#else
44#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
45#endif
46
47int fsetflags (const char * name, unsigned long flags)
48{
49 struct stat buf;
50#if HAVE_CHFLAGS && !(APPLE_DARWIN && HAVE_EXT2_IOCTLS)
51 unsigned long bsd_flags = 0;
52
53#ifdef UF_IMMUTABLE
54 if (flags & EXT2_IMMUTABLE_FL)
55 bsd_flags |= UF_IMMUTABLE;
56#endif
57#ifdef UF_APPEND
58 if (flags & EXT2_APPEND_FL)
59 bsd_flags |= UF_APPEND;
60#endif
61#ifdef UF_NODUMP
62 if (flags & EXT2_NODUMP_FL)
63 bsd_flags |= UF_NODUMP;
64#endif
65
66 return chflags (name, bsd_flags);
67#else
68#if HAVE_EXT2_IOCTLS
69 int fd, r, f, save_errno = 0;
70
71 if (!stat(name, &buf) &&
72 !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
73 goto notsupp;
74 }
75#if !APPLE_DARWIN
76 fd = open (name, OPEN_FLAGS);
77 if (fd == -1)
78 return -1;
79 f = (int) flags;
80 r = ioctl (fd, EXT2_IOC_SETFLAGS, &f);
81 if (r == -1)
82 save_errno = errno;
83 close (fd);
84 if (save_errno)
85 errno = save_errno;
86#else
87 f = (int) flags;
88 return syscall(SYS_fsctl, name, EXT2_IOC_SETFLAGS, &f, 0);
89#endif
90 return r;
91#endif /* HAVE_EXT2_IOCTLS */
92#endif
93notsupp:
94 errno = EOPNOTSUPP;
95 return -1;
96}
diff --git a/e2fsprogs/e2p/fsetversion.c b/e2fsprogs/e2p/fsetversion.c
new file mode 100644
index 000000000..93243d6e0
--- /dev/null
+++ b/e2fsprogs/e2p/fsetversion.c
@@ -0,0 +1,60 @@
1/*
2 * fsetversion.c - Set a file version on an ext2 file system
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU Library General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
15 */
16
17#if HAVE_ERRNO_H
18#include <errno.h>
19#endif
20#if HAVE_UNISTD_H
21#include <unistd.h>
22#endif
23#include <fcntl.h>
24#include <sys/ioctl.h>
25
26#include "e2p.h"
27
28#ifdef O_LARGEFILE
29#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK|O_LARGEFILE)
30#else
31#define OPEN_FLAGS (O_RDONLY|O_NONBLOCK)
32#endif
33
34int fsetversion (const char * name, unsigned long version)
35{
36#if HAVE_EXT2_IOCTLS
37#if !APPLE_DARWIN
38 int fd, r, ver, save_errno = 0;
39
40 fd = open (name, OPEN_FLAGS);
41 if (fd == -1)
42 return -1;
43 ver = (int) version;
44 r = ioctl (fd, EXT2_IOC_SETVERSION, &ver);
45 if (r == -1)
46 save_errno = errno;
47 close (fd);
48 if (save_errno)
49 errno = save_errno;
50 return r;
51#else
52 int ver = (int)version;
53 return syscall(SYS_fsctl, name, EXT2_IOC_SETVERSION, &ver, 0);
54#endif
55#else /* ! HAVE_EXT2_IOCTLS */
56 extern int errno;
57 errno = EOPNOTSUPP;
58 return -1;
59#endif /* ! HAVE_EXT2_IOCTLS */
60}
diff --git a/e2fsprogs/e2p/getflags.c b/e2fsprogs/e2p/getflags.c
new file mode 100644
index 000000000..acf7a122b
--- /dev/null
+++ b/e2fsprogs/e2p/getflags.c
@@ -0,0 +1,66 @@
1/*
2 * getflags.c - Get a file flags on an ext2 file system
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU Library General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
15 */
16
17#if HAVE_ERRNO_H
18#include <errno.h>
19#endif
20#include <sys/types.h>
21#include <sys/stat.h>
22#if HAVE_EXT2_IOCTLS
23#include <sys/ioctl.h>
24#endif
25
26#include "e2p.h"
27
28int getflags (int fd, unsigned long * flags)
29{
30 struct stat buf;
31#if HAVE_STAT_FLAGS
32
33 if (fstat (fd, &buf) == -1)
34 return -1;
35
36 *flags = 0;
37#ifdef UF_IMMUTABLE
38 if (buf.st_flags & UF_IMMUTABLE)
39 *flags |= EXT2_IMMUTABLE_FL;
40#endif
41#ifdef UF_APPEND
42 if (buf.st_flags & UF_APPEND)
43 *flags |= EXT2_APPEND_FL;
44#endif
45#ifdef UF_NODUMP
46 if (buf.st_flags & UF_NODUMP)
47 *flags |= EXT2_NODUMP_FL;
48#endif
49
50 return 0;
51#else
52#if HAVE_EXT2_IOCTLS
53 int r, f;
54
55 if (!fstat(fd, &buf) &&
56 !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode))
57 goto notsupp;
58 r = ioctl (fd, EXT2_IOC_GETFLAGS, &f);
59 *flags = f;
60 return r;
61#endif /* HAVE_EXT2_IOCTLS */
62#endif
63notsupp:
64 errno = EOPNOTSUPP;
65 return -1;
66}
diff --git a/e2fsprogs/e2p/getversion.c b/e2fsprogs/e2p/getversion.c
new file mode 100644
index 000000000..38b7d0fb0
--- /dev/null
+++ b/e2fsprogs/e2p/getversion.c
@@ -0,0 +1,37 @@
1/*
2 * getversion.c - Get a file version on an ext2 file system
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU Library General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
15 */
16
17#if HAVE_ERRNO_H
18#include <errno.h>
19#endif
20#include <sys/ioctl.h>
21
22#include "e2p.h"
23
24int getversion (int fd, unsigned long * version)
25{
26#if HAVE_EXT2_IOCTLS
27 int r, ver;
28
29 r = ioctl (fd, EXT2_IOC_GETVERSION, &ver);
30 *version = ver;
31 return 0;
32#else /* ! HAVE_EXT2_IOCTLS */
33 extern int errno;
34 errno = EOPNOTSUPP;
35 return -1;
36#endif /* ! HAVE_EXT2_IOCTLS */
37}
diff --git a/e2fsprogs/e2p/hashstr.c b/e2fsprogs/e2p/hashstr.c
new file mode 100644
index 000000000..b257eb26c
--- /dev/null
+++ b/e2fsprogs/e2p/hashstr.c
@@ -0,0 +1,70 @@
1/*
2 * feature.c --- convert between features and strings
3 *
4 * Copyright (C) 1999 Theodore Ts'o <tytso@mit.edu>
5 *
6 * This file can be redistributed under the terms of the GNU Library General
7 * Public License
8 *
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <ctype.h>
15#include <errno.h>
16
17#include "e2p.h"
18
19struct hash {
20 int num;
21 const char *string;
22};
23
24static struct hash hash_list[] = {
25 { EXT2_HASH_LEGACY, "legacy" },
26 { EXT2_HASH_HALF_MD4, "half_md4" },
27 { EXT2_HASH_TEA, "tea" },
28 { 0, 0 },
29};
30
31const char *e2p_hash2string(int num)
32{
33 struct hash *p;
34 static char buf[20];
35
36 for (p = hash_list; p->string; p++) {
37 if (num == p->num)
38 return p->string;
39 }
40 sprintf(buf, "HASHALG_%d", num);
41 return buf;
42}
43
44/*
45 * Returns the hash algorithm, or -1 on error
46 */
47int e2p_string2hash(char *string)
48{
49 struct hash *p;
50 char *eptr;
51 int num;
52
53 for (p = hash_list; p->string; p++) {
54 if (!strcasecmp(string, p->string)) {
55 return p->num;
56 }
57 }
58 if (strncasecmp(string, "HASHALG_", 8))
59 return -1;
60
61 if (string[8] == 0)
62 return -1;
63 num = strtol(string+8, &eptr, 10);
64 if (num > 255 || num < 0)
65 return -1;
66 if (*eptr)
67 return -1;
68 return num;
69}
70
diff --git a/e2fsprogs/e2p/iod.c b/e2fsprogs/e2p/iod.c
new file mode 100644
index 000000000..808d3a39d
--- /dev/null
+++ b/e2fsprogs/e2p/iod.c
@@ -0,0 +1,72 @@
1/*
2 * iod.c - Iterate a function on each entry of a directory
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU Library General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
15 */
16
17#include "e2p.h"
18#if HAVE_UNISTD_H
19#include <unistd.h>
20#endif
21#include <stdlib.h>
22#include <string.h>
23
24int iterate_on_dir (const char * dir_name,
25 int (*func) (const char *, struct dirent *, void *),
26 void * private)
27{
28 DIR * dir;
29 struct dirent *de, *dep;
30 int max_len = -1, len;
31
32#if HAVE_PATHCONF && defined(_PC_NAME_MAX)
33 max_len = pathconf(dir_name, _PC_NAME_MAX);
34#endif
35 if (max_len == -1) {
36#ifdef _POSIX_NAME_MAX
37 max_len = _POSIX_NAME_MAX;
38#else
39#ifdef NAME_MAX
40 max_len = NAME_MAX;
41#else
42 max_len = 256;
43#endif /* NAME_MAX */
44#endif /* _POSIX_NAME_MAX */
45 }
46 max_len += sizeof(struct dirent);
47
48 de = malloc(max_len+1);
49 if (!de)
50 return -1;
51 memset(de, 0, max_len+1);
52
53 dir = opendir (dir_name);
54 if (dir == NULL) {
55 free(de);
56 return -1;
57 }
58 while ((dep = readdir (dir))) {
59 len = sizeof(struct dirent);
60#ifdef HAVE_RECLEN_DIRENT
61 if (len < dep->d_reclen)
62 len = dep->d_reclen;
63 if (len > max_len)
64 len = max_len;
65#endif
66 memcpy(de, dep, len);
67 (*func) (dir_name, de, private);
68 }
69 free(de);
70 closedir(dir);
71 return 0;
72}
diff --git a/e2fsprogs/e2p/ls.c b/e2fsprogs/e2p/ls.c
new file mode 100644
index 000000000..e8d9d482d
--- /dev/null
+++ b/e2fsprogs/e2p/ls.c
@@ -0,0 +1,276 @@
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], *str;
153 time_t tm;
154
155 inode_blocks_per_group = (((sb->s_inodes_per_group *
156 EXT2_INODE_SIZE(sb)) +
157 EXT2_BLOCK_SIZE(sb) - 1) /
158 EXT2_BLOCK_SIZE(sb));
159 if (sb->s_volume_name[0]) {
160 memset(buf, 0, sizeof(buf));
161 strncpy(buf, sb->s_volume_name, sizeof(sb->s_volume_name));
162 } else
163 strcpy(buf, "<none>");
164 fprintf(f, "Filesystem volume name: %s\n", buf);
165 if (sb->s_last_mounted[0]) {
166 memset(buf, 0, sizeof(buf));
167 strncpy(buf, sb->s_last_mounted, sizeof(sb->s_last_mounted));
168 } else
169 strcpy(buf, "<not available>");
170 fprintf(f, "Last mounted on: %s\n", buf);
171 fprintf(f, "Filesystem UUID: %s\n", e2p_uuid2str(sb->s_uuid));
172 fprintf(f, "Filesystem magic number: 0x%04X\n", sb->s_magic);
173 fprintf(f, "Filesystem revision #: %d", sb->s_rev_level);
174 if (sb->s_rev_level == EXT2_GOOD_OLD_REV) {
175 fprintf(f, " (original)\n");
176#ifdef EXT2_DYNAMIC_REV
177 } else if (sb->s_rev_level == EXT2_DYNAMIC_REV) {
178 fprintf(f, " (dynamic)\n");
179#endif
180 } else
181 fprintf(f, " (unknown)\n");
182 print_features(sb, f);
183 print_mntopts(sb, f);
184 fprintf(f, "Filesystem state: ");
185 print_fs_state (f, sb->s_state);
186 fprintf(f, "\n");
187 fprintf(f, "Errors behavior: ");
188 print_fs_errors(f, sb->s_errors);
189 fprintf(f, "\n");
190 str = e2p_os2string(sb->s_creator_os);
191 fprintf(f, "Filesystem OS type: %s\n", str);
192 free(str);
193 fprintf(f, "Inode count: %u\n", sb->s_inodes_count);
194 fprintf(f, "Block count: %u\n", sb->s_blocks_count);
195 fprintf(f, "Reserved block count: %u\n", sb->s_r_blocks_count);
196 fprintf(f, "Free blocks: %u\n", sb->s_free_blocks_count);
197 fprintf(f, "Free inodes: %u\n", sb->s_free_inodes_count);
198 fprintf(f, "First block: %u\n", sb->s_first_data_block);
199 fprintf(f, "Block size: %u\n", EXT2_BLOCK_SIZE(sb));
200 fprintf(f, "Fragment size: %u\n", EXT2_FRAG_SIZE(sb));
201 if (sb->s_reserved_gdt_blocks)
202 fprintf(f, "Reserved GDT blocks: %u\n",
203 sb->s_reserved_gdt_blocks);
204 fprintf(f, "Blocks per group: %u\n", sb->s_blocks_per_group);
205 fprintf(f, "Fragments per group: %u\n", sb->s_frags_per_group);
206 fprintf(f, "Inodes per group: %u\n", sb->s_inodes_per_group);
207 fprintf(f, "Inode blocks per group: %u\n", inode_blocks_per_group);
208 if (sb->s_first_meta_bg)
209 fprintf(f, "First meta block group: %u\n",
210 sb->s_first_meta_bg);
211 if (sb->s_mkfs_time) {
212 tm = sb->s_mkfs_time;
213 fprintf(f, "Filesystem created: %s", ctime(&tm));
214 }
215 tm = sb->s_mtime;
216 fprintf(f, "Last mount time: %s",
217 sb->s_mtime ? ctime(&tm) : "n/a\n");
218 tm = sb->s_wtime;
219 fprintf(f, "Last write time: %s", ctime(&tm));
220 fprintf(f, "Mount count: %u\n", sb->s_mnt_count);
221 fprintf(f, "Maximum mount count: %d\n", sb->s_max_mnt_count);
222 tm = sb->s_lastcheck;
223 fprintf(f, "Last checked: %s", ctime(&tm));
224 fprintf(f, "Check interval: %u (%s)\n", sb->s_checkinterval,
225 interval_string(sb->s_checkinterval));
226 if (sb->s_checkinterval)
227 {
228 time_t next;
229
230 next = sb->s_lastcheck + sb->s_checkinterval;
231 fprintf(f, "Next check after: %s", ctime(&next));
232 }
233 fprintf(f, "Reserved blocks uid: ");
234 print_user(sb->s_def_resuid, f);
235 fprintf(f, "Reserved blocks gid: ");
236 print_group(sb->s_def_resgid, f);
237 if (sb->s_rev_level >= EXT2_DYNAMIC_REV) {
238 fprintf(f, "First inode: %d\n", sb->s_first_ino);
239 fprintf(f, "Inode size: %d\n", sb->s_inode_size);
240 }
241 if (!e2p_is_null_uuid(sb->s_journal_uuid))
242 fprintf(f, "Journal UUID: %s\n",
243 e2p_uuid2str(sb->s_journal_uuid));
244 if (sb->s_journal_inum)
245 fprintf(f, "Journal inode: %u\n",
246 sb->s_journal_inum);
247 if (sb->s_journal_dev)
248 fprintf(f, "Journal device: 0x%04x\n",
249 sb->s_journal_dev);
250 if (sb->s_last_orphan)
251 fprintf(f, "First orphan inode: %u\n",
252 sb->s_last_orphan);
253 if ((sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
254 sb->s_def_hash_version)
255 fprintf(f, "Default directory hash: %s\n",
256 e2p_hash2string(sb->s_def_hash_version));
257 if (!e2p_is_null_uuid(sb->s_hash_seed))
258 fprintf(f, "Directory Hash Seed: %s\n",
259 e2p_uuid2str(sb->s_hash_seed));
260 if (sb->s_jnl_backup_type) {
261 fprintf(f, "Journal backup: ");
262 switch (sb->s_jnl_backup_type) {
263 case 1:
264 fprintf(f, "inode blocks\n");
265 break;
266 default:
267 fprintf(f, "type %u\n", sb->s_jnl_backup_type);
268 }
269 }
270}
271
272void list_super (struct ext2_super_block * s)
273{
274 list_super2(s, stdout);
275}
276
diff --git a/e2fsprogs/e2p/mntopts.c b/e2fsprogs/e2p/mntopts.c
new file mode 100644
index 000000000..6d0eca0ae
--- /dev/null
+++ b/e2fsprogs/e2p/mntopts.c
@@ -0,0 +1,136 @@
1/*
2 * mountopts.c --- convert between default mount options and strings
3 *
4 * Copyright (C) 2002 Theodore Ts'o <tytso@mit.edu>
5 *
6 * This file can be redistributed under the terms of the GNU Library General
7 * Public License
8 *
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <ctype.h>
15#include <errno.h>
16
17#include "e2p.h"
18
19struct mntopt {
20 unsigned int mask;
21 const char *string;
22};
23
24static struct mntopt mntopt_list[] = {
25 { EXT2_DEFM_DEBUG, "debug" },
26 { EXT2_DEFM_BSDGROUPS, "bsdgroups" },
27 { EXT2_DEFM_XATTR_USER, "user_xattr" },
28 { EXT2_DEFM_ACL, "acl" },
29 { EXT2_DEFM_UID16, "uid16" },
30 { EXT3_DEFM_JMODE_DATA, "journal_data" },
31 { EXT3_DEFM_JMODE_ORDERED, "journal_data_ordered" },
32 { EXT3_DEFM_JMODE_WBACK, "journal_data_writeback" },
33 { 0, 0 },
34};
35
36const char *e2p_mntopt2string(unsigned int mask)
37{
38 struct mntopt *f;
39 static char buf[20];
40 int fnum;
41
42 for (f = mntopt_list; f->string; f++) {
43 if (mask == f->mask)
44 return f->string;
45 }
46 for (fnum = 0; mask >>= 1; fnum++);
47 sprintf(buf, "MNTOPT_%d", fnum);
48 return buf;
49}
50
51int e2p_string2mntopt(char *string, unsigned int *mask)
52{
53 struct mntopt *f;
54 char *eptr;
55 int num;
56
57 for (f = mntopt_list; f->string; f++) {
58 if (!strcasecmp(string, f->string)) {
59 *mask = f->mask;
60 return 0;
61 }
62 }
63 if (strncasecmp(string, "MNTOPT_", 8))
64 return 1;
65
66 if (string[8] == 0)
67 return 1;
68 num = strtol(string+8, &eptr, 10);
69 if (num > 32 || num < 0)
70 return 1;
71 if (*eptr)
72 return 1;
73 *mask = 1 << num;
74 return 0;
75}
76
77static char *skip_over_blanks(char *cp)
78{
79 while (*cp && isspace(*cp))
80 cp++;
81 return cp;
82}
83
84static char *skip_over_word(char *cp)
85{
86 while (*cp && !isspace(*cp) && *cp != ',')
87 cp++;
88 return cp;
89}
90
91/*
92 * Edit a mntopt set array as requested by the user. The ok
93 * parameter, if non-zero, allows the application to limit what
94 * mntopts the user is allowed to set or clear using this function.
95 */
96int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok)
97{
98 char *cp, *buf, *next;
99 int neg;
100 unsigned int mask;
101
102 buf = malloc(strlen(str)+1);
103 if (!buf)
104 return 1;
105 strcpy(buf, str);
106 cp = buf;
107 while (cp && *cp) {
108 neg = 0;
109 cp = skip_over_blanks(cp);
110 next = skip_over_word(cp);
111 if (*next == 0)
112 next = 0;
113 else
114 *next = 0;
115 switch (*cp) {
116 case '-':
117 case '^':
118 neg++;
119 case '+':
120 cp++;
121 break;
122 }
123 if (e2p_string2mntopt(cp, &mask))
124 return 1;
125 if (ok && !(ok & mask))
126 return 1;
127 if (mask & EXT3_DEFM_JMODE)
128 *mntopts &= ~EXT3_DEFM_JMODE;
129 if (neg)
130 *mntopts &= ~mask;
131 else
132 *mntopts |= mask;
133 cp = next ? next+1 : 0;
134 }
135 return 0;
136}
diff --git a/e2fsprogs/e2p/ostype.c b/e2fsprogs/e2p/ostype.c
new file mode 100644
index 000000000..fe6597dd5
--- /dev/null
+++ b/e2fsprogs/e2p/ostype.c
@@ -0,0 +1,73 @@
1/*
2 * getostype.c - Get the Filesystem OS type
3 *
4 * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
5 *
6 * This file can be redistributed under the terms of the GNU Library General
7 * Public License
8 */
9
10#include "e2p.h"
11#include <string.h>
12
13const char *os_tab[] =
14 { "Linux",
15 "Hurd",
16 "Masix",
17 "FreeBSD",
18 "Lites",
19 0 };
20
21/*
22 * Convert an os_type to a string
23 */
24char *e2p_os2string(int os_type)
25{
26 const char *os;
27 char *ret;
28
29 if (os_type <= EXT2_OS_LITES)
30 os = os_tab[os_type];
31 else
32 os = "(unknown os)";
33
34 ret = malloc(strlen(os)+1);
35 strcpy(ret, os);
36 return ret;
37}
38
39/*
40 * Convert an os_type to a string
41 */
42int e2p_string2os(char *str)
43{
44 const char **cpp;
45 int i = 0;
46
47 for (cpp = os_tab; *cpp; cpp++, i++) {
48 if (!strcasecmp(str, *cpp))
49 return i;
50 }
51 return -1;
52}
53
54#ifdef TEST_PROGRAM
55int main(int argc, char **argv)
56{
57 char *s;
58 int i, os;
59
60 for (i=0; i <= EXT2_OS_LITES; i++) {
61 s = e2p_os2string(i);
62 os = e2p_string2os(s);
63 printf("%d: %s (%d)\n", i, s, os);
64 if (i != os) {
65 fprintf(stderr, "Failure!\n");
66 exit(1);
67 }
68 }
69 exit(0);
70}
71#endif
72
73
diff --git a/e2fsprogs/e2p/parse_num.c b/e2fsprogs/e2p/parse_num.c
new file mode 100644
index 000000000..3910e70de
--- /dev/null
+++ b/e2fsprogs/e2p/parse_num.c
@@ -0,0 +1,64 @@
1/*
2 * parse_num.c - Parse the number of blocks
3 *
4 * Copyright (C) 2004,2005 Theodore Ts'o <tytso@mit.edu>
5 *
6 * This file can be redistributed under the terms of the GNU Library General
7 * Public License
8 */
9
10#include "e2p.h"
11
12#include <stdlib.h>
13
14unsigned long parse_num_blocks(const char *arg, int log_block_size)
15{
16 char *p;
17 unsigned long long num;
18
19 num = strtoull(arg, &p, 0);
20
21 if (p[0] && p[1])
22 return 0;
23
24 switch (*p) { /* Using fall-through logic */
25 case 'T': case 't':
26 num <<= 10;
27 case 'G': case 'g':
28 num <<= 10;
29 case 'M': case 'm':
30 num <<= 10;
31 case 'K': case 'k':
32 num >>= log_block_size;
33 break;
34 case 's':
35 num >>= 1;
36 break;
37 case '\0':
38 break;
39 default:
40 return 0;
41 }
42 return num;
43}
44
45#ifdef DEBUG
46#include <unistd.h>
47#include <stdio.h>
48
49main(int argc, char **argv)
50{
51 unsigned long num;
52 int log_block_size = 0;
53
54 if (argc != 2) {
55 fprintf(stderr, "Usage: %s arg\n", argv[0]);
56 exit(1);
57 }
58
59 num = parse_num_blocks(argv[1], log_block_size);
60
61 printf("Parsed number: %lu\n", num);
62 exit(0);
63}
64#endif
diff --git a/e2fsprogs/e2p/pe.c b/e2fsprogs/e2p/pe.c
new file mode 100644
index 000000000..4cce69117
--- /dev/null
+++ b/e2fsprogs/e2p/pe.c
@@ -0,0 +1,37 @@
1/*
2 * pe.c - Print a second extended filesystem errors behavior
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 * This file can be redistributed under the terms of the GNU Library General
9 * Public License
10 */
11
12/*
13 * History:
14 * 94/01/09 - Creation
15 */
16
17#include <stdio.h>
18
19#include "e2p.h"
20
21void print_fs_errors (FILE * f, unsigned short errors)
22{
23 switch (errors)
24 {
25 case EXT2_ERRORS_CONTINUE:
26 fprintf (f, "Continue");
27 break;
28 case EXT2_ERRORS_RO:
29 fprintf (f, "Remount read-only");
30 break;
31 case EXT2_ERRORS_PANIC:
32 fprintf (f, "Panic");
33 break;
34 default:
35 fprintf (f, "Unknown (continue)");
36 }
37}
diff --git a/e2fsprogs/e2p/pf.c b/e2fsprogs/e2p/pf.c
new file mode 100644
index 000000000..48d75a9ae
--- /dev/null
+++ b/e2fsprogs/e2p/pf.c
@@ -0,0 +1,74 @@
1/*
2 * pf.c - Print file attributes on an ext2 file system
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU Library General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
15 */
16
17#include <stdio.h>
18
19#include "e2p.h"
20
21struct flags_name {
22 unsigned long flag;
23 const char *short_name;
24 const char *long_name;
25};
26
27static struct flags_name flags_array[] = {
28 { EXT2_SECRM_FL, "s", "Secure_Deletion" },
29 { EXT2_UNRM_FL, "u" , "Undelete" },
30 { EXT2_SYNC_FL, "S", "Synchronous_Updates" },
31 { EXT2_DIRSYNC_FL, "D", "Synchronous_Directory_Updates" },
32 { EXT2_IMMUTABLE_FL, "i", "Immutable" },
33 { EXT2_APPEND_FL, "a", "Append_Only" },
34 { EXT2_NODUMP_FL, "d", "No_Dump" },
35 { EXT2_NOATIME_FL, "A", "No_Atime" },
36 { EXT2_COMPR_FL, "c", "Compression_Requested" },
37#ifdef ENABLE_COMPRESSION
38 { EXT2_COMPRBLK_FL, "B", "Compressed_File" },
39 { EXT2_DIRTY_FL, "Z", "Compressed_Dirty_File" },
40 { EXT2_NOCOMPR_FL, "X", "Compression_Raw_Access" },
41 { EXT2_ECOMPR_FL, "E", "Compression_Error" },
42#endif
43 { EXT3_JOURNAL_DATA_FL, "j", "Journaled_Data" },
44 { EXT2_INDEX_FL, "I", "Indexed_direcctory" },
45 { EXT2_NOTAIL_FL, "t", "No_Tailmerging" },
46 { EXT2_TOPDIR_FL, "T", "Top_of_Directory_Hierarchies" },
47 { 0, NULL, NULL }
48};
49
50void print_flags (FILE * f, unsigned long flags, unsigned options)
51{
52 int long_opt = (options & PFOPT_LONG);
53 struct flags_name *fp;
54 int first = 1;
55
56 for (fp = flags_array; fp->flag != 0; fp++) {
57 if (flags & fp->flag) {
58 if (long_opt) {
59 if (first)
60 first = 0;
61 else
62 fputs(", ", f);
63 fputs(fp->long_name, f);
64 } else
65 fputs(fp->short_name, f);
66 } else {
67 if (!long_opt)
68 fputs("-", f);
69 }
70 }
71 if (long_opt && first)
72 fputs("---", f);
73}
74
diff --git a/e2fsprogs/e2p/ps.c b/e2fsprogs/e2p/ps.c
new file mode 100644
index 000000000..bec8b4195
--- /dev/null
+++ b/e2fsprogs/e2p/ps.c
@@ -0,0 +1,29 @@
1/*
2 * ps.c - Print filesystem state
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU Library General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/12/22 - Creation
15 */
16
17#include <stdio.h>
18
19#include "e2p.h"
20
21void print_fs_state (FILE * f, unsigned short state)
22{
23 if (state & EXT2_VALID_FS)
24 fprintf (f, " clean");
25 else
26 fprintf (f, " not clean");
27 if (state & EXT2_ERROR_FS)
28 fprintf (f, " with errors");
29}
diff --git a/e2fsprogs/e2p/setflags.c b/e2fsprogs/e2p/setflags.c
new file mode 100644
index 000000000..47c52a7ad
--- /dev/null
+++ b/e2fsprogs/e2p/setflags.c
@@ -0,0 +1,72 @@
1/*
2 * setflags.c - Set a file flags on an ext2 file system
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU Library General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
15 */
16
17#if HAVE_ERRNO_H
18#include <errno.h>
19#endif
20#include <sys/types.h>
21#include <sys/stat.h>
22#if HAVE_EXT2_IOCTLS
23#include <sys/ioctl.h>
24#endif
25
26#include "e2p.h"
27
28/*
29 * Deal with lame glibc's that define this function without actually
30 * implementing it. Can you say "attractive nuisance", boys and girls?
31 * I knew you could!
32 */
33#ifdef __linux__
34#undef HAVE_CHFLAGS
35#endif
36
37int setflags (int fd, unsigned long flags)
38{
39 struct stat buf;
40#if HAVE_CHFLAGS
41 unsigned long bsd_flags = 0;
42
43#ifdef UF_IMMUTABLE
44 if (flags & EXT2_IMMUTABLE_FL)
45 bsd_flags |= UF_IMMUTABLE;
46#endif
47#ifdef UF_APPEND
48 if (flags & EXT2_APPEND_FL)
49 bsd_flags |= UF_APPEND;
50#endif
51#ifdef UF_NODUMP
52 if (flags & EXT2_NODUMP_FL)
53 bsd_flags |= UF_NODUMP;
54#endif
55
56 return fchflags (fd, bsd_flags);
57#else
58#if HAVE_EXT2_IOCTLS
59 int f;
60
61 if (!fstat(fd, &buf) &&
62 !S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) {
63 errno = EOPNOTSUPP;
64 return -1;
65 }
66 f = (int) flags;
67 return ioctl (fd, EXT2_IOC_SETFLAGS, &f);
68#endif /* HAVE_EXT2_IOCTLS */
69#endif
70 errno = EOPNOTSUPP;
71 return -1;
72}
diff --git a/e2fsprogs/e2p/setversion.c b/e2fsprogs/e2p/setversion.c
new file mode 100644
index 000000000..bd00df668
--- /dev/null
+++ b/e2fsprogs/e2p/setversion.c
@@ -0,0 +1,36 @@
1/*
2 * setversion.c - Set a file version on an ext2 file system
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU Library General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
15 */
16
17#if HAVE_ERRNO_H
18#include <errno.h>
19#endif
20#include <sys/ioctl.h>
21
22#include "e2p.h"
23
24int setversion (int fd, unsigned long version)
25{
26#if HAVE_EXT2_IOCTLS
27 int ver;
28
29 ver = (int) version;
30 return ioctl (fd, EXT2_IOC_SETVERSION, &ver);
31#else /* ! HAVE_EXT2_IOCTLS */
32 extern int errno;
33 errno = EOPNOTSUPP;
34 return -1;
35#endif /* ! HAVE_EXT2_IOCTLS */
36}
diff --git a/e2fsprogs/e2p/uuid.c b/e2fsprogs/e2p/uuid.c
new file mode 100644
index 000000000..fef3b91e7
--- /dev/null
+++ b/e2fsprogs/e2p/uuid.c
@@ -0,0 +1,79 @@
1/*
2 * uuid.c -- utility routines for manipulating UUID's.
3 */
4
5#include <stdio.h>
6#include <string.h>
7#include <ext2fs/ext2_types.h>
8
9#include "e2p.h"
10
11struct uuid {
12 __u32 time_low;
13 __u16 time_mid;
14 __u16 time_hi_and_version;
15 __u16 clock_seq;
16 __u8 node[6];
17};
18
19/* Returns 1 if the uuid is the NULL uuid */
20int e2p_is_null_uuid(void *uu)
21{
22 __u8 *cp;
23 int i;
24
25 for (i=0, cp = uu; i < 16; i++)
26 if (*cp)
27 return 0;
28 return 1;
29}
30
31static void e2p_unpack_uuid(void *in, struct uuid *uu)
32{
33 __u8 *ptr = in;
34 __u32 tmp;
35
36 tmp = *ptr++;
37 tmp = (tmp << 8) | *ptr++;
38 tmp = (tmp << 8) | *ptr++;
39 tmp = (tmp << 8) | *ptr++;
40 uu->time_low = tmp;
41
42 tmp = *ptr++;
43 tmp = (tmp << 8) | *ptr++;
44 uu->time_mid = tmp;
45
46 tmp = *ptr++;
47 tmp = (tmp << 8) | *ptr++;
48 uu->time_hi_and_version = tmp;
49
50 tmp = *ptr++;
51 tmp = (tmp << 8) | *ptr++;
52 uu->clock_seq = tmp;
53
54 memcpy(uu->node, ptr, 6);
55}
56
57void e2p_uuid_to_str(void *uu, char *out)
58{
59 struct uuid uuid;
60
61 e2p_unpack_uuid(uu, &uuid);
62 sprintf(out,
63 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
64 uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
65 uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
66 uuid.node[0], uuid.node[1], uuid.node[2],
67 uuid.node[3], uuid.node[4], uuid.node[5]);
68}
69
70const char *e2p_uuid2str(void *uu)
71{
72 static char buf[80];
73
74 if (e2p_is_null_uuid(uu))
75 return "<none>";
76 e2p_uuid_to_str(uu, buf);
77 return buf;
78}
79
diff --git a/e2fsprogs/lsattr.c b/e2fsprogs/lsattr.c
new file mode 100644
index 000000000..0f1c6f22c
--- /dev/null
+++ b/e2fsprogs/lsattr.c
@@ -0,0 +1,193 @@
1/*
2 * lsattr.c - List file attributes on an ext2 file system
3 *
4 * Copyright (C) 1993, 1994 Remy Card <card@masi.ibp.fr>
5 * Laboratoire MASI, Institut Blaise Pascal
6 * Universite Pierre et Marie Curie (Paris VI)
7 *
8 * This file can be redistributed under the terms of the GNU General
9 * Public License
10 */
11
12/*
13 * History:
14 * 93/10/30 - Creation
15 * 93/11/13 - Replace stat() calls by lstat() to avoid loops
16 * 94/02/27 - Integrated in Ted's distribution
17 * 98/12/29 - Display version info only when -V specified (G M Sipe)
18 */
19
20#include <sys/types.h>
21#include <dirent.h>
22#include <errno.h>
23#include <fcntl.h>
24#include <getopt.h>
25#include <stdio.h>
26#include <unistd.h>
27#include <stdlib.h>
28#include <string.h>
29#include <sys/param.h>
30#include <sys/stat.h>
31
32#include <ext2fs/ext2_fs.h>
33#include "e2fsbb.h"
34#include "e2p/e2p.h"
35
36#ifdef __GNUC__
37#define EXT2FS_ATTR(x) __attribute__(x)
38#else
39#define EXT2FS_ATTR(x)
40#endif
41
42static int all;
43static int dirs_opt;
44static unsigned pf_options;
45static int recursive;
46static int verbose;
47static int generation_opt;
48
49#ifdef _LFS64_LARGEFILE
50#define LSTAT lstat64
51#define STRUCT_STAT struct stat64
52#else
53#define LSTAT lstat
54#define STRUCT_STAT struct stat
55#endif
56
57#if 0
58static void usage(void)
59{
60 fprintf(stderr, _("Usage: %s [-RVadlv] [files...]\n"), program_name);
61 exit(1);
62}
63#endif
64
65static void list_attributes (const char * name)
66{
67 unsigned long flags;
68 unsigned long generation;
69
70 if (fgetflags (name, &flags) == -1) {
71 com_err (program_name, errno, _("While reading flags on %s"),
72 name);
73 return;
74 }
75 if (generation_opt) {
76 if (fgetversion (name, &generation) == -1) {
77 com_err (program_name, errno,
78 _("While reading version on %s"),
79 name);
80 return;
81 }
82 printf ("%5lu ", generation);
83 }
84 if (pf_options & PFOPT_LONG) {
85 printf("%-28s ", name);
86 print_flags(stdout, flags, pf_options);
87 fputc('\n', stdout);
88 } else {
89 print_flags(stdout, flags, pf_options);
90 printf(" %s\n", name);
91 }
92}
93
94static int lsattr_dir_proc (const char *, struct dirent *, void *);
95
96static void lsattr_args (const char * name)
97{
98 STRUCT_STAT st;
99
100 if (LSTAT (name, &st) == -1)
101 com_err (program_name, errno, _("while trying to stat %s"),
102 name);
103 else {
104 if (S_ISDIR(st.st_mode) && !dirs_opt)
105 iterate_on_dir (name, lsattr_dir_proc, NULL);
106 else
107 list_attributes (name);
108 }
109}
110
111static int lsattr_dir_proc (const char * dir_name, struct dirent * de,
112 void * private EXT2FS_ATTR((unused)))
113{
114 STRUCT_STAT st;
115 char *path;
116 int dir_len = strlen(dir_name);
117
118 path = malloc(dir_len + strlen (de->d_name) + 2);
119
120 if (dir_len && dir_name[dir_len-1] == '/')
121 sprintf (path, "%s%s", dir_name, de->d_name);
122 else
123 sprintf (path, "%s/%s", dir_name, de->d_name);
124 if (LSTAT (path, &st) == -1)
125 perror (path);
126 else {
127 if (de->d_name[0] != '.' || all) {
128 list_attributes (path);
129 if (S_ISDIR(st.st_mode) && recursive &&
130 strcmp(de->d_name, ".") &&
131 strcmp(de->d_name, "..")) {
132 printf ("\n%s:\n", path);
133 iterate_on_dir (path, lsattr_dir_proc, NULL);
134 printf ("\n");
135 }
136 }
137 }
138 free(path);
139 return 0;
140}
141
142int lsattr_main (int argc, char ** argv)
143{
144 int c;
145 int i;
146
147#ifdef ENABLE_NLS
148 setlocale(LC_MESSAGES, "");
149 setlocale(LC_CTYPE, "");
150 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
151 textdomain(NLS_CAT_NAME);
152#endif
153#if 0
154 if (argc && *argv)
155 program_name = *argv;
156#endif
157 while ((c = getopt (argc, argv, "Radlv")) != EOF)
158 switch (c)
159 {
160 case 'R':
161 recursive = 1;
162 break;
163 case 'V':
164 verbose = 1;
165 break;
166 case 'a':
167 all = 1;
168 break;
169 case 'd':
170 dirs_opt = 1;
171 break;
172 case 'l':
173 pf_options = PFOPT_LONG;
174 break;
175 case 'v':
176 generation_opt = 1;
177 break;
178 default:
179 usage();
180 }
181
182#if 0
183 if (verbose)
184 fprintf (stderr, "lsattr %s (%s)\n",
185 E2FSPROGS_VERSION, E2FSPROGS_DATE);
186#endif
187 if (optind > argc - 1)
188 lsattr_args (".");
189 else
190 for (i = optind; i < argc; i++)
191 lsattr_args (argv[i]);
192 exit(0);
193}
diff --git a/sysdeps/linux/Config.in b/sysdeps/linux/Config.in
index 744a84d18..e926b5973 100644
--- a/sysdeps/linux/Config.in
+++ b/sysdeps/linux/Config.in
@@ -221,6 +221,7 @@ source archival/Config.in
221source coreutils/Config.in 221source coreutils/Config.in
222source console-tools/Config.in 222source console-tools/Config.in
223source debianutils/Config.in 223source debianutils/Config.in
224source e2fsprogs/Config.in
224source editors/Config.in 225source editors/Config.in
225source findutils/Config.in 226source findutils/Config.in
226source init/Config.in 227source init/Config.in
@@ -291,4 +292,3 @@ endchoice
291 292
292 293
293endmenu 294endmenu
294