2 Bacula® - The Network Backup Solution
4 Copyright (C) 2003-2007 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 two of the GNU 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 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 John Walker.
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)
41 ATTR *new_attr(JCR *jcr)
43 ATTR *attr = (ATTR *)malloc(sizeof(ATTR));
44 memset(attr, 0, sizeof(ATTR));
45 attr->ofname = get_pool_memory(PM_FNAME);
46 attr->olname = get_pool_memory(PM_FNAME);
47 attr->attrEx = get_pool_memory(PM_FNAME);
53 void free_attr(ATTR *attr)
55 free_pool_memory(attr->olname);
56 free_pool_memory(attr->ofname);
57 free_pool_memory(attr->attrEx);
61 int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr)
65 * An Attributes record consists of:
70 * Link name (if file linked i.e. FT_LNK)
71 * Extended attributes (Win32)
72 * plus optional values determined by AR_ flags in upper bits of Type
76 attr->stream = stream;
77 Dmsg1(400, "Attr: %s\n", rec);
78 if (sscanf(rec, "%ld %ld", &attr->file_index, &attr->type) != 2) {
79 Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec);
80 Dmsg1(100, "\nError scanning attributes. %s\n", rec);
83 Dmsg2(400, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
84 if (attr->type & AR_DATA_STREAM) {
85 attr->data_stream = 1;
87 attr->data_stream = 0;
89 attr->type &= FT_MASK; /* keep only type bits */
91 while (*p++ != ' ') /* skip record file index */
93 while (*p++ != ' ') /* skip type */
96 attr->fname = p; /* set filname position */
97 while (*p++ != 0) /* skip filename */
99 attr->attr = p; /* set attributes position */
100 while (*p++ != 0) /* skip attributes */
102 attr->lname = p; /* set link position */
103 while (*p++ != 0) /* skip link */
105 pm_strcpy(attr->attrEx, p); /* copy extended attributes, if any */
107 if (attr->data_stream) {
109 while (*p++ != 0) /* skip extended attributes */
111 from_base64(&val, p);
112 attr->data_stream = (int32_t)val;
114 Dmsg7(400, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s ds=%d\n",
115 attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
116 attr->attrEx, attr->data_stream);
122 #if defined(HAVE_WIN32)
123 static void strip_double_slashes(char *fname)
127 p = strpbrk(p, "/\\");
129 if (IsPathSeparator(p[1])) {
139 * Build attr->ofname from attr->fname and
140 * attr->olname from attr->olname
142 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
145 * Prepend the where directory so that the
146 * files are put where the user wants.
148 * We do a little jig here to handle Win32 files with
149 * a drive letter -- we simply change the drive
150 * from, for example, c: to c/ for
151 * every filename if a prefix is supplied.
155 if (jcr->where_bregexp) {
157 apply_bregexps(attr->fname, jcr->where_bregexp, &ret);
158 pm_strcpy(attr->ofname, ret);
160 if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
161 /* Always add prefix to hard links (FT_LNKSAVED) and
162 * on user request to soft links
165 if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
166 apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
167 pm_strcpy(attr->olname, ret);
170 pm_strcpy(attr->olname, attr->lname);
174 } else if (jcr->where[0] == 0) {
175 pm_strcpy(attr->ofname, attr->fname);
176 pm_strcpy(attr->olname, attr->lname);
180 int wherelen = strlen(jcr->where);
181 pm_strcpy(attr->ofname, jcr->where); /* copy prefix */
182 #if defined(HAVE_WIN32)
183 if (attr->fname[1] == ':') {
184 attr->fname[1] = '/'; /* convert : to / */
187 fn = attr->fname; /* take whole name */
188 /* Ensure where is terminated with a slash */
189 if (!IsPathSeparator(jcr->where[wherelen-1]) && !IsPathSeparator(fn[0])) {
190 pm_strcat(attr->ofname, "/");
192 pm_strcat(attr->ofname, fn); /* copy rest of name */
194 * Fixup link name -- if it is an absolute path
196 if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
198 /* Always add prefix to hard links (FT_LNKSAVED) and
199 * on user request to soft links
201 if (IsPathSeparator(attr->lname[0]) &&
202 (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
203 pm_strcpy(attr->olname, jcr->where);
210 #if defined(HAVE_WIN32)
211 if (attr->lname[1] == ':') {
212 attr->lname[1] = '/'; /* turn : into / */
215 fn = attr->lname; /* take whole name */
216 /* Ensure where is terminated with a slash */
218 !IsPathSeparator(jcr->where[wherelen-1]) &&
219 !IsPathSeparator(fn[0])) {
220 pm_strcat(attr->olname, "/");
222 pm_strcat(attr->olname, fn); /* copy rest of link */
225 #if defined(HAVE_WIN32)
226 strip_double_slashes(attr->ofname);
227 strip_double_slashes(attr->olname);
231 extern char *getuser(uid_t uid, char *name, int len);
232 extern char *getgroup(gid_t gid, char *name, int len);
235 * Print an ls style message, also send M_RESTORED
237 void print_ls_output(JCR *jcr, ATTR *attr)
241 char en1[30], en2[30];
245 if (attr->type == FT_DELETED) { /* TODO: change this to get last seen values */
246 bsnprintf(buf, sizeof(buf),
247 "---------- - - - - ---------- -------- %s\n", attr->ofname);
248 Dmsg1(20, "%s", buf);
249 Jmsg(jcr, M_RESTORED, 1, "%s", buf);
254 jcr->id_list = new_guid_list();
257 p = encode_mode(attr->statp.st_mode, buf);
258 p += sprintf(p, " %2d ", (uint32_t)attr->statp.st_nlink);
259 p += sprintf(p, "%-8.8s %-8.8s",
260 guid->uid_to_name(attr->statp.st_uid, en1, sizeof(en1)),
261 guid->gid_to_name(attr->statp.st_gid, en2, sizeof(en2)));
262 p += sprintf(p, "%10.10s ", edit_int64(attr->statp.st_size, ec1));
263 p = encode_time(attr->statp.st_ctime, p);
266 for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
269 if (attr->type == FT_LNK) {
275 for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
281 Dmsg1(20, "%s", buf);
282 Jmsg(jcr, M_RESTORED, 1, "%s", buf);