+ return 0;
+
+ case 'g':
+ case_s_continued: // -s, see above
+ case opt_set: // --set
+ {
+ ataopts.get_set_used = true;
+ bool get = (optchar == 'g');
+ char name[16+1]; unsigned val;
+ int n1 = -1, n2 = -1, n3 = -1, len = strlen(optarg);
+ if (sscanf(optarg, "%16[^,=]%n%*[,=]%n%u%n", name, &n1, &n2, &val, &n3) >= 1
+ && (n1 == len || (!get && n2 > 0))) {
+ bool on = false;
+ bool off = false;
+ bool ata = false;
+ bool persistent = false;
+
+ if (n2 > 0) {
+ int len2 = strlen(optarg + n2);
+ char * tmp = strstr(optarg+n2, ",p");
+ // handle ",p" in persistent options like: wcache-sct,[ata|on|off],p
+ if (tmp && (strlen(tmp) == 2)) {
+ persistent = true;
+ len2 = strlen(optarg+n2) - 2;
+
+ // the ,p option only works for set of SCT Feature Control command
+ if (strcmp(name, "wcache-sct") != 0 &&
+ strcmp(name, "wcreorder") != 0)
+ badarg = true;
+ }
+ on = !strncmp(optarg+n2, "on", len2);
+ off = !strncmp(optarg+n2, "off", len2);
+ ata = !strncmp(optarg+n2, "ata", len2);
+ }
+ if (n3 != len)
+ val = ~0U;
+
+ if (get && !strcmp(name, "all")) {
+ ataopts.get_aam = ataopts.get_apm = true;
+ ataopts.get_security = true;
+ ataopts.get_lookahead = ataopts.get_wcache = true;
+ ataopts.get_dsn = true;
+ scsiopts.get_rcd = scsiopts.get_wce = true;
+ }
+ else if (!strcmp(name, "aam")) {
+ if (get)
+ ataopts.get_aam = true;
+ else if (off)
+ ataopts.set_aam = -1;
+ else if (val <= 254)
+ ataopts.set_aam = val + 1;
+ else {
+ snprintf(extraerror, sizeof(extraerror), "Option -s aam,N must have 0 <= N <= 254\n");
+ badarg = true;
+ }
+ }
+ else if (!strcmp(name, "apm")) {
+ if (get)
+ ataopts.get_apm = true;
+ else if (off)
+ ataopts.set_apm = -1;
+ else if (1 <= val && val <= 254)
+ ataopts.set_apm = val + 1;
+ else {
+ snprintf(extraerror, sizeof(extraerror), "Option -s apm,N must have 1 <= N <= 254\n");
+ badarg = true;
+ }
+ }
+ else if (!strcmp(name, "lookahead")) {
+ if (get) {
+ ataopts.get_lookahead = true;
+ }
+ else if (off)
+ ataopts.set_lookahead = -1;
+ else if (on)
+ ataopts.set_lookahead = 1;
+ else
+ badarg = true;
+ }
+ else if (!strcmp(name, "wcreorder")) {
+ ataopts.sct_wcache_reorder_set_pers = persistent;
+ if (get) {
+ ataopts.sct_wcache_reorder_get = true;
+ }
+ else if (off)
+ ataopts.sct_wcache_reorder_set = -1;
+ else if (on)
+ ataopts.sct_wcache_reorder_set = 1;
+ else
+ badarg = true;
+ }
+ else if (!strcmp(name, "wcache-sct")) {
+ ataopts.sct_wcache_sct_set_pers = persistent;
+ if (get) {
+ ataopts.sct_wcache_sct_get = true;
+ }
+ else if (off)
+ ataopts.sct_wcache_sct_set = 3;
+ else if (on)
+ ataopts.sct_wcache_sct_set = 2;
+ else if (ata)
+ ataopts.sct_wcache_sct_set = 1;
+ else
+ badarg = true;
+ }
+ else if (!strcmp(name, "rcache")) {
+ if (get)
+ scsiopts.get_rcd = true;
+ else if (off)
+ scsiopts.set_rcd = -1;
+ else if (on)
+ scsiopts.set_rcd = 1;
+ else
+ badarg = true;
+ }
+ else if (get && !strcmp(name, "security")) {
+ ataopts.get_security = true;
+ }
+ else if (!get && !strcmp(optarg, "security-freeze")) {
+ ataopts.set_security_freeze = true;
+ }
+ else if (!get && !strcmp(optarg, "standby,now")) {
+ ataopts.set_standby_now = true;
+ }
+ else if (!get && !strcmp(name, "standby")) {
+ if (off)
+ ataopts.set_standby = 0 + 1;
+ else if (val <= 255)
+ ataopts.set_standby = val + 1;
+ else {
+ snprintf(extraerror, sizeof(extraerror), "Option -s standby,N must have 0 <= N <= 255\n");
+ badarg = true;
+ }
+ }
+ else if (!strcmp(name, "wcache")) {
+ if (get) {
+ ataopts.get_wcache = true;
+ scsiopts.get_wce = true;
+ }
+ else if (off) {
+ ataopts.set_wcache = -1;
+ scsiopts.set_wce = -1;
+ }
+ else if (on) {
+ ataopts.set_wcache = 1;
+ scsiopts.set_wce = 1;
+ }
+ else
+ badarg = true;
+ }
+ else if (!strcmp(name, "dsn")) {
+ if (get) {
+ ataopts.get_dsn = true;
+ }
+ else if (off) {
+ ataopts.set_dsn = -1;
+ }
+ else if (on) {
+ ataopts.set_dsn = 1;
+ }
+ else
+ badarg = true;
+ }
+ else
+ badarg = true;
+ }
+ else
+ badarg = true;
+ }
+ break;
+
+ case opt_scan:
+ case opt_scan_open:
+ scan = optchar;
+ break;
+
+ case 'j':
+ {
+ print_as_json = true;
+ print_as_json_options.pretty = true;
+ print_as_json_options.sorted = false;
+ print_as_json_options.flat = false;
+ print_as_json_output = false;
+ print_as_json_impl = print_as_json_unimpl = false;
+ bool json_verbose = false;
+ if (optarg_is_set) {
+ for (int i = 0; optarg[i]; i++) {
+ switch (optarg[i]) {
+ case 'c': print_as_json_options.pretty = false; break;
+ case 'g': print_as_json_options.flat = true; break;
+ case 'i': print_as_json_impl = true; break;
+ case 'o': print_as_json_output = true; break;
+ case 's': print_as_json_options.sorted = true; break;
+ case 'u': print_as_json_unimpl = true; break;
+ case 'v': json_verbose = true; break;
+ default: badarg = true;
+ }
+ }
+ }
+ js_initialize(argc, argv, json_verbose);
+ }