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