diff --git a/zdev/include/exit_code.h b/zdev/include/exit_code.h index 090fbf6c..7f0e4ba4 100644 --- a/zdev/include/exit_code.h +++ b/zdev/include/exit_code.h @@ -54,6 +54,9 @@ typedef enum { EXIT_GROUP_FAILED = 31, /* CCW group device grouping failed */ EXIT_UNGROUP_FAILED = 32, /* CCW group device ungrouping failed */ + /* is-owner related */ + EXIT_UNKNOWN_FILE = 33, /* The file is not generated by chzdev */ + EXIT_INTERNAL_ERROR = 99, /* An internal error occurred */ } exit_code_t; diff --git a/zdev/include/zdev.h b/zdev/include/zdev.h index 11dcfacd..5f82179b 100644 --- a/zdev/include/zdev.h +++ b/zdev/include/zdev.h @@ -24,6 +24,7 @@ #define NUM_SITES 11 #define NUM_USER_SITES (NUM_SITES - 1) #define SITE_FALLBACK NUM_USER_SITES +#define CHZDEV_HEADER "# Generated by chzdev" /* Helper to find the availability of site-configuration */ #define dev_site_configured(dev, x) (dev->site_specific[(x)].exists && \ diff --git a/zdev/man/chzdev.8 b/zdev/man/chzdev.8 index 498790b1..556d7cfa 100644 --- a/zdev/man/chzdev.8 +++ b/zdev/man/chzdev.8 @@ -601,6 +601,18 @@ Combining apparently inconsistent settings .PP .RE . +.OD is-owner "" "FILENAME" +Detect if the file mentioned is generated by zdev tools. + +Return 0 if the +.IR FILENAME +is generated by zdev tools and 33 otherwise. + +.B Example: +.CL chzdev --is-owner /etc/udev/rules/41-dasd-0.0.1234.rules + +.PP +. .OD no-root-update "" "" Skip root device update. @@ -916,6 +928,14 @@ CCW group device: Grouping failed CCW group device: Ungrouping failed .PP .TP +.B 33 +The file specified by +.nh +\-\-is-owner +.hy +is not generated by zdev +.PP +.TP .B 99 An internal error occurred .PP diff --git a/zdev/src/chzdev.c b/zdev/src/chzdev.c index 8b2a8db4..1b29471f 100644 --- a/zdev/src/chzdev.c +++ b/zdev/src/chzdev.c @@ -50,6 +50,7 @@ * diff of simple function parameter modifications to pass this value. */ int global_site_id = SITE_FALLBACK; +#define MAX_HEADER_LENGTH sizeof(CHZDEV_HEADER) /* Main program action. */ typedef enum { @@ -60,6 +61,7 @@ typedef enum { ACT_HELP_ATTRIBS, ACT_EXPORT, ACT_IMPORT, + ACT_IS_OWNER, ACT_APPLY, ACT_HELP, ACT_VERSION, @@ -86,6 +88,7 @@ struct options { unsigned int help_attribs:1; char *export; char *import; + char *is_owner; unsigned int apply:1; unsigned int help:1; unsigned int version:1; @@ -134,6 +137,7 @@ enum { OPT_LIST_TYPES = 'L', OPT_EXPORT = (OPT_ANONYMOUS_BASE+__COUNTER__), OPT_IMPORT = (OPT_ANONYMOUS_BASE+__COUNTER__), + OPT_IS_OWNER = (OPT_ANONYMOUS_BASE+__COUNTER__), OPT_APPLY = (OPT_ANONYMOUS_BASE+__COUNTER__), OPT_ACTIVE = 'a', OPT_PERSISTENT = 'p', @@ -187,6 +191,13 @@ static struct opts_conflict conflict_list[] = { OPT_REMOVE_ALL, OPT_CONFIGURED, OPT_EXISTING, OPT_BY_PATH, OPT_BY_ATTRIB, OPT_BY_NODE, OPT_BY_INTERFACE, OPT_DECONFIGURE_ALL, 0), + OPTS_CONFLICT(OPT_IS_OWNER, + OPT_DECONFIGURE, OPT_HELP_ATTRIBS, OPT_LIST_TYPES, + OPT_EXPORT, OPT_IMPORT, OPT_APPLY, OPT_REMOVE, + OPT_REMOVE_ALL, OPT_CONFIGURED, OPT_EXISTING, OPT_ONLINE, + OPT_OFFLINE, OPT_BY_PATH, OPT_BY_NODE, OPT_BY_INTERFACE, + OPT_BY_ATTRIB, OPT_ACTIVE, OPT_PERSISTENT, OPT_FAILED, + OPT_DECONFIGURE_ALL, 0), OPTS_CONFLICT(OPT_APPLY, OPT_DECONFIGURE, OPT_LIST_ATTRIBS, OPT_HELP_ATTRIBS, OPT_LIST_TYPES, OPT_EXPORT, OPT_IMPORT, OPT_REMOVE, @@ -227,6 +238,7 @@ static const struct option opt_list[] = { { "list-types", no_argument, NULL, OPT_LIST_TYPES }, { "export", required_argument, NULL, OPT_EXPORT }, { "import", required_argument, NULL, OPT_IMPORT }, + { "is-owner", required_argument, NULL, OPT_IS_OWNER }, { "apply", no_argument, NULL, OPT_APPLY }, { "help", no_argument, NULL, OPT_HELP }, { "version", no_argument, NULL, OPT_VERSION }, @@ -278,6 +290,7 @@ static void free_options(struct options *opts) return; free(opts->export); free(opts->import); + free(opts->is_owner); select_opts_free(opts->select); strlist_free(opts->positional); strlist_free(opts->settings); @@ -318,6 +331,8 @@ static action_t get_action(struct options *opts) return ACT_EXPORT; if (opts->import) return ACT_IMPORT; + if (opts->is_owner) + return ACT_IS_OWNER; if (opts->apply) return ACT_APPLY; return ACT_CONFIGURE; @@ -339,6 +354,8 @@ static const char *get_action_option(action_t action) return "--export"; case ACT_IMPORT: return "--import"; + case ACT_IS_OWNER: + return "--is-owner"; case ACT_APPLY: return "--apply"; case ACT_HELP: @@ -902,6 +919,16 @@ static exit_code_t parse_options(struct options *opts, int argc, char *argv[]) opts->import = misc_strdup(optarg); break; + case OPT_IS_OWNER: + /* --is-owner */ + if (opts->is_owner) { + error("Cannot specify '--is-owner' multiple " + "times\n"); + return EXIT_USAGE_ERROR; + } + opts->is_owner = misc_strdup(optarg); + break; + case OPT_APPLY: /* --apply */ opts->apply = 1; @@ -2929,6 +2956,39 @@ static void apply_selection_to_import(struct util_list *objects, } } +static exit_code_t zdev_file_detect(FILE *fd) +{ + char buffer[MAX_HEADER_LENGTH]; + + if (fgets(buffer, MAX_HEADER_LENGTH, fd)) { + if (starts_with(buffer, CHZDEV_HEADER)) + return EXIT_OK; + } else { + return EXIT_RUNTIME_ERROR; + } + + return EXIT_UNKNOWN_FILE; +} + +/* Check if the file mentioned is generated by zdev */ +static exit_code_t do_is_owner(struct options *opts) +{ + FILE *fd; + exit_code_t rc = EXIT_OK; + + fd = fopen(opts->is_owner, "r"); + if (!fd) { + error("Could not open file %s: %s\n", opts->is_owner, + strerror(errno)); + return EXIT_RUNTIME_ERROR; + } + + rc = zdev_file_detect(fd); + + fclose(fd); + return rc; +} + /* Import configuration data. */ static exit_code_t do_import(struct options *opts) { @@ -3137,6 +3197,9 @@ int main(int argc, char *argv[]) case ACT_IMPORT: rc = do_import(&opts); break; + case ACT_IS_OWNER: + rc = do_is_owner(&opts); + break; case ACT_APPLY: rc = do_apply(&opts); break; diff --git a/zdev/src/chzdev_usage.txt b/zdev/src/chzdev_usage.txt index 7e81ea73..ab9cd854 100644 --- a/zdev/src/chzdev_usage.txt +++ b/zdev/src/chzdev_usage.txt @@ -58,5 +58,6 @@ OPTIONS --no-settle Do not wait for udev to settle --auto-conf Apply changes to auto-configuration only -s, --site ID Apply changes to the specified site only + --is-owner FILE Examine whether the file is generated by zdev -V, --verbose Print additional run-time information -q, --quiet Print only minimal run-time information