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