Annotation of embedaddon/rsync/tls.c, revision 1.1.1.3
1.1 misho 1: /*
2: * Trivial ls for comparing two directories after running an rsync.
3: *
4: * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
1.1.1.3 ! misho 5: * Copyright (C) 2003-2015 Wayne Davison
1.1 misho 6: *
7: * This program is free software; you can redistribute it and/or modify
8: * it under the terms of the GNU General Public License as published by
9: * the Free Software Foundation; either version 3 of the License, or
10: * (at your option) any later version.
11: *
12: * This program is distributed in the hope that it will be useful,
13: * but WITHOUT ANY WARRANTY; without even the implied warranty of
14: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: * GNU General Public License for more details.
16: *
17: * You should have received a copy of the GNU General Public License along
18: * with this program; if not, write to the Free Software Foundation, Inc.,
19: * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
20: */
21:
22: /* The problem with using the system's own ls is that some features
23: * have little quirks that make directories look different when for
24: * our purposes they're the same -- for example, the BSD braindamage
25: * about setting the mode on symlinks based on your current umask.
26: *
27: * All the filenames must be given on the command line -- tls does not
28: * even read directories, let alone recurse. The typical usage is
29: * "find|sort|xargs tls".
30: *
31: * The format is not exactly the same as any particular Unix ls(1).
32: *
33: * A key requirement for this program is that the output be "very
34: * reproducible." So we mask away information that can accidentally
35: * change. */
36:
37: #include "rsync.h"
38: #include <popt.h>
39: #include "lib/sysxattrs.h"
40:
41: #define PROGRAM "tls"
42:
43: /* These are to make syscall.o shut up. */
44: int dry_run = 0;
45: int am_root = 0;
1.1.1.2 misho 46: int am_sender = 1;
1.1 misho 47: int read_only = 1;
48: int list_only = 0;
49: int link_times = 0;
50: int link_owner = 0;
1.1.1.2 misho 51: int nsec_times = 0;
1.1 misho 52: int preserve_perms = 0;
53: int preserve_executability = 0;
54:
55: #ifdef SUPPORT_XATTRS
56:
57: #ifdef HAVE_LINUX_XATTRS
58: #define XSTAT_ATTR "user.rsync.%stat"
59: #else
60: #define XSTAT_ATTR "rsync.%stat"
61: #endif
62:
63: static int stat_xattr(const char *fname, STRUCT_STAT *fst)
64: {
65: int mode, rdev_major, rdev_minor, uid, gid, len;
66: char buf[256];
67:
68: if (am_root >= 0 || IS_DEVICE(fst->st_mode) || IS_SPECIAL(fst->st_mode))
69: return -1;
70:
71: len = sys_lgetxattr(fname, XSTAT_ATTR, buf, sizeof buf - 1);
72: if (len >= (int)sizeof buf) {
73: len = -1;
74: errno = ERANGE;
75: }
76: if (len < 0) {
77: if (errno == ENOTSUP || errno == ENOATTR)
78: return -1;
79: if (errno == EPERM && S_ISLNK(fst->st_mode)) {
80: fst->st_uid = 0;
81: fst->st_gid = 0;
82: return 0;
83: }
84: fprintf(stderr, "failed to read xattr %s for %s: %s\n",
85: XSTAT_ATTR, fname, strerror(errno));
86: return -1;
87: }
88: buf[len] = '\0';
89:
90: if (sscanf(buf, "%o %d,%d %d:%d",
91: &mode, &rdev_major, &rdev_minor, &uid, &gid) != 5) {
92: fprintf(stderr, "Corrupt %s xattr attached to %s: \"%s\"\n",
93: XSTAT_ATTR, fname, buf);
94: exit(1);
95: }
96:
97: #if _S_IFLNK != 0120000
98: if ((mode & (_S_IFMT)) == 0120000)
99: mode = (mode & ~(_S_IFMT)) | _S_IFLNK;
100: #endif
101: fst->st_mode = mode;
102:
103: fst->st_rdev = MAKEDEV(rdev_major, rdev_minor);
104: fst->st_uid = uid;
105: fst->st_gid = gid;
106:
107: return 0;
108: }
109:
110: #endif
111:
112: static void failed(char const *what, char const *where)
113: {
114: fprintf(stderr, PROGRAM ": %s %s: %s\n",
115: what, where, strerror(errno));
116: exit(1);
117: }
118:
119: static void list_file(const char *fname)
120: {
121: STRUCT_STAT buf;
122: char permbuf[PERMSTRING_SIZE];
123: struct tm *mt;
124: char datebuf[50];
125: char linkbuf[4096];
126:
127: if (do_lstat(fname, &buf) < 0)
128: failed("stat", fname);
129: #ifdef SUPPORT_XATTRS
130: if (am_root < 0)
131: stat_xattr(fname, &buf);
132: #endif
133:
134: /* The size of anything but a regular file is probably not
135: * worth thinking about. */
136: if (!S_ISREG(buf.st_mode))
137: buf.st_size = 0;
138:
139: /* On some BSD platforms the mode bits of a symlink are
140: * undefined. Also it tends not to be possible to reset a
141: * symlink's mtime, so we default to ignoring it too. */
142: if (S_ISLNK(buf.st_mode)) {
143: int len;
144: buf.st_mode &= ~0777;
145: if (!link_times)
146: buf.st_mtime = (time_t)0;
147: if (!link_owner)
148: buf.st_uid = buf.st_gid = 0;
149: strlcpy(linkbuf, " -> ", sizeof linkbuf);
150: /* const-cast required for silly UNICOS headers */
1.1.1.2 misho 151: len = do_readlink((char *) fname, linkbuf+4, sizeof(linkbuf) - 4);
1.1 misho 152: if (len == -1)
1.1.1.2 misho 153: failed("do_readlink", fname);
1.1 misho 154: else
155: /* it's not nul-terminated */
156: linkbuf[4+len] = 0;
157: } else {
158: linkbuf[0] = 0;
159: }
160:
161: permstring(permbuf, buf.st_mode);
162:
163: if (buf.st_mtime) {
1.1.1.2 misho 164: int len;
1.1 misho 165: mt = gmtime(&buf.st_mtime);
166:
1.1.1.2 misho 167: len = snprintf(datebuf, sizeof datebuf,
1.1 misho 168: "%04d-%02d-%02d %02d:%02d:%02d",
169: (int)mt->tm_year + 1900,
170: (int)mt->tm_mon + 1,
171: (int)mt->tm_mday,
172: (int)mt->tm_hour,
173: (int)mt->tm_min,
174: (int)mt->tm_sec);
1.1.1.2 misho 175: #ifdef ST_MTIME_NSEC
176: if (nsec_times) {
177: snprintf(datebuf + len, sizeof datebuf - len,
178: ".%09d", (int)buf.ST_MTIME_NSEC);
179: }
180: #endif
181: } else {
182: int len = MIN(19 + 9*nsec_times, (int)sizeof datebuf - 1);
183: memset(datebuf, ' ', len);
184: datebuf[len] = '\0';
185: }
1.1 misho 186:
187: /* TODO: Perhaps escape special characters in fname? */
188:
189: printf("%s ", permbuf);
190: if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)) {
191: printf("%5ld,%6ld",
192: (long)major(buf.st_rdev),
193: (long)minor(buf.st_rdev));
1.1.1.2 misho 194: } else
195: printf("%15s", do_big_num(buf.st_size, 1, NULL));
1.1 misho 196: printf(" %6ld.%-6ld %6ld %s %s%s\n",
197: (long)buf.st_uid, (long)buf.st_gid, (long)buf.st_nlink,
198: datebuf, fname, linkbuf);
199: }
200:
201: static struct poptOption long_options[] = {
202: /* longName, shortName, argInfo, argPtr, value, descrip, argDesc */
203: {"link-times", 'l', POPT_ARG_NONE, &link_times, 0, 0, 0 },
204: {"link-owner", 'L', POPT_ARG_NONE, &link_owner, 0, 0, 0 },
205: #ifdef SUPPORT_XATTRS
206: {"fake-super", 'f', POPT_ARG_VAL, &am_root, -1, 0, 0 },
207: #endif
1.1.1.2 misho 208: #ifdef ST_MTIME_NSEC
209: {"nsec", 's', POPT_ARG_NONE, &nsec_times, 0, 0, 0 },
210: #endif
1.1 misho 211: {"help", 'h', POPT_ARG_NONE, 0, 'h', 0, 0 },
212: {0,0,0,0,0,0,0}
213: };
214:
215: static void tls_usage(int ret)
216: {
217: FILE *F = ret ? stderr : stdout;
218: fprintf(F,"usage: " PROGRAM " [OPTIONS] FILE ...\n");
219: fprintf(F,"Trivial file listing program for portably checking rsync\n");
220: fprintf(F,"\nOptions:\n");
221: fprintf(F," -l, --link-times display the time on a symlink\n");
222: fprintf(F," -L, --link-owner display the owner+group on a symlink\n");
223: #ifdef SUPPORT_XATTRS
224: fprintf(F," -f, --fake-super display attributes including fake-super xattrs\n");
225: #endif
226: fprintf(F," -h, --help show this help\n");
227: exit(ret);
228: }
229:
230: int
231: main(int argc, char *argv[])
232: {
233: poptContext pc;
234: const char **extra_args;
235: int opt;
236:
237: pc = poptGetContext(PROGRAM, argc, (const char **)argv,
238: long_options, 0);
239: while ((opt = poptGetNextOpt(pc)) != -1) {
240: switch (opt) {
241: case 'h':
242: tls_usage(0);
243: default:
244: fprintf(stderr,
245: "%s: %s\n",
246: poptBadOption(pc, POPT_BADOPTION_NOALIAS),
247: poptStrerror(opt));
248: tls_usage(1);
249: }
250: }
251:
252: extra_args = poptGetArgs(pc);
253: if (!extra_args || *extra_args == NULL)
254: tls_usage(1);
255:
256: for (; *extra_args; extra_args++)
257: list_file(*extra_args);
258: poptFreeContext(pc);
259:
260: return 0;
261: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>