Line data Source code
1 : #include "../burp.h"
2 : #include "../action.h"
3 : #include "../asfd.h"
4 : #include "../async.h"
5 : #include "../attribs.h"
6 : #include "../cmd.h"
7 : #include "../log.h"
8 :
9 : /* Note: The chars in this function are not the same as in the CMD_ set.
10 : These are for printing to the screen only. */
11 0 : static char *encode_mode(mode_t mode, char *buf)
12 : {
13 0 : char *cp=buf;
14 0 : *cp++=S_ISDIR(mode)?'d':S_ISBLK(mode)?'b':S_ISCHR(mode)?'c':
15 0 : S_ISLNK(mode)?'l':S_ISFIFO(mode)?'p':S_ISSOCK(mode)?'s':'-';
16 0 : *cp++=mode&S_IRUSR?'r':'-';
17 0 : *cp++=mode&S_IWUSR?'w':'-';
18 0 : *cp++=(mode&S_ISUID?(mode&S_IXUSR?'s':'S'):(mode&S_IXUSR?'x':'-'));
19 0 : *cp++=mode&S_IRGRP?'r':'-';
20 0 : *cp++=mode&S_IWGRP?'w':'-';
21 0 : *cp++=(mode&S_ISGID?(mode&S_IXGRP?'s':'S'):(mode&S_IXGRP?'x':'-'));
22 0 : *cp++=mode&S_IROTH?'r':'-';
23 0 : *cp++=mode&S_IWOTH?'w':'-';
24 0 : *cp++=(mode&S_ISVTX?(mode&S_IXOTH?'t':'T'):(mode&S_IXOTH?'x':'-'));
25 0 : *cp='\0';
26 0 : return cp;
27 : }
28 :
29 0 : static char *encode_time(uint64_t utime, char *buf)
30 : {
31 : const struct tm *tm;
32 0 : int n=0;
33 0 : time_t time=utime;
34 :
35 : #ifdef HAVE_WIN32
36 : /* Avoid a seg fault in Microsoft's CRT localtime_r(),
37 : * which incorrectly references a NULL returned from gmtime() if
38 : * time is negative before or after the timezone adjustment. */
39 : struct tm *gtm;
40 :
41 : if(!(gtm=gmtime(&time))) return buf;
42 :
43 : if(gtm->tm_year==1970 && gtm->tm_mon==1 && gtm->tm_mday<3) return buf;
44 : #endif
45 :
46 0 : if((tm=localtime(&time)))
47 : n=sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d",
48 : tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
49 0 : tm->tm_hour, tm->tm_min, tm->tm_sec);
50 0 : return buf+n;
51 : }
52 :
53 0 : void ls_to_buf(char *lsbuf, struct sbuf *sb)
54 : {
55 : int n;
56 : char *p;
57 : time_t time;
58 : const char *f;
59 0 : struct stat *statp=&sb->statp;
60 0 : *lsbuf='\0';
61 :
62 0 : p=encode_mode(statp->st_mode, lsbuf);
63 0 : n=sprintf(p, " %2d ", (uint32_t)statp->st_nlink);
64 0 : p+=n;
65 : n=sprintf(p, "%5d %5d", (uint32_t)statp->st_uid,
66 0 : (uint32_t)statp->st_gid);
67 0 : p+=n;
68 0 : n=sprintf(p, " %7lu ", (unsigned long)statp->st_size);
69 0 : p+=n;
70 0 : if(statp->st_ctime>statp->st_mtime) time=statp->st_ctime;
71 0 : else time=statp->st_mtime;
72 :
73 : // Display most recent time.
74 0 : p=encode_time(time, p);
75 0 : *p++=' ';
76 0 : for(f=sb->path.buf; *f; ) *p++=*f++;
77 0 : *p=0;
78 0 : }
79 :
80 0 : static void ls_long_output(struct sbuf *sb)
81 : {
82 : static char lsbuf[2048];
83 0 : ls_to_buf(lsbuf, sb);
84 : printf("%s", lsbuf);
85 0 : if(sb->link.buf) printf(" -> %s", sb->link.buf);
86 : printf("\n");
87 0 : }
88 :
89 : static void ls_short_output(struct sbuf *sb)
90 : {
91 0 : printf("%s\n", sb->path.buf);
92 : }
93 :
94 0 : static void list_item(enum action act, struct sbuf *sb)
95 : {
96 0 : if(act==ACTION_LIST_LONG)
97 : {
98 0 : ls_long_output(sb);
99 : }
100 : else
101 : {
102 0 : ls_short_output(sb);
103 : }
104 0 : }
105 :
106 0 : int do_list_client(struct asfd *asfd, enum action act, struct conf **confs)
107 : {
108 0 : int ret=-1;
109 0 : char msg[512]="";
110 0 : struct sbuf *sb=NULL;
111 0 : struct iobuf *rbuf=asfd->rbuf;
112 0 : const char *backup=get_string(confs[OPT_BACKUP]);
113 0 : const char *backup2=get_string(confs[OPT_BACKUP2]);
114 0 : const char *browsedir=get_string(confs[OPT_BROWSEDIR]);
115 0 : const char *regex=get_string(confs[OPT_REGEX]);
116 : //logp("in do_list\n");
117 :
118 0 : switch(act)
119 : {
120 : case ACTION_LIST:
121 : case ACTION_LIST_LONG:
122 0 : if(browsedir && regex)
123 : {
124 0 : logp("You cannot specify both a directory and a regular expression when listing.\n");
125 0 : goto end;
126 : }
127 0 : if(browsedir)
128 : snprintf(msg, sizeof(msg), "listb %s:%s",
129 0 : backup?backup:"", browsedir);
130 : else
131 : snprintf(msg, sizeof(msg), "list %s:%s",
132 0 : backup?backup:"", regex?regex:"");
133 : break;
134 : case ACTION_DIFF:
135 : case ACTION_DIFF_LONG:
136 : snprintf(msg, sizeof(msg), "diff %s:%s",
137 0 : backup?backup:"", backup2?backup2:"");
138 : break;
139 : default:
140 0 : logp("unknown action %d\n", act);
141 0 : goto end;
142 : }
143 0 : if(asfd->write_str(asfd, CMD_GEN, msg)
144 0 : || asfd_read_expect(asfd, CMD_GEN, "ok"))
145 : goto end;
146 :
147 0 : if(!(sb=sbuf_alloc(get_protocol(confs)))) goto end;
148 0 : iobuf_init(&sb->path);
149 0 : iobuf_init(&sb->link);
150 0 : iobuf_init(&sb->attr);
151 :
152 : // This should probably should use the sbuf stuff.
153 : while(1)
154 : {
155 0 : sbuf_free_content(sb);
156 :
157 0 : iobuf_free_content(rbuf);
158 0 : if(asfd->read(asfd)) break;
159 0 : if(rbuf->cmd==CMD_MESSAGE)
160 : {
161 0 : printf("%s\n", rbuf->buf);
162 0 : if(!strcmp(rbuf->buf, "no backups"))
163 0 : ret=0;
164 : goto end;
165 : }
166 0 : else if(rbuf->cmd==CMD_TIMESTAMP)
167 : {
168 : // A backup timestamp, just print it.
169 0 : printf("Backup: %s\n", rbuf->buf);
170 0 : if(browsedir)
171 : printf("Listing directory: %s\n",
172 : browsedir);
173 0 : if(regex)
174 : printf("With regex: %s\n",
175 : regex);
176 : continue;
177 : }
178 0 : else if(rbuf->cmd!=CMD_ATTRIBS)
179 : {
180 0 : iobuf_log_unexpected(rbuf, __func__);
181 0 : goto end;
182 : }
183 0 : iobuf_copy(&sb->attr, rbuf);
184 0 : iobuf_init(rbuf);
185 :
186 0 : attribs_decode(sb);
187 :
188 0 : if(asfd->read(asfd))
189 : {
190 0 : logp("got stat without an object\n");
191 0 : goto end;
192 : }
193 0 : iobuf_copy(&sb->path, rbuf);
194 0 : iobuf_init(rbuf);
195 :
196 0 : if(sb->path.cmd==CMD_DIRECTORY
197 0 : || sb->path.cmd==CMD_FILE
198 0 : || sb->path.cmd==CMD_ENC_FILE
199 0 : || sb->path.cmd==CMD_EFS_FILE
200 0 : || sb->path.cmd==CMD_SPECIAL)
201 : {
202 0 : list_item(act, sb);
203 : }
204 0 : else if(cmd_is_link(sb->path.cmd)) // symlink or hardlink
205 : {
206 0 : if(asfd->read(asfd)
207 0 : || rbuf->cmd!=sb->path.cmd)
208 : {
209 : logp("could not get link %c:%s\n",
210 0 : sb->path.cmd, sb->path.buf);
211 0 : goto end;
212 : }
213 0 : iobuf_copy(&sb->link, rbuf);
214 0 : iobuf_init(rbuf);
215 0 : list_item(act, sb);
216 : }
217 : else
218 : {
219 : logp("unlistable %c:%s\n",
220 0 : sb->path.cmd, sb->path.buf?sb->path.buf:"");
221 : }
222 : }
223 :
224 : ret=0;
225 : end:
226 0 : sbuf_free(&sb);
227 0 : if(!ret) logp("List finished ok\n");
228 0 : return ret;
229 : }
|