]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/attr.c
bat: Add restore job list in console
[bacula/bacula] / bacula / src / lib / attr.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2003-2010 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *   attr.c  Unpack an Attribute record returned from the tape
30  *
31  *    Kern Sibbald, June MMIII  (code pulled from filed/restore.c and updated)
32  *
33  */
34
35
36 #include "bacula.h"
37 #include "jcr.h"
38 #include "lib/breg.h"
39
40 static const int dbglvl = 150;
41
42 ATTR *new_attr(JCR *jcr)
43 {
44    ATTR *attr = (ATTR *)malloc(sizeof(ATTR));
45    memset(attr, 0, sizeof(ATTR));
46    attr->ofname = get_pool_memory(PM_FNAME);
47    attr->olname = get_pool_memory(PM_FNAME);
48    attr->attrEx = get_pool_memory(PM_FNAME);
49    attr->jcr = jcr;
50    attr->uid = getuid();
51    return attr;
52 }
53
54 void free_attr(ATTR *attr)
55 {
56    free_pool_memory(attr->olname);
57    free_pool_memory(attr->ofname);
58    free_pool_memory(attr->attrEx);
59    free(attr);
60 }
61
62 int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, int32_t reclen, ATTR *attr)
63 {
64    char *p;
65    int object_len;
66    /*
67     * An Attributes record consists of:
68     *    File_index
69     *    Type   (FT_types)
70     *    Filename
71     *    Attributes
72     *    Link name (if file linked i.e. FT_LNK)
73     *    Extended attributes (Win32)
74     *  plus optional values determined by AR_ flags in upper bits of Type
75     *    Data_stream
76     *
77     */
78    attr->stream = stream;
79    Dmsg1(dbglvl, "Attr: %s\n", rec);
80    if (sscanf(rec, "%d %d", &attr->file_index, &attr->type) != 2) {
81       Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec);
82       Dmsg1(dbglvl, "\nError scanning attributes. %s\n", rec);
83       return 0;
84    }
85    Dmsg2(dbglvl, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
86    if (attr->type & AR_DATA_STREAM) {
87       attr->data_stream = 1;
88    } else {
89       attr->data_stream = 0;
90    }
91    attr->type &= FT_MASK;             /* keep only type bits */
92    p = rec;
93    while (*p++ != ' ')               /* skip record file index */
94       { }
95    while (*p++ != ' ')               /* skip type */
96       { }
97
98    attr->fname = p;                   /* set filname position */
99    while (*p++ != 0)                  /* skip filename */
100       { }
101    attr->attr = p;                    /* set attributes position */
102    while (*p++ != 0)                  /* skip attributes */
103       { }
104    attr->lname = p;                   /* set link position */
105    while (*p++ != 0)                  /* skip link */
106       { }
107    if (attr->type == FT_RESTORE_FIRST) {
108       /* We have an object, so do a binary copy */
109       object_len = reclen + rec - p;
110       attr->attrEx = check_pool_memory_size(attr->attrEx, object_len + 1);
111       memcpy(attr->attrEx, p, object_len);  
112       /* Add a EOS for those who attempt to print the object */
113       p = attr->attrEx + object_len;
114       *p = 0;
115    } else {
116       pm_strcpy(attr->attrEx, p);     /* copy extended attributes, if any */
117       if (attr->data_stream) {
118          int64_t val;
119          while (*p++ != 0)               /* skip extended attributes */
120             { }
121          from_base64(&val, p);
122          attr->data_stream = (int32_t)val;
123       }
124    }
125    Dmsg7(dbglvl, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s ds=%d\n",
126       attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
127       attr->attrEx, attr->data_stream);
128    *attr->ofname = 0;
129    *attr->olname = 0;
130    return 1;
131 }
132
133 #if defined(HAVE_WIN32)
134 static void strip_double_slashes(char *fname)
135 {
136    char *p = fname;
137    while (p && *p) {
138       p = strpbrk(p, "/\\");
139       if (p != NULL) {
140          if (IsPathSeparator(p[1])) {
141             strcpy(p, p+1);
142          }
143          p++;
144       }
145    }
146 }
147 #endif
148
149 /*
150  * Build attr->ofname from attr->fname and
151  *       attr->olname from attr->olname
152  */
153 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
154 {
155    /*
156     * Prepend the where directory so that the
157     * files are put where the user wants.
158     *
159     * We do a little jig here to handle Win32 files with
160     *   a drive letter -- we simply change the drive
161     *   from, for example, c: to c/ for
162     *   every filename if a prefix is supplied.
163     *
164     */
165
166    if (jcr->where_bregexp) { 
167       char *ret;
168       apply_bregexps(attr->fname, jcr->where_bregexp, &ret);
169       pm_strcpy(attr->ofname, ret);
170
171       if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
172          /* Always add prefix to hard links (FT_LNKSAVED) and
173           *  on user request to soft links
174           */
175
176          if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
177             apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
178             pm_strcpy(attr->olname, ret);
179
180          } else {
181             pm_strcpy(attr->olname, attr->lname);
182          }
183       }
184       
185    } else if (jcr->where[0] == 0) {
186       pm_strcpy(attr->ofname, attr->fname);
187       pm_strcpy(attr->olname, attr->lname);
188
189    } else {
190       const char *fn;
191       int wherelen = strlen(jcr->where);
192       pm_strcpy(attr->ofname, jcr->where);  /* copy prefix */
193 #if defined(HAVE_WIN32)
194       if (attr->fname[1] == ':') {
195          attr->fname[1] = '/';     /* convert : to / */
196       }
197 #endif
198       fn = attr->fname;            /* take whole name */
199       /* Ensure where is terminated with a slash */
200       if (!IsPathSeparator(jcr->where[wherelen-1]) && !IsPathSeparator(fn[0])) {
201          pm_strcat(attr->ofname, "/");
202       }
203       pm_strcat(attr->ofname, fn); /* copy rest of name */
204       /*
205        * Fixup link name -- if it is an absolute path
206        */
207       if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
208          bool add_link;
209          /* Always add prefix to hard links (FT_LNKSAVED) and
210           *  on user request to soft links
211           */
212          if (IsPathSeparator(attr->lname[0]) &&
213              (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
214             pm_strcpy(attr->olname, jcr->where);
215             add_link = true;
216          } else {
217             attr->olname[0] = 0;
218             add_link = false;
219          }
220
221 #if defined(HAVE_WIN32)
222          if (attr->lname[1] == ':') {
223             attr->lname[1] = '/';    /* turn : into / */
224          }
225 #endif
226          fn = attr->lname;       /* take whole name */
227          /* Ensure where is terminated with a slash */
228          if (add_link && 
229             !IsPathSeparator(jcr->where[wherelen-1]) && 
230             !IsPathSeparator(fn[0])) {
231             pm_strcat(attr->olname, "/");
232          }
233          pm_strcat(attr->olname, fn);     /* copy rest of link */
234       }
235    }
236 #if defined(HAVE_WIN32)
237    strip_double_slashes(attr->ofname);
238    strip_double_slashes(attr->olname);
239 #endif
240 }
241
242 extern char *getuser(uid_t uid, char *name, int len);
243 extern char *getgroup(gid_t gid, char *name, int len);
244
245 /*
246  * Print an ls style message, also send M_RESTORED
247  */
248 void print_ls_output(JCR *jcr, ATTR *attr)
249 {
250    char buf[5000];
251    char ec1[30];
252    char en1[30], en2[30];
253    char *p, *f;
254    guid_list *guid;
255
256    if (attr->type == FT_DELETED) { /* TODO: change this to get last seen values */
257       bsnprintf(buf, sizeof(buf),
258                 "----------   - -        -                - ---------- --------  %s\n", attr->ofname);
259       Dmsg1(dbglvl, "%s", buf);
260       Jmsg(jcr, M_RESTORED, 1, "%s", buf);
261       return;
262    }
263
264    if (!jcr->id_list) {
265       jcr->id_list = new_guid_list();
266    }
267    guid = jcr->id_list;
268    p = encode_mode(attr->statp.st_mode, buf);
269    p += sprintf(p, "  %2d ", (uint32_t)attr->statp.st_nlink);
270    p += sprintf(p, "%-8.8s %-8.8s", 
271                 guid->uid_to_name(attr->statp.st_uid, en1, sizeof(en1)),
272                 guid->gid_to_name(attr->statp.st_gid, en2, sizeof(en2)));
273    p += sprintf(p, "%12.12s ", edit_int64(attr->statp.st_size, ec1));
274    p = encode_time(attr->statp.st_ctime, p);
275    *p++ = ' ';
276    *p++ = ' ';
277    for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
278       *p++ = *f++;
279    }
280    if (attr->type == FT_LNK) {
281       *p++ = ' ';
282       *p++ = '-';
283       *p++ = '>';
284       *p++ = ' ';
285       /* Copy link name */
286       for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
287          *p++ = *f++;
288       }
289    }
290    *p++ = '\n';
291    *p = 0;
292    Dmsg1(dbglvl, "%s", buf);
293    Jmsg(jcr, M_RESTORED, 1, "%s", buf);
294 }