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