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