]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/attr.c
Working directory pane in restore. Will get this into the stack next.
[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 #include "lib/breg.h"
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 = strpbrk(p, "/\\");
125       if (p != NULL) {
126          if (IsPathSeparator(p[1])) {
127             strcpy(p, p+1);
128          }
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
152    if (jcr->where_bregexp) { 
153       char *ret;
154       apply_bregexps(attr->fname, jcr->where_bregexp, &ret);
155       pm_strcpy(attr->ofname, ret);
156
157       if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
158          /* Always add prefix to hard links (FT_LNKSAVED) and
159           *  on user request to soft links
160           */
161
162          if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
163             apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
164             pm_strcpy(attr->olname, ret);
165
166          } else {
167             pm_strcpy(attr->olname, attr->lname);
168          }
169       }
170       
171    } else if (jcr->where[0] == 0) {
172       pm_strcpy(attr->ofname, attr->fname);
173       pm_strcpy(attr->olname, attr->lname);
174
175    } else {
176       const char *fn;
177       int wherelen = strlen(jcr->where);
178       pm_strcpy(attr->ofname, jcr->where);  /* copy prefix */
179 #if defined(HAVE_WIN32)
180       if (attr->fname[1] == ':') {
181          attr->fname[1] = '/';     /* convert : to / */
182       }
183 #endif
184       fn = attr->fname;            /* take whole name */
185       /* Ensure where is terminated with a slash */
186       if (!IsPathSeparator(jcr->where[wherelen-1]) && !IsPathSeparator(fn[0])) {
187          pm_strcat(attr->ofname, "/");
188       }
189       pm_strcat(attr->ofname, fn); /* copy rest of name */
190       /*
191        * Fixup link name -- if it is an absolute path
192        */
193       if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
194          bool add_link;
195          /* Always add prefix to hard links (FT_LNKSAVED) and
196           *  on user request to soft links
197           */
198          if (IsPathSeparator(attr->lname[0]) &&
199              (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
200             pm_strcpy(attr->olname, jcr->where);
201             add_link = true;
202          } else {
203             attr->olname[0] = 0;
204             add_link = false;
205          }
206
207 #if defined(HAVE_WIN32)
208          if (attr->lname[1] == ':') {
209             attr->lname[1] = '/';    /* turn : into / */
210          }
211 #endif
212          fn = attr->lname;       /* take whole name */
213          /* Ensure where is terminated with a slash */
214          if (add_link && 
215             !IsPathSeparator(jcr->where[wherelen-1]) && 
216             !IsPathSeparator(fn[0])) {
217             pm_strcat(attr->olname, "/");
218          }
219          pm_strcat(attr->olname, fn);     /* copy rest of link */
220       }
221    }
222 #if defined(HAVE_WIN32)
223    strip_double_slashes(attr->ofname);
224    strip_double_slashes(attr->olname);
225 #endif
226 }
227
228 extern char *getuser(uid_t uid, char *name, int len);
229 extern char *getgroup(gid_t gid, char *name, int len);
230
231 /*
232  * Print an ls style message, also send M_RESTORED
233  */
234 void print_ls_output(JCR *jcr, ATTR *attr)
235 {
236    char buf[5000];
237    char ec1[30];
238    char en1[30], en2[30];
239    char *p, *f;
240
241    p = encode_mode(attr->statp.st_mode, buf);
242    p += sprintf(p, "  %2d ", (uint32_t)attr->statp.st_nlink);
243    p += sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid, en1, sizeof(en1)),
244                 getgroup(attr->statp.st_gid, en2, sizeof(en2)));
245    p += sprintf(p, "%10.10s ", edit_uint64(attr->statp.st_size, ec1));
246    p = encode_time(attr->statp.st_ctime, p);
247    *p++ = ' ';
248    *p++ = ' ';
249    for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
250       *p++ = *f++;
251    }
252    if (attr->type == FT_LNK) {
253       *p++ = ' ';
254       *p++ = '-';
255       *p++ = '>';
256       *p++ = ' ';
257       /* Copy link name */
258       for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
259          *p++ = *f++;
260       }
261    }
262    *p++ = '\n';
263    *p = 0;
264    Dmsg1(20, "%s", buf);
265    Jmsg(jcr, M_RESTORED, 1, "%s", buf);
266 }