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.
152 if (jcr->where[0] == 0) {
153 pm_strcpy(attr->ofname, attr->fname);
154 pm_strcpy(attr->olname, attr->lname);
156 } else if (jcr->where_bregexp) {
158 apply_bregexps(attr->fname, jcr->where_bregexp, &ret);
159 pm_strcpy(attr->ofname, ret);
161 if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
162 /* Always add prefix to hard links (FT_LNKSAVED) and
163 * on user request to soft links
166 if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
167 apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
168 pm_strcpy(attr->olname, ret);
171 pm_strcpy(attr->olname, attr->lname);
177 int wherelen = strlen(jcr->where);
178 pm_strcpy(attr->ofname, jcr->where); /* copy prefix */
179 #if defined(HAVE_WIN32)
180 if (attr->fname[1] == ':') {
181 attr->fname[1] = '/'; /* convert : to / */
184 fn = attr->fname; /* take whole name */
185 /* Ensure where is terminated with a slash */
186 if (!IsPathSeparator(jcr->where[wherelen-1]) && !IsPathSeparator(fn[0])) {
187 pm_strcat(attr->ofname, "/");
189 pm_strcat(attr->ofname, fn); /* copy rest of name */
191 * Fixup link name -- if it is an absolute path
193 if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
195 /* Always add prefix to hard links (FT_LNKSAVED) and
196 * on user request to soft links
198 if (IsPathSeparator(attr->lname[0]) &&
199 (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
200 pm_strcpy(attr->olname, jcr->where);
207 #if defined(HAVE_WIN32)
208 if (attr->lname[1] == ':') {
209 attr->lname[1] = '/'; /* turn : into / */
212 fn = attr->lname; /* take whole name */
213 /* Ensure where is terminated with a slash */
215 !IsPathSeparator(jcr->where[wherelen-1]) &&
216 !IsPathSeparator(fn[0])) {
217 pm_strcat(attr->olname, "/");
219 pm_strcat(attr->olname, fn); /* copy rest of link */
222 #if defined(HAVE_WIN32)
223 strip_double_slashes(attr->ofname);
224 strip_double_slashes(attr->olname);
228 extern char *getuser(uid_t uid, char *name, int len);
229 extern char *getgroup(gid_t gid, char *name, int len);
232 * Print an ls style message, also send M_RESTORED
234 void print_ls_output(JCR *jcr, ATTR *attr)
238 char en1[30], en2[30];
241 p = encode_mode(attr->statp.st_mode, buf);
242 p += sprintf(p, " %2d ", (uint32_t)attr->statp.st_nlink);
243 p += sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid, en1, sizeof(en1)),
244 getgroup(attr->statp.st_gid, en2, sizeof(en2)));
245 p += sprintf(p, "%10.10s ", edit_uint64(attr->statp.st_size, ec1));
246 p = encode_time(attr->statp.st_ctime, p);
249 for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
252 if (attr->type == FT_LNK) {
258 for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
264 Dmsg1(20, "%s", buf);
265 Jmsg(jcr, M_RESTORED, 1, "%s", buf);