]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/attr.c
kes Change Bacula trademark owner from John Walker to Kern Sibbald
[bacula/bacula] / bacula / src / lib / attr.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2003-2007 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 two of the GNU 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 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  *   Version $Id$
34  */
35
36
37 #include "bacula.h"
38 #include "jcr.h"
39 #include "lib/breg.h"
40
41 ATTR *new_attr(JCR *jcr)
42 {
43    ATTR *attr = (ATTR *)malloc(sizeof(ATTR));
44    memset(attr, 0, sizeof(ATTR));
45    attr->ofname = get_pool_memory(PM_FNAME);
46    attr->olname = get_pool_memory(PM_FNAME);
47    attr->attrEx = get_pool_memory(PM_FNAME);
48    attr->jcr = jcr;
49    attr->uid = getuid();
50    return attr;
51 }
52
53 void free_attr(ATTR *attr)
54 {
55    free_pool_memory(attr->olname);
56    free_pool_memory(attr->ofname);
57    free_pool_memory(attr->attrEx);
58    free(attr);
59 }
60
61 int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr)
62 {
63    char *p;
64    /*
65     * An Attributes record consists of:
66     *    File_index
67     *    Type   (FT_types)
68     *    Filename
69     *    Attributes
70     *    Link name (if file linked i.e. FT_LNK)
71     *    Extended attributes (Win32)
72     *  plus optional values determined by AR_ flags in upper bits of Type
73     *    Data_stream
74     *
75     */
76    attr->stream = stream;
77    Dmsg1(400, "Attr: %s\n", rec);
78    if (sscanf(rec, "%d %d", &attr->file_index, &attr->type) != 2) {
79       Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec);
80       Dmsg1(100, "\nError scanning attributes. %s\n", rec);
81       return 0;
82    }
83    Dmsg2(400, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
84    if (attr->type & AR_DATA_STREAM) {
85       attr->data_stream = 1;
86    } else {
87       attr->data_stream = 0;
88    }
89    attr->type &= FT_MASK;             /* keep only type bits */
90    p = rec;
91    while (*p++ != ' ')               /* skip record file index */
92       { }
93    while (*p++ != ' ')               /* skip type */
94       { }
95
96    attr->fname = p;                   /* set filname position */
97    while (*p++ != 0)                  /* skip filename */
98       { }
99    attr->attr = p;                    /* set attributes position */
100    while (*p++ != 0)                  /* skip attributes */
101       { }
102    attr->lname = p;                   /* set link position */
103    while (*p++ != 0)                  /* skip link */
104       { }
105    pm_strcpy(attr->attrEx, p);        /* copy extended attributes, if any */
106
107    if (attr->data_stream) {
108       int64_t val;
109       while (*p++ != 0)               /* skip extended attributes */
110          { }
111       from_base64(&val, p);
112       attr->data_stream = (int32_t)val;
113    }
114    Dmsg7(400, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s ds=%d\n",
115       attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
116       attr->attrEx, attr->data_stream);
117    *attr->ofname = 0;
118    *attr->olname = 0;
119    return 1;
120 }
121
122 #if defined(HAVE_WIN32)
123 static void strip_double_slashes(char *fname)
124 {
125    char *p = fname;
126    while (p && *p) {
127       p = strpbrk(p, "/\\");
128       if (p != NULL) {
129          if (IsPathSeparator(p[1])) {
130             strcpy(p, p+1);
131          }
132          p++;
133       }
134    }
135 }
136 #endif
137
138 /*
139  * Build attr->ofname from attr->fname and
140  *       attr->olname from attr->olname
141  */
142 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
143 {
144    /*
145     * Prepend the where directory so that the
146     * files are put where the user wants.
147     *
148     * We do a little jig here to handle Win32 files with
149     *   a drive letter -- we simply change the drive
150     *   from, for example, c: to c/ for
151     *   every filename if a prefix is supplied.
152     *
153     */
154
155    if (jcr->where_bregexp) { 
156       char *ret;
157       apply_bregexps(attr->fname, jcr->where_bregexp, &ret);
158       pm_strcpy(attr->ofname, ret);
159
160       if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
161          /* Always add prefix to hard links (FT_LNKSAVED) and
162           *  on user request to soft links
163           */
164
165          if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
166             apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
167             pm_strcpy(attr->olname, ret);
168
169          } else {
170             pm_strcpy(attr->olname, attr->lname);
171          }
172       }
173       
174    } else if (jcr->where[0] == 0) {
175       pm_strcpy(attr->ofname, attr->fname);
176       pm_strcpy(attr->olname, attr->lname);
177
178    } else {
179       const char *fn;
180       int wherelen = strlen(jcr->where);
181       pm_strcpy(attr->ofname, jcr->where);  /* copy prefix */
182 #if defined(HAVE_WIN32)
183       if (attr->fname[1] == ':') {
184          attr->fname[1] = '/';     /* convert : to / */
185       }
186 #endif
187       fn = attr->fname;            /* take whole name */
188       /* Ensure where is terminated with a slash */
189       if (!IsPathSeparator(jcr->where[wherelen-1]) && !IsPathSeparator(fn[0])) {
190          pm_strcat(attr->ofname, "/");
191       }
192       pm_strcat(attr->ofname, fn); /* copy rest of name */
193       /*
194        * Fixup link name -- if it is an absolute path
195        */
196       if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
197          bool add_link;
198          /* Always add prefix to hard links (FT_LNKSAVED) and
199           *  on user request to soft links
200           */
201          if (IsPathSeparator(attr->lname[0]) &&
202              (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
203             pm_strcpy(attr->olname, jcr->where);
204             add_link = true;
205          } else {
206             attr->olname[0] = 0;
207             add_link = false;
208          }
209
210 #if defined(HAVE_WIN32)
211          if (attr->lname[1] == ':') {
212             attr->lname[1] = '/';    /* turn : into / */
213          }
214 #endif
215          fn = attr->lname;       /* take whole name */
216          /* Ensure where is terminated with a slash */
217          if (add_link && 
218             !IsPathSeparator(jcr->where[wherelen-1]) && 
219             !IsPathSeparator(fn[0])) {
220             pm_strcat(attr->olname, "/");
221          }
222          pm_strcat(attr->olname, fn);     /* copy rest of link */
223       }
224    }
225 #if defined(HAVE_WIN32)
226    strip_double_slashes(attr->ofname);
227    strip_double_slashes(attr->olname);
228 #endif
229 }
230
231 extern char *getuser(uid_t uid, char *name, int len);
232 extern char *getgroup(gid_t gid, char *name, int len);
233
234 /*
235  * Print an ls style message, also send M_RESTORED
236  */
237 void print_ls_output(JCR *jcr, ATTR *attr)
238 {
239    char buf[5000];
240    char ec1[30];
241    char en1[30], en2[30];
242    char *p, *f;
243    guid_list *guid;
244
245    if (attr->type == FT_DELETED) { /* TODO: change this to get last seen values */
246       bsnprintf(buf, sizeof(buf),
247                 "----------   - -        -                - ---------- --------  %s\n", attr->ofname);
248       Dmsg1(20, "%s", buf);
249       Jmsg(jcr, M_RESTORED, 1, "%s", buf);
250       return;
251    }
252
253    if (!jcr->id_list) {
254       jcr->id_list = new_guid_list();
255    }
256    guid = jcr->id_list;
257    p = encode_mode(attr->statp.st_mode, buf);
258    p += sprintf(p, "  %2d ", (uint32_t)attr->statp.st_nlink);
259    p += sprintf(p, "%-8.8s %-8.8s", 
260                 guid->uid_to_name(attr->statp.st_uid, en1, sizeof(en1)),
261                 guid->gid_to_name(attr->statp.st_gid, en2, sizeof(en2)));
262    p += sprintf(p, "%10.10s ", edit_int64(attr->statp.st_size, ec1));
263    p = encode_time(attr->statp.st_ctime, p);
264    *p++ = ' ';
265    *p++ = ' ';
266    for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
267       *p++ = *f++;
268    }
269    if (attr->type == FT_LNK) {
270       *p++ = ' ';
271       *p++ = '-';
272       *p++ = '>';
273       *p++ = ' ';
274       /* Copy link name */
275       for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
276          *p++ = *f++;
277       }
278    }
279    *p++ = '\n';
280    *p = 0;
281    Dmsg1(20, "%s", buf);
282    Jmsg(jcr, M_RESTORED, 1, "%s", buf);
283 }