]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/attr.c
Use new FO_xxx bits in backup/restore and plugins
[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    /*
87     * Note AR_DATA_STREAM should never be set since it is encoded
88     *  at the end of the attributes.
89     */
90    if (attr->type & AR_DATA_STREAM) {
91       attr->data_stream = 1;
92    } else {
93       attr->data_stream = 0;
94    }
95    attr->type &= FT_MASK;             /* keep only type bits */
96    p = rec;
97    while (*p++ != ' ')               /* skip record file index */
98       { }
99    while (*p++ != ' ')               /* skip type */
100       { }
101
102    attr->fname = p;                   /* set filname position */
103    while (*p++ != 0)                  /* skip filename */
104       { }
105    attr->attr = p;                    /* set attributes position */
106    while (*p++ != 0)                  /* skip attributes */
107       { }
108    attr->lname = p;                   /* set link position */
109    while (*p++ != 0)                  /* skip link */
110       { }
111    attr->delta_seq = 0;
112    if (attr->type == FT_RESTORE_FIRST) {
113       /* We have an object, so do a binary copy */
114       object_len = reclen + rec - p;
115       attr->attrEx = check_pool_memory_size(attr->attrEx, object_len + 1);
116       memcpy(attr->attrEx, p, object_len);  
117       /* Add a EOS for those who attempt to print the object */
118       p = attr->attrEx + object_len;
119       *p = 0;
120    } else {
121       pm_strcpy(attr->attrEx, p);     /* copy extended attributes, if any */
122       if (attr->data_stream) {
123          int64_t val;
124          while (*p++ != 0)            /* skip extended attributes */
125             { }
126          from_base64(&val, p);
127          attr->data_stream = (int32_t)val;
128       } else {
129          while (*p++ != 0)            /* skip extended attributes */
130             { }
131          if (p - rec < reclen) {
132             attr->delta_seq = str_to_int32(p); /* delta_seq */
133          }
134       }       
135    }
136    Dmsg8(dbglvl, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s datastr=%d delta_seq=%d\n",
137       attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
138       attr->attrEx, attr->data_stream, attr->delta_seq);
139    *attr->ofname = 0;
140    *attr->olname = 0;
141    return 1;
142 }
143
144 #if defined(HAVE_WIN32)
145 static void strip_double_slashes(char *fname)
146 {
147    char *p = fname;
148    while (p && *p) {
149       p = strpbrk(p, "/\\");
150       if (p != NULL) {
151          if (IsPathSeparator(p[1])) {
152             strcpy(p, p+1);
153          }
154          p++;
155       }
156    }
157 }
158 #endif
159
160 /*
161  * Build attr->ofname from attr->fname and
162  *       attr->olname from attr->olname
163  */
164 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
165 {
166    /*
167     * Prepend the where directory so that the
168     * files are put where the user wants.
169     *
170     * We do a little jig here to handle Win32 files with
171     *   a drive letter -- we simply change the drive
172     *   from, for example, c: to c/ for
173     *   every filename if a prefix is supplied.
174     *
175     */
176
177    if (jcr->where_bregexp) { 
178       char *ret;
179       apply_bregexps(attr->fname, jcr->where_bregexp, &ret);
180       pm_strcpy(attr->ofname, ret);
181
182       if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
183          /* Always add prefix to hard links (FT_LNKSAVED) and
184           *  on user request to soft links
185           */
186
187          if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
188             apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
189             pm_strcpy(attr->olname, ret);
190
191          } else {
192             pm_strcpy(attr->olname, attr->lname);
193          }
194       }
195       
196    } else if (jcr->where[0] == 0) {
197       pm_strcpy(attr->ofname, attr->fname);
198       pm_strcpy(attr->olname, attr->lname);
199
200    } else {
201       const char *fn;
202       int wherelen = strlen(jcr->where);
203       pm_strcpy(attr->ofname, jcr->where);  /* copy prefix */
204 #if defined(HAVE_WIN32)
205       if (attr->fname[1] == ':') {
206          attr->fname[1] = '/';     /* convert : to / */
207       }
208 #endif
209       fn = attr->fname;            /* take whole name */
210       /* Ensure where is terminated with a slash */
211       if (!IsPathSeparator(jcr->where[wherelen-1]) && !IsPathSeparator(fn[0])) {
212          pm_strcat(attr->ofname, "/");
213       }
214       pm_strcat(attr->ofname, fn); /* copy rest of name */
215       /*
216        * Fixup link name -- if it is an absolute path
217        */
218       if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
219          bool add_link;
220          /* Always add prefix to hard links (FT_LNKSAVED) and
221           *  on user request to soft links
222           */
223          if (IsPathSeparator(attr->lname[0]) &&
224              (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
225             pm_strcpy(attr->olname, jcr->where);
226             add_link = true;
227          } else {
228             attr->olname[0] = 0;
229             add_link = false;
230          }
231
232 #if defined(HAVE_WIN32)
233          if (attr->lname[1] == ':') {
234             attr->lname[1] = '/';    /* turn : into / */
235          }
236 #endif
237          fn = attr->lname;       /* take whole name */
238          /* Ensure where is terminated with a slash */
239          if (add_link && 
240             !IsPathSeparator(jcr->where[wherelen-1]) && 
241             !IsPathSeparator(fn[0])) {
242             pm_strcat(attr->olname, "/");
243          }
244          pm_strcat(attr->olname, fn);     /* copy rest of link */
245       }
246    }
247 #if defined(HAVE_WIN32)
248    strip_double_slashes(attr->ofname);
249    strip_double_slashes(attr->olname);
250 #endif
251 }
252
253 extern char *getuser(uid_t uid, char *name, int len);
254 extern char *getgroup(gid_t gid, char *name, int len);
255
256 /*
257  * Print an ls style message, also send M_RESTORED
258  */
259 void print_ls_output(JCR *jcr, ATTR *attr)
260 {
261    char buf[5000];
262    char ec1[30];
263    char en1[30], en2[30];
264    char *p, *f;
265    guid_list *guid;
266
267    if (attr->type == FT_DELETED) { /* TODO: change this to get last seen values */
268       bsnprintf(buf, sizeof(buf),
269                 "----------   - -        -                - ---------- --------  %s\n", attr->ofname);
270       Dmsg1(dbglvl, "%s", buf);
271       Jmsg(jcr, M_RESTORED, 1, "%s", buf);
272       return;
273    }
274
275    if (!jcr->id_list) {
276       jcr->id_list = new_guid_list();
277    }
278    guid = jcr->id_list;
279    p = encode_mode(attr->statp.st_mode, buf);
280    p += sprintf(p, "  %2d ", (uint32_t)attr->statp.st_nlink);
281    p += sprintf(p, "%-8.8s %-8.8s", 
282                 guid->uid_to_name(attr->statp.st_uid, en1, sizeof(en1)),
283                 guid->gid_to_name(attr->statp.st_gid, en2, sizeof(en2)));
284    p += sprintf(p, "%12.12s ", edit_int64(attr->statp.st_size, ec1));
285    p = encode_time(attr->statp.st_ctime, p);
286    *p++ = ' ';
287    *p++ = ' ';
288    for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
289       *p++ = *f++;
290    }
291    if (attr->type == FT_LNK) {
292       *p++ = ' ';
293       *p++ = '-';
294       *p++ = '>';
295       *p++ = ' ';
296       /* Copy link name */
297       for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
298          *p++ = *f++;
299       }
300    }
301    *p++ = '\n';
302    *p = 0;
303    Dmsg1(dbglvl, "%s", buf);
304    Jmsg(jcr, M_RESTORED, 1, "%s", buf);
305 }