2 Bacula® - The Network Backup Solution
4 Copyright (C) 2003-2010 Free Software Foundation Europe e.V.
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 three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
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.
18 You should have received a copy of the GNU Affero 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
23 Bacula® is a registered trademark of Kern Sibbald.
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.
29 * attr.c Unpack an Attribute record returned from the tape
31 * Kern Sibbald, June MMIII (code pulled from filed/restore.c and updated)
40 static const int dbglvl = 150;
42 ATTR *new_attr(JCR *jcr)
44 ATTR *attr = (ATTR *)malloc(sizeof(ATTR));
45 memset(attr, 0, sizeof(ATTR));
46 attr->ofname = get_pool_memory(PM_FNAME);
47 attr->olname = get_pool_memory(PM_FNAME);
48 attr->attrEx = get_pool_memory(PM_FNAME);
54 void free_attr(ATTR *attr)
56 free_pool_memory(attr->olname);
57 free_pool_memory(attr->ofname);
58 free_pool_memory(attr->attrEx);
62 int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, int32_t reclen, ATTR *attr)
67 * An Attributes record consists of:
72 * Link name (if file linked i.e. FT_LNK)
73 * Extended attributes (Win32)
74 * plus optional values determined by AR_ flags in upper bits of Type
78 attr->stream = stream;
79 Dmsg1(dbglvl, "Attr: %s\n", rec);
80 if (sscanf(rec, "%d %d", &attr->file_index, &attr->type) != 2) {
81 Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec);
82 Dmsg1(dbglvl, "\nError scanning attributes. %s\n", rec);
85 Dmsg2(dbglvl, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
87 * Note AR_DATA_STREAM should never be set since it is encoded
88 * at the end of the attributes.
90 if (attr->type & AR_DATA_STREAM) {
91 attr->data_stream = 1;
93 attr->data_stream = 0;
95 attr->type &= FT_MASK; /* keep only type bits */
97 while (*p++ != ' ') /* skip record file index */
99 while (*p++ != ' ') /* skip type */
102 attr->fname = p; /* set filname position */
103 while (*p++ != 0) /* skip filename */
105 attr->attr = p; /* set attributes position */
106 while (*p++ != 0) /* skip attributes */
108 attr->lname = p; /* set link position */
109 while (*p++ != 0) /* skip link */
112 if (attr->type == FT_RESTORE_FIRST) {
113 /* We have an object, so do a binary copy */
114 object_len = reclen + rec - p;
115 attr->attrEx = check_pool_memory_size(attr->attrEx, object_len + 1);
116 memcpy(attr->attrEx, p, object_len);
117 /* Add a EOS for those who attempt to print the object */
118 p = attr->attrEx + object_len;
121 pm_strcpy(attr->attrEx, p); /* copy extended attributes, if any */
122 if (attr->data_stream) {
124 while (*p++ != 0) /* skip extended attributes */
126 from_base64(&val, p);
127 attr->data_stream = (int32_t)val;
129 while (*p++ != 0) /* skip extended attributes */
131 if (p - rec < reclen) {
132 attr->delta_seq = str_to_int32(p); /* delta_seq */
136 Dmsg8(dbglvl, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s datastr=%d delta_seq=%d\n",
137 attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
138 attr->attrEx, attr->data_stream, attr->delta_seq);
144 #if defined(HAVE_WIN32)
145 static void strip_double_slashes(char *fname)
149 p = strpbrk(p, "/\\");
151 if (IsPathSeparator(p[1])) {
161 * Build attr->ofname from attr->fname and
162 * attr->olname from attr->olname
164 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
167 * Prepend the where directory so that the
168 * files are put where the user wants.
170 * We do a little jig here to handle Win32 files with
171 * a drive letter -- we simply change the drive
172 * from, for example, c: to c/ for
173 * every filename if a prefix is supplied.
177 if (jcr->where_bregexp) {
179 apply_bregexps(attr->fname, jcr->where_bregexp, &ret);
180 pm_strcpy(attr->ofname, ret);
182 if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
183 /* Always add prefix to hard links (FT_LNKSAVED) and
184 * on user request to soft links
187 if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
188 apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
189 pm_strcpy(attr->olname, ret);
192 pm_strcpy(attr->olname, attr->lname);
196 } else if (jcr->where[0] == 0) {
197 pm_strcpy(attr->ofname, attr->fname);
198 pm_strcpy(attr->olname, attr->lname);
202 int wherelen = strlen(jcr->where);
203 pm_strcpy(attr->ofname, jcr->where); /* copy prefix */
204 #if defined(HAVE_WIN32)
205 if (attr->fname[1] == ':') {
206 attr->fname[1] = '/'; /* convert : to / */
209 fn = attr->fname; /* take whole name */
210 /* Ensure where is terminated with a slash */
211 if (!IsPathSeparator(jcr->where[wherelen-1]) && !IsPathSeparator(fn[0])) {
212 pm_strcat(attr->ofname, "/");
214 pm_strcat(attr->ofname, fn); /* copy rest of name */
216 * Fixup link name -- if it is an absolute path
218 if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
220 /* Always add prefix to hard links (FT_LNKSAVED) and
221 * on user request to soft links
223 if (IsPathSeparator(attr->lname[0]) &&
224 (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
225 pm_strcpy(attr->olname, jcr->where);
232 #if defined(HAVE_WIN32)
233 if (attr->lname[1] == ':') {
234 attr->lname[1] = '/'; /* turn : into / */
237 fn = attr->lname; /* take whole name */
238 /* Ensure where is terminated with a slash */
240 !IsPathSeparator(jcr->where[wherelen-1]) &&
241 !IsPathSeparator(fn[0])) {
242 pm_strcat(attr->olname, "/");
244 pm_strcat(attr->olname, fn); /* copy rest of link */
247 #if defined(HAVE_WIN32)
248 strip_double_slashes(attr->ofname);
249 strip_double_slashes(attr->olname);
253 extern char *getuser(uid_t uid, char *name, int len);
254 extern char *getgroup(gid_t gid, char *name, int len);
257 * Print an ls style message, also send M_RESTORED
259 void print_ls_output(JCR *jcr, ATTR *attr)
263 char en1[30], en2[30];
267 if (attr->type == FT_DELETED) { /* TODO: change this to get last seen values */
268 bsnprintf(buf, sizeof(buf),
269 "---------- - - - - ---------- -------- %s\n", attr->ofname);
270 Dmsg1(dbglvl, "%s", buf);
271 Jmsg(jcr, M_RESTORED, 1, "%s", buf);
276 jcr->id_list = new_guid_list();
279 p = encode_mode(attr->statp.st_mode, buf);
280 p += sprintf(p, " %2d ", (uint32_t)attr->statp.st_nlink);
281 p += sprintf(p, "%-8.8s %-8.8s",
282 guid->uid_to_name(attr->statp.st_uid, en1, sizeof(en1)),
283 guid->gid_to_name(attr->statp.st_gid, en2, sizeof(en2)));
284 p += sprintf(p, "%12.12s ", edit_int64(attr->statp.st_size, ec1));
285 p = encode_time(attr->statp.st_ctime, p);
288 for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
291 if (attr->type == FT_LNK) {
297 for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
303 Dmsg1(dbglvl, "%s", buf);
304 Jmsg(jcr, M_RESTORED, 1, "%s", buf);