2 * attr.c Unpack an Attribute record returned from the tape
4 * Kern Sibbald, June MMIII (code pulled from filed/restore.c and updated)
9 Bacula® - The Network Backup Solution
11 Copyright (C) 2003-2006 Free Software Foundation Europe e.V.
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.
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.
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
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.
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);
50 void free_attr(ATTR *attr)
52 free_pool_memory(attr->olname);
53 free_pool_memory(attr->ofname);
54 free_pool_memory(attr->attrEx);
58 int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr)
62 * An Attributes record consists of:
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
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);
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;
84 attr->data_stream = 0;
86 attr->type &= FT_MASK; /* keep only type bits */
88 while (*p++ != ' ') /* skip record file index */
90 while (*p++ != ' ') /* skip type */
93 attr->fname = p; /* set filname position */
94 while (*p++ != 0) /* skip filename */
96 attr->attr = p; /* set attributes position */
97 while (*p++ != 0) /* skip attributes */
99 attr->lname = p; /* set link position */
100 while (*p++ != 0) /* skip link */
102 pm_strcpy(attr->attrEx, p); /* copy extended attributes, if any */
104 if (attr->data_stream) {
106 while (*p++ != 0) /* skip extended attributes */
108 from_base64(&val, p);
109 attr->data_stream = (int32_t)val;
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);
119 #if defined(HAVE_WIN32)
120 static void strip_double_slashes(char *fname)
124 p = strpbrk(p, "/\\");
126 if (IsPathSeparator(p[1])) {
136 * Build attr->ofname from attr->fname and
137 * attr->olname from attr->olname
139 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
142 * Prepend the where directory so that the
143 * files are put where the user wants.
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.
151 if (jcr->where[0] == 0) {
152 pm_strcpy(attr->ofname, attr->fname);
153 pm_strcpy(attr->olname, attr->lname);
156 int wherelen = strlen(jcr->where);
157 pm_strcpy(attr->ofname, jcr->where); /* copy prefix */
158 #if defined(HAVE_WIN32)
159 if (attr->fname[1] == ':') {
160 attr->fname[1] = '/'; /* convert : to / */
163 fn = attr->fname; /* take whole name */
164 /* Ensure where is terminated with a slash */
165 if (!IsPathSeparator(jcr->where[wherelen-1]) && !IsPathSeparator(fn[0])) {
166 pm_strcat(attr->ofname, "/");
168 pm_strcat(attr->ofname, fn); /* copy rest of name */
170 * Fixup link name -- if it is an absolute path
172 if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
174 /* Always add prefix to hard links (FT_LNKSAVED) and
175 * on user request to soft links
177 if (IsPathSeparator(attr->lname[0]) &&
178 (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
179 pm_strcpy(attr->olname, jcr->where);
186 #if defined(HAVE_WIN32)
187 if (attr->lname[1] == ':') {
188 attr->lname[1] = '/'; /* turn : into / */
191 fn = attr->lname; /* take whole name */
192 /* Ensure where is terminated with a slash */
194 !IsPathSeparator(jcr->where[wherelen-1]) &&
195 !IsPathSeparator(fn[0])) {
196 pm_strcat(attr->olname, "/");
198 pm_strcat(attr->olname, fn); /* copy rest of link */
201 #if defined(HAVE_WIN32)
202 strip_double_slashes(attr->ofname);
203 strip_double_slashes(attr->olname);
207 extern char *getuser(uid_t uid, char *name, int len);
208 extern char *getgroup(gid_t gid, char *name, int len);
211 * Print an ls style message, also send M_RESTORED
213 void print_ls_output(JCR *jcr, ATTR *attr)
217 char en1[30], en2[30];
220 p = encode_mode(attr->statp.st_mode, buf);
221 p += sprintf(p, " %2d ", (uint32_t)attr->statp.st_nlink);
222 p += sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid, en1, sizeof(en1)),
223 getgroup(attr->statp.st_gid, en2, sizeof(en2)));
224 p += sprintf(p, "%10.10s ", edit_uint64(attr->statp.st_size, ec1));
225 p = encode_time(attr->statp.st_ctime, p);
228 for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
231 if (attr->type == FT_LNK) {
237 for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
243 Dmsg1(20, "%s", buf);
244 Jmsg(jcr, M_RESTORED, 1, "%s", buf);