+2003-05-13 root <tytso@mit.edu>
+
+ * util.c (reset_getopt), debugfs.c (do_open_filesys,
+ do_show_super_stats), ls.c (do_list_dir), dump.c (do_dump),
+ htree.c (do_htree_dump, do_dx_hash), logdump.c (do_logdump):
+ Define and use a new function, reset_getopt(), which does whatever
+ is necessary to reset getopt() again. This is different for
+ different implementations, so the portabilty issues are a bit of a
+ nightmare. (Addresses Debian bug #192834)
+
2003-05-05 Theodore Ts'o <tytso@mit.edu>
* debugfs.c (do_imap), debugfs.h, debug_cmds.ct, debugfs.8.in:
extern int optind;
extern char *optarg;
#endif
-#ifdef HAVE_OPTRESET
-extern int optreset; /* defined by BSD, but not others */
-#endif
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
blk_t blocksize = 0;
int open_flags = 0;
- optind = 1;
-#ifdef HAVE_OPTRESET
- optreset = 1; /* Makes BSD getopt happy */
-#endif
+ reset_getopt();
while ((c = getopt (argc, argv, "iwfcb:s:")) != EOF) {
switch (c) {
case 'i':
int numdirs = 0;
const char *usage = "Usage: show_super [-h]";
- optind = 1;
-#ifdef HAVE_OPTRESET
- optreset = 1; /* Makes BSD getopt happy */
-#endif
+ reset_getopt();
while ((c = getopt (argc, argv, "h")) != EOF) {
switch (c) {
case 'h':
return;
ino = string_to_inode(argv[1]);
if (!ino)
- return 0;
+ return;
group = (ino - 1) / EXT2_INODES_PER_GROUP(current_fs->super);
offset = ((ino - 1) % EXT2_INODES_PER_GROUP(current_fs->super)) *
extern ext2_filsys current_fs;
extern ext2_ino_t root, cwd;
+extern void reset_getopt(void);
extern FILE *open_pager(void);
extern void close_pager(FILE *stream);
extern int check_fs_open(char *name);
extern int optind;
extern char *optarg;
#endif
-#ifdef HAVE_OPTRESET
-extern int optreset; /* defined by BSD, but not others */
-#endif
#include "debugfs.h"
const char *dump_usage = "Usage: dump_inode [-p] <file> <output_file>";
char *in_fn, *out_fn;
- optind = 1;
-#ifdef HAVE_OPTRESET
- optreset = 1; /* Makes BSD getopt happy */
-#endif
+ reset_getopt();
while ((c = getopt (argc, argv, "p")) != EOF) {
switch (c) {
case 'p':
extern int optind;
extern char *optarg;
#endif
-#ifdef HAVE_OPTRESET
-extern int optreset; /* defined by BSD, but not others */
-#endif
#include "debugfs.h"
pager = open_pager();
- optind = 1;
-#ifdef HAVE_OPTRESET
- optreset = 1; /* Makes BSD getopt happy */
-#endif
+ reset_getopt();
while ((c = getopt (argc, argv, "l")) != EOF) {
switch (c) {
case 'l':
__u32 hash_seed[4];
hash_seed[0] = hash_seed[1] = hash_seed[2] = hash_seed[3] = 0;
- optind = 1;
-#ifdef HAVE_OPTRESET
- optreset = 1; /* Makes BSD getopt happy */
-#endif
+
+ reset_getopt();
while ((c = getopt (argc, argv, "h:")) != EOF) {
switch (c) {
case 'h':
extern int optind;
extern char *optarg;
#endif
-#ifdef HAVE_OPTRESET
-extern int optreset; /* defined by BSD, but not others */
-#endif
#include "debugfs.h"
#include "blkid/blkid.h"
struct journal_source journal_source;
struct ext2_super_block *es = NULL;
- optind = 1;
-#ifdef HAVE_OPTRESET
- optreset = 1; /* Makes BSD getopt happy */
-#endif
journal_source.where = 0;
journal_source.fd = 0;
journal_source.file = 0;
inode_block_to_dump = -1;
inode_to_dump = -1;
+ reset_getopt();
while ((c = getopt (argc, argv, "ab:ci:f:")) != EOF) {
switch (c) {
case 'a':
extern int optind;
extern char *optarg;
#endif
-#ifdef HAVE_OPTRESET
-extern int optreset; /* defined by BSD, but not others */
-#endif
#include "debugfs.h"
if (check_fs_open(argv[0]))
return;
- optind = 1;
-#ifdef HAVE_OPTRESET
- optreset = 1; /* Makes BSD getopt happy */
-#endif
+ reset_getopt();
while ((c = getopt (argc, argv, "dl")) != EOF) {
switch (c) {
case 'l':
#include <string.h>
#include <time.h>
#include <signal.h>
+#ifdef HAVE_GETOPT_H
+#include <getopt.h>
+#else
+extern int optind;
+extern char *optarg;
+#endif
+#ifdef HAVE_OPTRESET
+extern int optreset; /* defined by BSD, but not others */
+#endif
#include "debugfs.h"
+/*
+ * This function resets the libc getopt() function, which keeps
+ * internal state. Bad design! Stupid libc API designers! No
+ * biscuit!
+ *
+ * BSD-derived getopt() functions require that optind be reset to 1 in
+ * order to reset getopt() state. This used to be generally accepted
+ * way of resetting getopt(). However, glibc's getopt()
+ * has additional getopt() state beyond optind, and requires that
+ * optind be set zero to reset its state. So the unfortunate state of
+ * affairs is that BSD-derived versions of getopt() misbehave if
+ * optind is set to 0 in order to reset getopt(), and glibc's getopt()
+ * will core ump if optind is set 1 in order to reset getopt().
+ *
+ * More modern versions of BSD require that optreset be set to 1 in
+ * order to reset getopt(). Sigh. Standards, anyone?
+ *
+ * We hide the hair here.
+ */
+void reset_getopt(void)
+{
+#ifdef __GLIBC__
+ optind = 0;
+#else
+ optind = 1;
+#endif
+#ifdef HAVE_OPTRESET
+ optreset = 1; /* Makes BSD getopt happy */
+#endif
+}
+
FILE *open_pager(void)
{
FILE *outfile;