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