- int c, rc;
- int ret = 0;
- time_t t;
- struct find_param param = {
- .fp_max_depth = -1,
- .fp_quiet = 1,
- .fp_time_margin = 24 * 60 * 60,
- };
- struct option long_opts[] = {
- { .val = 'A', .name = "atime", .has_arg = required_argument },
- { .val = 'b', .name = "blocks", .has_arg = required_argument },
- { .val = LFS_COMP_COUNT_OPT,
- .name = "comp-count", .has_arg = required_argument },
- { .val = LFS_COMP_COUNT_OPT,
- .name = "component-count",
- .has_arg = required_argument },
- { .val = LFS_COMP_FLAGS_OPT,
- .name = "comp-flags", .has_arg = required_argument },
- { .val = LFS_COMP_FLAGS_OPT,
- .name = "component-flags",
- .has_arg = required_argument },
- { .val = LFS_COMP_START_OPT,
- .name = "comp-start", .has_arg = required_argument },
- { .val = LFS_COMP_START_OPT,
- .name = "component-start",
- .has_arg = required_argument },
- { .val = LFS_MIRROR_STATE_OPT,
- .name = "mirror-state", .has_arg = required_argument },
- { .val = LFS_LAYOUT_FOREIGN_OPT,
- .name = "foreign", .has_arg = optional_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "newer", .has_arg = required_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "neweraa", .has_arg = required_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "neweram", .has_arg = required_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "newerac", .has_arg = required_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "newerma", .has_arg = required_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "newermm", .has_arg = required_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "newermc", .has_arg = required_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "newerca", .has_arg = required_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "newercm", .has_arg = required_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "newercc", .has_arg = required_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "newerat", .has_arg = required_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "newermt", .has_arg = required_argument},
- { .val = LFS_NEWERXY_OPT,
- .name = "newerct", .has_arg = required_argument},
- { .val = 'c', .name = "stripe-count", .has_arg = required_argument },
- { .val = 'c', .name = "stripe_count", .has_arg = required_argument },
- { .val = 'C', .name = "ctime", .has_arg = required_argument },
-/* getstripe { .val = 'd', .name = "directory", .has_arg = no_argument }, */
- { .val = 'D', .name = "maxdepth", .has_arg = required_argument },
- { .val = 'E', .name = "comp-end", .has_arg = required_argument },
- { .val = 'E', .name = "component-end",
- .has_arg = required_argument },
-/* find { .val = 'F', .name = "fid", .has_arg = no_argument }, */
- { .val = LFS_LAYOUT_FOREIGN_OPT,
- .name = "foreign", .has_arg = optional_argument},
- { .val = 'g', .name = "gid", .has_arg = required_argument },
- { .val = 'G', .name = "group", .has_arg = required_argument },
- { .val = 'H', .name = "mdt-hash", .has_arg = required_argument },
- { .val = 'i', .name = "stripe-index", .has_arg = required_argument },
- { .val = 'i', .name = "stripe_index", .has_arg = required_argument },
-/* getstripe { .val = 'I', .name = "comp-id", .has_arg = required_argument }*/
- { .val = 'l', .name = "lazy", .has_arg = no_argument },
- { .val = 'L', .name = "layout", .has_arg = required_argument },
+ int loop;
+ int user, group, other;
+ int who, all;
+ char c, op;
+ mode_t perm;
+ mode_t usermask;
+ mode_t previous_flags;
+
+ user = group = other = 0;
+ all = 0;
+ loop = 1;
+ perm = 0;
+ previous_flags = 0;
+ *end = input;
+ usermask = 0;
+
+ while (loop) {
+ switch (*input) {
+ case 'u':
+ user = 1;
+ break;
+ case 'g':
+ group = 1;
+ break;
+ case 'o':
+ other = 1;
+ break;
+ case 'a':
+ user = group = other = 1;
+ all = 1;
+ break;
+ default:
+ loop = 0;
+ }
+
+ if (loop)
+ input++;
+ }
+
+ who = user || group || other;
+ if (!who) {
+ /* get the umask */
+ usermask = umask(0022);
+ umask(usermask);
+ usermask &= 07777;
+ }
+
+ if (*input == '-' || *input == '+' || *input == '=')
+ op = *input++;
+ else
+ /* operation is required */
+ return -1;
+
+ /* get the flags in *outmode */
+ switch (*input) {
+ case 'u':
+ previous_flags = (*outmode & 0700);
+ perm |= user ? previous_flags : 0;
+ perm |= group ? (previous_flags >> 3) : 0;
+ perm |= other ? (previous_flags >> 6) : 0;
+ input++;
+ goto write_perm;
+ case 'g':
+ previous_flags = (*outmode & 0070);
+ perm |= user ? (previous_flags << 3) : 0;
+ perm |= group ? previous_flags : 0;
+ perm |= other ? (previous_flags >> 3) : 0;
+ input++;
+ goto write_perm;
+ case 'o':
+ previous_flags = (*outmode & 0007);
+ perm |= user ? (previous_flags << 6) : 0;
+ perm |= group ? (previous_flags << 3) : 0;
+ perm |= other ? previous_flags : 0;
+ input++;
+ goto write_perm;
+ default:
+ break;
+ }
+
+ /* this part is optional,
+ * if empty perm = 0 and *outmode is not modified
+ */
+ loop = 1;
+ while (loop) {
+ c = *input;
+ switch (c) {
+ case 'r':
+ perm |= user ? 0400 : 0;
+ perm |= group ? 0040 : 0;
+ perm |= other ? 0004 : 0;
+ /* set read permission for uog except for umask's
+ * permissions
+ */
+ perm |= who ? 0 : (0444 & ~usermask);
+ break;
+ case 'w':
+ perm |= user ? 0200 : 0;
+ perm |= group ? 0020 : 0;
+ perm |= other ? 0002 : 0;
+ /* set write permission for uog except for umask'
+ * permissions
+ */
+ perm |= who ? 0 : (0222 & ~usermask);
+ break;
+ case 'x':
+ perm |= user ? 0100 : 0;
+ perm |= group ? 0010 : 0;
+ perm |= other ? 0001 : 0;
+ /* set execute permission for uog except for umask'
+ * permissions
+ */
+ perm |= who ? 0 : (0111 & ~usermask);
+ break;
+ case 'X':
+ /*
+ * Adds execute permission to 'u', 'g' and/or 'g' if
+ * specified and either 'u', 'g' or 'o' already has
+ * execute permissions.
+ */
+ if ((*outmode & 0111) != 0) {
+ perm |= user ? 0100 : 0;
+ perm |= group ? 0010 : 0;
+ perm |= other ? 0001 : 0;
+ perm |= !who ? 0111 : 0;
+ }
+ break;
+ case 's':
+ /* s is ignored if o is given, but it's not an error */
+ if (other && !group && !user)
+ break;
+ perm |= user ? S_ISUID : 0;
+ perm |= group ? S_ISGID : 0;
+ break;
+ case 't':
+ /* 't' should be used when 'a' is given
+ * or who is empty
+ */
+ perm |= (!who || all) ? S_ISVTX : 0;
+ /* using ugo with t is not an error */
+ break;
+ default:
+ loop = 0;
+ break;
+ }
+ if (loop)
+ input++;
+ }
+
+write_perm:
+ /* uog flags should be only one character long */
+ if (previous_flags && (*input != '\0' && *input != ','))
+ return -1;
+
+ switch (op) {
+ case '-':
+ /* remove the flags from outmode */
+ *outmode &= ~perm;
+ break;
+ case '+':
+ /* add the flags to outmode */
+ *outmode |= perm;
+ break;
+ case '=':
+ /* set the flags of outmode to perm */
+ if (perm != 0)
+ *outmode = perm;
+ break;
+ }
+
+ *end = input;
+ return 0;
+}
+
+static int str2mode_t(const char *input, mode_t *outmode)
+{
+ int ret;
+ const char *iter;
+
+ ret = 0;
+
+ if (*input >= '0' && *input <= '7') {
+ /* parse octal representation */
+ char *end;
+
+ iter = input;
+
+ /* look for invalid digits in octal representation */
+ while (isdigit(*iter))
+ if (*iter++ > '7')
+ return -1;
+
+ errno = 0;
+ *outmode = strtoul(input, &end, 8);
+
+ if (errno != 0 || *outmode > 07777) {
+ *outmode = 0;
+ ret = -1;
+ }
+
+ } else if (*input == '8' || *input == '9') {
+ /* error: invalid octal number */
+ ret = -1;
+ } else {
+ /* parse coma seperated list of symbolic representation */
+ int rc;
+ const char *end;
+
+ *outmode = 0;
+ rc = 0;
+ end = NULL;
+
+ do {
+ rc = parse_symbolic(input, outmode, &end);
+ if (rc)
+ return -1;
+
+ input = end+1;
+ } while (*end == ',');
+
+ if (*end != '\0')
+ ret = -1;
+ }
+ return ret;
+}
+
+static int lfs_find(int argc, char **argv)
+{
+ int c, rc;
+ int ret = 0;
+ time_t t;
+ struct find_param param = {
+ .fp_max_depth = -1,
+ .fp_quiet = 1,
+ .fp_time_margin = FP_DEFAULT_TIME_MARGIN,
+ };
+ struct option long_opts[] = {
+ { .val = 'A', .name = "atime", .has_arg = required_argument },
+ { .val = 'b', .name = "blocks", .has_arg = required_argument },
+ { .val = 'B', .name = "btime", .has_arg = required_argument },
+ { .val = 'B', .name = "Btime", .has_arg = required_argument },
+ { .val = LFS_COMP_COUNT_OPT,
+ .name = "comp-count", .has_arg = required_argument },
+ { .val = LFS_COMP_COUNT_OPT,
+ .name = "component-count",
+ .has_arg = required_argument },
+ { .val = LFS_COMP_FLAGS_OPT,
+ .name = "comp-flags", .has_arg = required_argument },
+ { .val = LFS_COMP_FLAGS_OPT,
+ .name = "component-flags",
+ .has_arg = required_argument },
+ { .val = LFS_COMP_START_OPT,
+ .name = "comp-start", .has_arg = required_argument },
+ { .val = LFS_COMP_START_OPT,
+ .name = "component-start",
+ .has_arg = required_argument },
+ { .val = LFS_MIRROR_STATE_OPT,
+ .name = "mirror-state", .has_arg = required_argument },
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newer", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "neweraa", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "neweram", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerac", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerab", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerma", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newermm", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newermc", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newermb", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerca", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newercm", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newercc", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newercb", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerba", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerbm", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerbc", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerbb", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerBa", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerBm", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerBc", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerBB", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerat", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newermt", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerct", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerbt", .has_arg = required_argument},
+ { .val = LFS_NEWERXY_OPT,
+ .name = "newerBt", .has_arg = required_argument},
+ { .val = 'c', .name = "stripe-count", .has_arg = required_argument },
+ { .val = 'c', .name = "stripe_count", .has_arg = required_argument },
+ { .val = 'C', .name = "ctime", .has_arg = required_argument },
+/* getstripe { .val = 'd', .name = "directory", .has_arg = no_argument }, */
+ { .val = 'D', .name = "maxdepth", .has_arg = required_argument },
+ { .val = 'E', .name = "comp-end", .has_arg = required_argument },
+ { .val = 'E', .name = "component-end",
+ .has_arg = required_argument },
+/* find { .val = 'F', .name = "fid", .has_arg = no_argument }, */
+ { .val = LFS_LAYOUT_FOREIGN_OPT,
+ .name = "foreign", .has_arg = optional_argument},
+ { .val = 'g', .name = "gid", .has_arg = required_argument },
+ { .val = 'G', .name = "group", .has_arg = required_argument },
+ { .val = 'h', .name = "help", .has_arg = no_argument },
+ { .val = 'H', .name = "mdt-hash", .has_arg = required_argument },
+ { .val = 'i', .name = "stripe-index", .has_arg = required_argument },
+ { .val = 'i', .name = "stripe_index", .has_arg = required_argument },
+/* getstripe { .val = 'I', .name = "comp-id", .has_arg = required_argument }*/
+ { .val = 'l', .name = "lazy", .has_arg = no_argument },
+ { .val = 'L', .name = "layout", .has_arg = required_argument },