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)
125 if (p && 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 (jcr->where[wherelen-1] != '/' && 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 (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 */
193 if (add_link && jcr->where[wherelen-1] != '/' && fn[0] != '/') {
194 pm_strcat(attr->olname, "/");
196 pm_strcat(attr->olname, fn); /* copy rest of link */
199 #if defined(HAVE_WIN32)
200 strip_double_slashes(attr->ofname);
201 strip_double_slashes(attr->olname);
205 extern char *getuser(uid_t uid, char *name, int len);
206 extern char *getgroup(gid_t gid, char *name, int len);
209 * Print an ls style message, also send M_RESTORED
211 void print_ls_output(JCR *jcr, ATTR *attr)
215 char en1[30], en2[30];
218 p = encode_mode(attr->statp.st_mode, buf);
219 p += sprintf(p, " %2d ", (uint32_t)attr->statp.st_nlink);
220 p += sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid, en1, sizeof(en1)),
221 getgroup(attr->statp.st_gid, en2, sizeof(en2)));
222 p += sprintf(p, "%10.10s ", edit_uint64(attr->statp.st_size, ec1));
223 p = encode_time(attr->statp.st_ctime, p);
226 for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
229 if (attr->type == FT_LNK) {
235 for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
241 Dmsg1(20, "%s", buf);
242 Jmsg(jcr, M_RESTORED, 1, "%s", buf);