char * parse_name (char const *s, int strip_leading, char const **endp) { char *ret; while (ISSPACE ((unsigned char) *s)) s++; if (*s == '"') ret = parse_c_string (s, endp); else { char const *t; for (t = s; *t && ! ISSPACE ((unsigned char) *t); t++) /* do nothing*/ ; ret = savebuf (s, t - s + 1); ret[t - s] = 0; if (endp) *endp = t; } if (! strip_leading_slashes (ret, strip_leading)) { free (ret); ret = NULL; } return ret; }
void fetchname (char const *at, int strip_leading, char **pname, char **ptimestr, struct timespec *pstamp) { char *name; const char *t; char *timestr = NULL; struct timespec stamp; stamp.tv_sec = -1; stamp.tv_nsec = 0; while (ISSPACE ((unsigned char) *at)) at++; if (debug & 128) say ("fetchname %s %d\n", at, strip_leading); if (*at == '"') { name = parse_c_string (at, &t); if (! name) { if (debug & 128) say ("ignoring malformed filename %s\n", quotearg (at)); return; } } else { for (t = at; *t; t++) { if (ISSPACE ((unsigned char) *t)) { /* Allow file names with internal spaces, but only if a tab separates the file name from the date. */ char const *u = t; while (*u != '\t' && ISSPACE ((unsigned char) u[1])) u++; if (*u != '\t' && (strchr (u + 1, pstamp ? '\t' : '\n'))) continue; break; } } name = savebuf (at, t - at + 1); name[t - at] = 0; } /* If the name is "/dev/null", ignore the name and mark the file as being nonexistent. The name "/dev/null" appears in patches regardless of how NULL_DEVICE is spelled. */ if (strcmp (name, "/dev/null") == 0) { free (name); if (pstamp) { pstamp->tv_sec = 0; pstamp->tv_nsec = 0; } return; } /* Ignore the name if it doesn't have enough slashes to strip off. */ if (! strip_leading_slashes (name, strip_leading)) { free (name); return; } if (ptimestr) { char const *u = t + strlen (t); if (u != t && *(u-1) == '\n') u--; if (u != t && *(u-1) == '\r') u--; timestr = savebuf (t, u - t + 1); timestr[u - t] = 0; } if (*t != '\n') { if (! pstamp) { free (name); free (timestr); return; } if (set_time | set_utc) get_date (&stamp, t, &initial_time); else { /* The head says the file is nonexistent if the timestamp is the epoch; but the listed time is local time, not UTC, and POSIX.1 allows local time offset anywhere in the range -25:00 < offset < +26:00. Match any time in that range. */ const struct timespec lower = { -25L * 60 * 60 }, upper = { 26L * 60 * 60 }; if (get_date (&stamp, t, &initial_time) && timespec_cmp (stamp, lower) > 0 && timespec_cmp (stamp, upper) < 0) { stamp.tv_sec = 0; stamp.tv_nsec = 0; } } } free (*pname); *pname = name; if (ptimestr) { free (*ptimestr); *ptimestr = timestr; } if (pstamp) *pstamp = stamp; }
void do_set_xattr(int argc, char **argv) { ext2_ino_t ino; struct ext2_xattr_handle *h; FILE *fp = NULL; char *buf = NULL; size_t buflen; unsigned int handle_flags = 0; int i; errcode_t err; reset_getopt(); while ((i = getopt(argc, argv, "f:r")) != -1) { switch (i) { case 'f': if (fp) fclose(fp); fp = fopen(optarg, "r"); if (fp == NULL) { perror(optarg); return; } break; case 'r': handle_flags |= XATTR_HANDLE_FLAG_RAW; break; default: goto print_usage; } } if (!(fp && optind == argc - 2) && !(!fp && optind == argc - 3)) { print_usage: printf("Usage:\t%s [-r] <file> <attr> <value>\n", argv[0]); printf("\t%s -f <value_file> [-r] <file> <attr>\n", argv[0]); goto out2; } if (check_fs_open(argv[0])) goto out2; if (check_fs_read_write(argv[0])) goto out2; if (check_fs_bitmaps(argv[0])) goto out2; ino = string_to_inode(argv[optind]); if (!ino) goto out2; err = ext2fs_xattrs_open(current_fs, ino, &h); if (err) goto out2; err = ext2fs_xattrs_flags(h, &handle_flags, NULL); if (err) goto out; err = ext2fs_xattrs_read(h); if (err) goto out; if (fp) { err = ext2fs_get_mem(current_fs->blocksize, &buf); if (err) goto out; buflen = fread(buf, 1, current_fs->blocksize, fp); } else { buf = argv[optind + 2]; buflen = parse_c_string(buf); } err = ext2fs_xattr_set(h, argv[optind + 1], buf, buflen); out: ext2fs_xattrs_close(&h); if (err) com_err(argv[0], err, "while setting extended attribute"); out2: if (fp) { fclose(fp); ext2fs_free_mem(&buf); } }