]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/attr.c
This commit was manufactured by cvs2svn to create tag
[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-2005 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 extern const int win32_client;
27
28 ATTR *new_attr()
29 {
30    ATTR *attr = (ATTR *)malloc(sizeof(ATTR));
31    memset(attr, 0, sizeof(ATTR));
32    attr->ofname = get_pool_memory(PM_FNAME);
33    attr->olname = get_pool_memory(PM_FNAME);
34    attr->attrEx = get_pool_memory(PM_FNAME);
35    return attr;
36 }
37
38 void free_attr(ATTR *attr)
39 {
40    free_pool_memory(attr->olname);
41    free_pool_memory(attr->ofname);
42    free_pool_memory(attr->attrEx);
43    free(attr);
44 }
45
46 int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr)
47 {
48    char *p;
49    /*
50     * An Attributes record consists of:
51     *    File_index
52     *    Type   (FT_types)
53     *    Filename
54     *    Attributes
55     *    Link name (if file linked i.e. FT_LNK)
56     *    Extended attributes (Win32)
57     *  plus optional values determined by AR_ flags in upper bits of Type
58     *    Data_stream
59     *
60     */
61    attr->stream = stream;
62    Dmsg1(100, "Attr: %s\n", rec);
63    if (sscanf(rec, "%d %d", &attr->file_index, &attr->type) != 2) {
64       Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec);
65       Dmsg1(100, "\nError scanning attributes. %s\n", rec);
66       return 0;
67    }
68    Dmsg2(100, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
69    if (attr->type & AR_DATA_STREAM) {
70       attr->data_stream = 1;
71    } else {
72       attr->data_stream = 0;
73    }
74    attr->type &= FT_MASK;             /* keep only type bits */
75    p = rec;
76    while (*p++ != ' ')               /* skip record file index */
77       { }
78    while (*p++ != ' ')               /* skip type */
79       { }
80
81    attr->fname = p;                   /* set filname position */
82    while (*p++ != 0)                  /* skip filename */
83       { }
84    attr->attr = p;                    /* set attributes position */
85    while (*p++ != 0)                  /* skip attributes */
86       { }
87    attr->lname = p;                   /* set link position */
88    while (*p++ != 0)                  /* skip link */
89       { }
90    pm_strcpy(attr->attrEx, p);        /* copy extended attributes, if any */
91
92    if (attr->data_stream) {
93       int64_t val;
94       while (*p++ != 0)               /* skip extended attributes */
95          { }
96       from_base64(&val, p);
97       attr->data_stream = (int32_t)val;
98    }
99    Dmsg7(200, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s ds=%d\n",
100       attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
101       attr->attrEx, attr->data_stream);
102    *attr->ofname = 0;
103    *attr->olname = 0;
104    return 1;
105 }
106
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
121 /*
122  * Build attr->ofname from attr->fname and
123  *       attr->olname from attr->olname
124  */
125 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
126 {
127    /*
128     * Prepend the where directory so that the
129     * files are put where the user wants.
130     *
131     * We do a little jig here to handle Win32 files with
132     *   a drive letter -- we simply change the drive
133     *   from, for example, c: to c/ for
134     *   every filename if a prefix is supplied.
135     *
136     */
137    if (jcr->where[0] == 0) {
138       pm_strcpy(attr->ofname, attr->fname);
139       pm_strcpy(attr->olname, attr->lname);
140    } else {
141       const char *fn;
142       int wherelen = strlen(jcr->where);
143       pm_strcpy(attr->ofname, jcr->where);  /* copy prefix */
144       if (win32_client && attr->fname[1] == ':') {
145          attr->fname[1] = '/';     /* convert : to / */
146       }
147       fn = attr->fname;            /* take whole name */
148       /* Ensure where is terminated with a slash */
149       if (jcr->where[wherelen-1] != '/' && fn[0] != '/') {
150          pm_strcat(attr->ofname, "/");
151       }
152       pm_strcat(attr->ofname, fn); /* copy rest of name */
153       /*
154        * Fixup link name -- if it is an absolute path
155        */
156       if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
157          bool add_link;
158          /* Always add prefix to hard links (FT_LNKSAVED) and
159           *  on user request to soft links
160           */
161          if (attr->lname[0] == '/' &&
162              (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
163             pm_strcpy(attr->olname, jcr->where);
164             add_link = true;
165          } else {
166             attr->olname[0] = 0;
167             add_link = false;
168          }
169          if (win32_client && attr->lname[1] == ':') {
170             attr->lname[1] = '/';    /* turn : into / */
171          }
172          fn = attr->lname;       /* take whole name */
173          /* Ensure where is terminated with a slash */
174          if (add_link && jcr->where[wherelen-1] != '/' && fn[0] != '/') {
175             pm_strcat(attr->olname, "/");
176          }
177          pm_strcat(attr->olname, fn);     /* copy rest of link */
178       }
179    }
180    if (win32_client) {
181       strip_double_slashes(attr->ofname);
182       strip_double_slashes(attr->olname);
183    }
184 }
185
186 extern char *getuser(uid_t uid, char *name, int len);
187 extern char *getgroup(gid_t gid, char *name, int len);
188
189 /*
190  * Print an ls style message, also send M_RESTORED
191  */
192 void print_ls_output(JCR *jcr, ATTR *attr)
193 {
194    char buf[5000];
195    char ec1[30];
196    char en1[30], en2[30];
197    char *p, *f;
198
199    p = encode_mode(attr->statp.st_mode, buf);
200    p += sprintf(p, "  %2d ", (uint32_t)attr->statp.st_nlink);
201    p += sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid, en1, sizeof(en1)),
202                 getgroup(attr->statp.st_gid, en2, sizeof(en2)));
203    p += sprintf(p, "%10.10s ", edit_uint64(attr->statp.st_size, ec1));
204    p = encode_time(attr->statp.st_ctime, p);
205    *p++ = ' ';
206    *p++ = ' ';
207    for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
208       *p++ = *f++;
209    }
210    if (attr->type == FT_LNK) {
211       *p++ = ' ';
212       *p++ = '-';
213       *p++ = '>';
214       *p++ = ' ';
215       /* Copy link name */
216       for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
217          *p++ = *f++;
218       }
219    }
220    *p++ = '\n';
221    *p = 0;
222    Dmsg1(20, "%s", buf);
223    Jmsg(jcr, M_RESTORED, 1, "%s", buf);
224 }