예제 #1
0
/**
 * ntfs_log_parse_option - Act upon command line options
 * @option:	Option flag
 *
 * Delegate some of the work of parsing the command line.  All the options begin
 * with "--log-".  Options cause log levels to be enabled in @ntfs_log (the
 * global logging structure).
 *
 * Note: The "colour" option changes the logging handler.
 *
 * Returns:  TRUE  Option understood
 *          FALSE  Invalid log option
 */
BOOL1 ntfs_log_parse_option(const char *option)
{
	if (strcmp(option, "--log-debug") == 0) {
		ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG);
		return TRUE;
	} else if (strcmp(option, "--log-verbose") == 0) {
		ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
		return TRUE;
	} else if (strcmp(option, "--log-quiet") == 0) {
		ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
		return TRUE;
	} else if (strcmp(option, "--log-trace") == 0) {
		ntfs_log_set_levels(NTFS_LOG_LEVEL_TRACE);
		return TRUE;
	}

	ntfs_log_debug("Unknown logging option '%s'\n", option);
	return FALSE;
}
예제 #2
0
/**
 * parse_options - Read and validate the programs command line
 *
 * Read the command line, verify the syntax and parse the options.
 * This function is very long, but quite simple.
 *
 * Return:  1 Success
 *	    0 Error, one or more problems
 */
static int parse_options(int argc, char **argv)
{
	static const char *sopt = "-a:fh?i:n:qVvr";
	static const struct option lopt[] = {
		{ "attribute",      required_argument,	NULL, 'a' },
		{ "attribute-name", required_argument,	NULL, 'n' },
		{ "force",	    no_argument,	NULL, 'f' },
		{ "help",	    no_argument,	NULL, 'h' },
		{ "inode",	    required_argument,	NULL, 'i' },
		{ "quiet",	    no_argument,	NULL, 'q' },
		{ "version",	    no_argument,	NULL, 'V' },
		{ "verbose",	    no_argument,	NULL, 'v' },
		{ "raw",	    no_argument,	NULL, 'r' },
		{ NULL,		    0,			NULL, 0   }
	};

	int c = -1;
	int err  = 0;
	int ver  = 0;
	int help = 0;
	int levels = 0;
	ATTR_TYPES attr = AT_UNUSED;

	opterr = 0; /* We'll handle the errors, thank you. */

	opts.inode = -1;
	opts.attr = cpu_to_le32(-1);
	opts.attr_name = NULL;
	opts.attr_name_len = 0;

	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
		switch (c) {
		case 1:	/* A non-option argument */
			if (!opts.device) {
				opts.device = argv[optind - 1];
			} else if (!opts.file) {
				opts.file = argv[optind - 1];
			} else {
				ntfs_log_error("You must specify exactly one "
						"file.\n");
				err++;
			}
			break;
		case 'a':
			if (opts.attr != cpu_to_le32(-1)) {
				ntfs_log_error("You must specify exactly one "
						"attribute.\n");
			} else if (parse_attribute(optarg, &attr) > 0) {
				opts.attr = attr;
				break;
			} else {
				ntfs_log_error("Couldn't parse attribute.\n");
			}
			err++;
			break;
		case 'f':
			opts.force++;
			break;
		case 'h':
		case '?':
			if (strncmp (argv[optind-1], "--log-", 6) == 0) {
				if (!ntfs_log_parse_option (argv[optind-1]))
					err++;
				break;
			}
			help++;
			break;
		case 'i':
			if (opts.inode != -1)
				ntfs_log_error("You must specify exactly one inode.\n");
			else if (utils_parse_size(optarg, &opts.inode, FALSE))
				break;
			else
				ntfs_log_error("Couldn't parse inode number.\n");
			err++;
			break;

		case 'n':
			opts.attr_name_len = ntfs_mbstoucs(optarg,
							   &opts.attr_name);
			if (opts.attr_name_len < 0) {
				ntfs_log_perror("Invalid attribute name '%s'",
						optarg);
				usage();
			}

		case 'q':
			opts.quiet++;
			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
			break;
		case 'V':
			ver++;
			break;
		case 'v':
			opts.verbose++;
			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
			break;
		case 'r':
			opts.raw = TRUE;
			break;
		default:
			ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
			err++;
			break;
		}
	}

	/* Make sure we're in sync with the log levels */
	levels = ntfs_log_get_levels();
	if (levels & NTFS_LOG_LEVEL_VERBOSE)
		opts.verbose++;
	if (!(levels & NTFS_LOG_LEVEL_QUIET))
		opts.quiet++;

	if (help || ver) {
		opts.quiet = 0;
	} else {
		if (opts.device == NULL) {
			ntfs_log_error("You must specify a device.\n");
			err++;

		} else if (opts.file == NULL && opts.inode == -1) {
			ntfs_log_error("You must specify a file or inode "
				 "with the -i option.\n");
			err++;

		} else if (opts.file != NULL && opts.inode != -1) {
			ntfs_log_error("You can't specify both a file and inode.\n");
			err++;
		}

		if (opts.quiet && opts.verbose) {
			ntfs_log_error("You may not use --quiet and --verbose at the "
					"same time.\n");
			err++;
		}
	}

	if (ver)
		version();
	if (help || err)
		usage();

	return (!err && !help && !ver);
}
예제 #3
0
/**
 * parse_options - Read and validate the programs command line
 *
 * Read the command line, verify the syntax and parse the options.
 * This function is very long, but quite simple.
 *
 * Return:  1 Success
 *	    0 Error, one or more problems
 */
static int parse_options(int argc, char *argv[])
{
	static const char *sopt = "-fh?nqvV";
	static const struct option lopt[] = {
		{ "force",	 no_argument,		NULL, 'f' },
		{ "help",	 no_argument,		NULL, 'h' },
		{ "no-action",	 no_argument,		NULL, 'n' },
		{ "quiet",	 no_argument,		NULL, 'q' },
		{ "verbose",	 no_argument,		NULL, 'v' },
		{ "version",	 no_argument,		NULL, 'V' },
		{ NULL, 0, NULL, 0 },
	};

	int c = -1;
	int err  = 0;
	int ver  = 0;
	int help = 0;
	int levels = 0;

	opterr = 0; /* We'll handle the errors, thank you. */

	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
		switch (c) {
		case 1:	/* A non-option argument */
			if (!err && !opts.device)
				opts.device = argv[optind-1];
			else if (!err && !opts.label)
				opts.label = argv[optind-1];
			else
				err++;
			break;
		case 'f':
			opts.force++;
			break;
		case 'h':
		case '?':
			if (strncmp (argv[optind-1], "--log-", 6) == 0) {
				if (!ntfs_log_parse_option (argv[optind-1]))
					err++;
				break;
			}
			help++;
			break;
		case 'n':
			opts.noaction++;
			break;
		case 'q':
			opts.quiet++;
			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
			break;
		case 'v':
			opts.verbose++;
			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
			break;
		case 'V':
			ver++;
			break;
		default:
			ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
			err++;
			break;
		}
	}

	/* Make sure we're in sync with the log levels */
	levels = ntfs_log_get_levels();
	if (levels & NTFS_LOG_LEVEL_VERBOSE)
		opts.verbose++;
	if (!(levels & NTFS_LOG_LEVEL_QUIET))
		opts.quiet++;

	if (help || ver) {
		opts.quiet = 0;
	} else {
		if (opts.device == NULL) {
			if (argc > 1)
				ntfs_log_error("You must specify a device.\n");
			err++;
		}

		if (opts.quiet && opts.verbose) {
			ntfs_log_error("You may not use --quiet and --verbose at "
					"the same time.\n");
			err++;
		}
	}

	if (ver)
		version();
	if (help || err)
		usage();

	return (!err && !help && !ver);
}
예제 #4
0
/**
 * parse_options - Read and validate the programs command line
 *
 * Read the command line, verify the syntax and parse the options.
 * This function is very long, but quite simple.
 *
 * Return:  1 Success
 *	    0 Error, one or more problems
 */
static int parse_options(int argc, char **argv)
{
	static const char *sopt = "-c:F:fh?I:ilqs:vV";
	static const struct option lopt[] = {
		{ "cluster",	required_argument,	NULL, 'c' },
		{ "filename",	required_argument,	NULL, 'F' },
		{ "force",	no_argument,		NULL, 'f' },
		{ "help",	no_argument,		NULL, 'h' },
		{ "info",	no_argument,		NULL, 'i' },
		{ "inode",	required_argument,	NULL, 'I' },
		{ "last",	no_argument,		NULL, 'l' },
		{ "quiet",	no_argument,		NULL, 'q' },
		{ "sector",	required_argument,	NULL, 's' },
		{ "verbose",	no_argument,		NULL, 'v' },
		{ "version",	no_argument,		NULL, 'V' },
		{ NULL,		0,			NULL, 0   }
	};

	int c = -1;
	int err  = 0;
	int ver  = 0;
	int help = 0;
	int levels = 0;
	char *end = NULL;

	opterr = 0; /* We'll handle the errors, thank you. */

	opts.action      = act_none;
	opts.range_begin = -1;
	opts.range_end   = -1;

	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
		switch (c) {
		case 1:	/* A non-option argument */
			if (!opts.device) {
				opts.device = argv[optind-1];
			} else {
				opts.device = NULL;
				err++;
			}
			break;

		case 'c':
			if ((opts.action == act_none) &&
			    (utils_parse_range(optarg, &opts.range_begin, &opts.range_end, FALSE)))
				opts.action = act_cluster;
			else
				opts.action = act_error;
			break;
		case 'F':
			if (opts.action == act_none) {
				opts.action = act_file;
				opts.filename = optarg;
			} else {
				opts.action = act_error;
			}
			break;
		case 'f':
			opts.force++;
			break;
		case 'h':
		case '?':
			if (strncmp (argv[optind-1], "--log-", 6) == 0) {
				if (!ntfs_log_parse_option (argv[optind-1]))
					err++;
				break;
			}
			help++;
			break;
		case 'I':
			if (opts.action == act_none) {
				opts.action = act_inode;
				opts.inode = strtol(optarg, &end, 0);
				if (end && *end)
					err++;
			} else {
				opts.action = act_error;
			}
			break;
		case 'i':
			if (opts.action == act_none)
				opts.action = act_info;
			else
				opts.action = act_error;
			break;
		case 'l':
			if (opts.action == act_none)
				opts.action = act_last;
			else
				opts.action = act_error;
			break;
		case 'q':
			opts.quiet++;
			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
			break;
		case 's':
			if ((opts.action == act_none) &&
			    (utils_parse_range(optarg, &opts.range_begin, &opts.range_end, FALSE)))
				opts.action = act_sector;
			else
				opts.action = act_error;
			break;
		case 'v':
			opts.verbose++;
			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
			break;
		case 'V':
			ver++;
			break;
		default:
			if ((optopt == 'c') || (optopt == 's'))
				ntfs_log_error("Option '%s' requires an argument.\n", argv[optind-1]);
			else
				ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
			err++;
			break;
		}
	}

	/* Make sure we're in sync with the log levels */
	levels = ntfs_log_get_levels();
	if (levels & NTFS_LOG_LEVEL_VERBOSE)
		opts.verbose++;
	if (!(levels & NTFS_LOG_LEVEL_QUIET))
		opts.quiet++;

	if (help || ver) {
		opts.quiet = 0;
	} else {
		if (opts.action == act_none)
			opts.action = act_info;
		if (opts.action == act_info)
			opts.quiet = 0;

		if (opts.device == NULL) {
			if (argc > 1)
				ntfs_log_error("You must specify exactly one device.\n");
			err++;
		}

		if (opts.quiet && opts.verbose) {
			ntfs_log_error("You may not use --quiet and --verbose at the same time.\n");
			err++;
		}

		if (opts.action == act_error) {
			ntfs_log_error("You may only specify one action: --info, --cluster, --sector or --last.\n");
			err++;
		} else if (opts.range_begin > opts.range_end) {
			ntfs_log_error("The range must be in ascending order.\n");
			err++;
		}
	}

	if (ver)
		version();
	if (help || err)
		usage();

	return (!err && !help && !ver);
}
예제 #5
0
/**
 * parse_options - Read and validate the programs command line
 *
 * Read the command line, verify the syntax and parse the options.
 * This function is very long, but quite simple.
 *
 * Return:  1 Success
 *	    0 Error, one or more problems
 */
static int parse_options(int argc, char **argv)
{
    static const char *sopt = "-fh?i:k:qVv";
    static const struct option lopt[] = {
        {"force", no_argument, NULL, 'f'},
        {"help", no_argument, NULL, 'h'},
        {"inode", required_argument, NULL, 'i'},
        {"keyfile", required_argument, NULL, 'k'},
        {"quiet", no_argument, NULL, 'q'},
        {"version", no_argument, NULL, 'V'},
        {"verbose", no_argument, NULL, 'v'},
        {NULL, 0, NULL, 0}
    };

    int c = -1;
    int err = 0;
    int ver = 0;
    int help = 0;

    opterr = 0;		/* We'll handle the errors, thank you. */

    opts.inode = -1;

    while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
        switch (c) {
        case 1:	/* A non-option argument */
            if (!opts.device)
                opts.device = argv[optind - 1];
            else if (!opts.file)
                opts.file = argv[optind - 1];
            else {
                ntfs_log_error("You must specify exactly one "
                               "file.\n");
                err++;
            }
            break;
        case 'f':
            opts.force++;
            break;
        case 'h':
        case '?':
            help++;
            break;
        case 'k':
            if (!opts.keyfile)
                opts.keyfile = argv[optind - 1];
            else {
                ntfs_log_error("You must specify exactly one "
                               "key file.\n");
                err++;
            }
            break;
        case 'i':
            if (opts.inode != -1)
                ntfs_log_error("You must specify exactly one "
                               "inode.\n");
            else if (utils_parse_size(optarg, &opts.inode, FALSE))
                break;
            else
                ntfs_log_error("Couldn't parse inode number.\n");
            err++;
            break;
        case 'q':
            opts.quiet++;
            ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
            break;
        case 'V':
            ver++;
            break;
        case 'v':
            opts.verbose++;
            ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
            break;
        default:
            ntfs_log_error("Unknown option '%s'.\n",
                           argv[optind - 1]);
            err++;
            break;
        }
    }

    if (help || ver) {
        opts.quiet = 0;
        ntfs_log_set_levels(NTFS_LOG_LEVEL_QUIET);
    } else {
        if (!opts.keyfile) {
            ntfs_log_error("You must specify a key file.\n");
            err++;
        } else if (opts.device == NULL) {
            ntfs_log_error("You must specify a device.\n");
            err++;
        } else if (opts.file == NULL && opts.inode == -1) {
            ntfs_log_error("You must specify a file or inode with "
                           "the -i option.\n");
            err++;
        } else if (opts.file != NULL && opts.inode != -1) {
            ntfs_log_error("You can't specify both a file and "
                           "inode.\n");
            err++;
        }
        if (opts.quiet && opts.verbose) {
            ntfs_log_error("You may not use --quiet and --verbose "
                           "at the same time.\n");
            err++;
        }
    }

    if (ver)
        version();
    if (help || err)
        usage();

    return (!err && !help && !ver);
}
예제 #6
0
파일: ntfslabel.c 프로젝트: AllardJ/Tomato
/**
 * parse_options - Read and validate the programs command line
 *
 * Read the command line, verify the syntax and parse the options.
 * This function is very long, but quite simple.
 *
 * Return:  1 Success
 *	    0 Error, one or more problems
 */
static int parse_options(int argc, char *argv[])
{
	static const char *sopt = "-fh?IinqvV";
	static const struct option lopt[] = {
		{ "force",	 no_argument,		NULL, 'f' },
		{ "help",	 no_argument,		NULL, 'h' },
		{ "new-serial",  optional_argument,	NULL, 'I' },
		{ "new-half-serial", optional_argument,	NULL, 'i' },
		{ "no-action",	 no_argument,		NULL, 'n' },
		{ "quiet",	 no_argument,		NULL, 'q' },
		{ "verbose",	 no_argument,		NULL, 'v' },
		{ "version",	 no_argument,		NULL, 'V' },
		{ NULL, 0, NULL, 0 },
	};

	int c = -1;
	int err  = 0;
	int ver  = 0;
	int help = 0;
	int levels = 0;
	char *endserial;

	opterr = 0; /* We'll handle the errors, thank you. */

	while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
		switch (c) {
		case 1:	/* A non-option argument */
			if (!err && !opts.device)
				opts.device = argv[optind-1];
			else if (!err && !opts.label)
				opts.label = argv[optind-1];
			else
				err++;
			break;
		case 'f':
			opts.force++;
			break;
		case 'h':
			help++;
			break;
		case 'I' :	/* not proposed as a short option letter */
			if (optarg) {
				opts.serial = strtoull(optarg, &endserial, 16);
				if (*endserial)
					ntfs_log_error("Bad hexadecimal serial number.\n");
			}
			opts.new_serial |= 2;
			break;
		case 'i' :	/* not proposed as a short option letter */
			if (optarg) {
				opts.serial = strtoull(optarg, &endserial, 16)
							<< 32;
				if (*endserial)
					ntfs_log_error("Bad hexadecimal serial number.\n");
			}
			opts.new_serial |= 1;
			break;
		case 'n':
			opts.noaction++;
			break;
		case 'q':
			opts.quiet++;
			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
			break;
		case 'v':
			opts.verbose++;
			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
			break;
		case 'V':
			ver++;
			break;
		case '?':
			if (strncmp (argv[optind-1], "--log-", 6) == 0) {
				if (!ntfs_log_parse_option (argv[optind-1]))
					err++;
				break;
			}
			/* fall through */
		default:
			ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]);
			err++;
			break;
		}
	}

	/* Make sure we're in sync with the log levels */
	levels = ntfs_log_get_levels();
	if (levels & NTFS_LOG_LEVEL_VERBOSE)
		opts.verbose++;
	if (!(levels & NTFS_LOG_LEVEL_QUIET))
		opts.quiet++;

	if (help || ver) {
		opts.quiet = 0;
	} else {
		if (opts.device == NULL) {
			if (argc > 1)
				ntfs_log_error("You must specify a device.\n");
			err++;
		}

		if (opts.quiet && opts.verbose) {
			ntfs_log_error("You may not use --quiet and --verbose at "
					"the same time.\n");
			err++;
		}
	}

	if (ver)
		version();
	if (help || err)
		usage();

		/* tri-state 0 : done, 1 : error, -1 : proceed */
	return (err ? 1 : (help || ver ? 0 : -1));
}
예제 #7
0
/**
 * parse_options
 */
static void parse_options(int argc, char *argv[])
{
	long long ll;
	char *s, *s2;
	int c;

	opt_alloc_len = 0;
	opt_alloc_offs = 0;
	if (argc && *argv)
		EXEC_NAME = *argv;
	fprintf(stderr, "%s v%s (libntfs-3g)\n", EXEC_NAME, VERSION);
	while ((c = getopt_long(argc, argv, "fh?no:qvVl:", lopt, NULL)) != EOF) {
		switch (c) {
		case 'f':
			opts.force = 1;
			break;
		case 'n':
			opts.no_size_change = 1;
			break;
		case 'N':		/* Not proposed as a short option */
			opts.no_action = 1;
			break;
		case 'q':
			opts.quiet = 1;
			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
			break;
		case 'v':
			opts.verbose++;
			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
			break;
		case 'V':
			/* Version number already printed */
			license();
			exit(0);
		case 'l':
			ll = option_value(argv[optind - 1]);
			if ((ll <= 0)
			    || (ll >= LLONG_MAX && errno == ERANGE))
				err_usage("Invalid length : %s\n",
					argv[optind - 1]);
			opt_alloc_len = ll;
			break;
		case 'o':
			ll = option_value(argv[optind - 1]);
			if ((ll < 0)
			    || (ll >= LLONG_MAX && errno == ERANGE))
				err_usage("Invalid offset : %s\n",
					argv[optind - 1]);
			opt_alloc_offs = ll;
			break;
		case 'h':
			usage(0);
		case '?':
		default:
			usage(1);
		}
	}
	if (!opt_alloc_len) {
		err_usage("Missing allocation length\n");
	}

	ntfs_log_verbose("length = %lli = 0x%llx\n",
			(long long)opt_alloc_len, (long long)opt_alloc_len);
	ntfs_log_verbose("offset = %lli = 0x%llx\n",
			(long long)opt_alloc_offs, (long long)opt_alloc_offs);

	if (optind == argc)
		usage(1);

	if (opts.verbose > 1)
		ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE |
			NTFS_LOG_LEVEL_VERBOSE | NTFS_LOG_LEVEL_QUIET);

	/* Get the device. */
	dev_name = argv[optind++];
	ntfs_log_verbose("device name = %s\n", dev_name);

	if (optind == argc)
		usage(1);

	/* Get the file name. */
	file_name = argv[optind++];
	ntfs_log_verbose("file name = \"%s\"\n", file_name);

	/* Get the attribute type, if specified. */
	if (optind == argc) {
		attr_type = AT_DATA;
		attr_name = AT_UNNAMED;
		attr_name_len = 0;
	} else {
		unsigned long ul;

		s = argv[optind++];
		ul = strtoul(s, &s2, 0);
		if (*s2 || !ul || (ul >= ULONG_MAX && errno == ERANGE))
			err_usage("Invalid attribute type %s: %s\n", s,
					strerror(errno));
		attr_type = cpu_to_le32(ul);

		/* Get the attribute name, if specified. */
		if (optind != argc) {
			s = argv[optind++];
			/* Convert the string to little endian Unicode. */
			attr_name_len = ntfs_mbstoucs(s, &attr_name);
			if ((int)attr_name_len < 0)
				err_usage("Invalid attribute name "
						"\"%s\": %s\n",
						s, strerror(errno));

			/* Keep hold of the original string. */
			s2 = s;

			s = argv[optind++];
			if (optind != argc)
				usage(1);
		} else {
			attr_name = AT_UNNAMED;
			attr_name_len = 0;
		}
	}
	ntfs_log_verbose("attribute type = 0x%lx\n",
					(unsigned long)le32_to_cpu(attr_type));
	if (attr_name == AT_UNNAMED)
		ntfs_log_verbose("attribute name = \"\" (UNNAMED)\n");
	else
		ntfs_log_verbose("attribute name = \"%s\" (length %u "
				"Unicode characters)\n", s2,
				(unsigned int)attr_name_len);
}
예제 #8
0
/**
 * parse_options
 */
static void parse_options(int argc, char *argv[])
{
	long long ll;
	char *s, *s2;
	int c;

	if (argc && *argv)
		EXEC_NAME = *argv;
	fprintf(stderr, "%s v%s (libntfs-3g)\n", EXEC_NAME, VERSION);
	while ((c = getopt(argc, argv, "fh?nqvVl")) != EOF)
		switch (c) {
		case 'f':
			opts.force = 1;
			break;
		case 'n':
			opts.no_action = 1;
			break;
		case 'q':
			opts.quiet = 1;
			ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET);
			break;
		case 'v':
			opts.verbose++;
			ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE);
			break;
		case 'V':
			/* Version number already printed, so just exit. */
			exit(0);
		case 'l':
			copyright();
			license();
			exit(0);
		case 'h':
		case '?':
		default:
			usage();
		}
	if (optind == argc)
		usage();

	if (opts.verbose > 1)
		ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE |
			NTFS_LOG_LEVEL_VERBOSE | NTFS_LOG_LEVEL_QUIET);

	/* Get the device. */
	dev_name = argv[optind++];
	ntfs_log_verbose("device name = %s\n", dev_name);

	if (optind == argc)
		usage();

	/* Get the inode. */
	ll = strtoll(argv[optind++], &s, 0);
	if (*s || !ll || (ll >= LLONG_MAX && errno == ERANGE))
		err_exit("Invalid inode number: %s\n", argv[optind - 1]);
	inode = ll;
	ntfs_log_verbose("inode = %lli\n", (long long)inode);

	if (optind == argc)
		usage();

	/* Get the attribute type, if specified. */
	s = argv[optind++];
	if (optind == argc) {
		attr_type = AT_DATA;
		attr_name = AT_UNNAMED;
		attr_name_len = 0;
	} else {
		unsigned long ul;

		ul = strtoul(s, &s2, 0);
		if (*s2 || !ul || (ul >= ULONG_MAX && errno == ERANGE))
			err_exit("Invalid attribute type %s: %s\n", s,
					strerror(errno));
		attr_type = ul;

		/* Get the attribute name, if specified. */
		s = argv[optind++];
		if (optind != argc) {
			/* Convert the string to little endian Unicode. */
			attr_name_len = ntfs_mbstoucs(s, &attr_name);
			if ((int)attr_name_len < 0)
				err_exit("Invalid attribute name \"%s\": %s\n",
						s, strerror(errno));

			/* Keep hold of the original string. */
			s2 = s;

			s = argv[optind++];
			if (optind != argc)
				usage();
		} else {
			attr_name = AT_UNNAMED;
			attr_name_len = 0;
		}
	}
	ntfs_log_verbose("attribute type = 0x%x\n", (unsigned int)attr_type);
	if (attr_name == AT_UNNAMED)
		ntfs_log_verbose("attribute name = \"\" (UNNAMED)\n");
	else
		ntfs_log_verbose("attribute name = \"%s\" (length %u Unicode "
				"characters)\n", s2,
				(unsigned int)attr_name_len);

	/* Get the new length. */
	ll = strtoll(s, &s2, 0);
	if (*s2 || ll < 0 || (ll >= LLONG_MAX && errno == ERANGE))
		err_exit("Invalid new length: %s\n", s);
	new_len = ll;
	ntfs_log_verbose("new length = %lli\n", (long long)new_len);
}