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)
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);
51 void free_attr(ATTR *attr)
53 free_pool_memory(attr->olname);
54 free_pool_memory(attr->ofname);
55 free_pool_memory(attr->attrEx);
59 int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr)
63 * An Attributes record consists of:
68 * Link name (if file linked i.e. FT_LNK)
69 * Extended attributes (Win32)
70 * plus optional values determined by AR_ flags in upper bits of Type
74 attr->stream = stream;
75 Dmsg1(400, "Attr: %s\n", rec);
76 if (sscanf(rec, "%ld %ld", &attr->file_index, &attr->type) != 2) {
77 Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec);
78 Dmsg1(100, "\nError scanning attributes. %s\n", rec);
81 Dmsg2(400, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
82 if (attr->type & AR_DATA_STREAM) {
83 attr->data_stream = 1;
85 attr->data_stream = 0;
87 attr->type &= FT_MASK; /* keep only type bits */
89 while (*p++ != ' ') /* skip record file index */
91 while (*p++ != ' ') /* skip type */
94 attr->fname = p; /* set filname position */
95 while (*p++ != 0) /* skip filename */
97 attr->attr = p; /* set attributes position */
98 while (*p++ != 0) /* skip attributes */
100 attr->lname = p; /* set link position */
101 while (*p++ != 0) /* skip link */
103 pm_strcpy(attr->attrEx, p); /* copy extended attributes, if any */
105 if (attr->data_stream) {
107 while (*p++ != 0) /* skip extended attributes */
109 from_base64(&val, p);
110 attr->data_stream = (int32_t)val;
112 Dmsg7(400, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s ds=%d\n",
113 attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
114 attr->attrEx, attr->data_stream);
120 #if defined(HAVE_WIN32)
121 static void strip_double_slashes(char *fname)
125 p = strpbrk(p, "/\\");
127 if (IsPathSeparator(p[1])) {
137 * Build attr->ofname from attr->fname and
138 * attr->olname from attr->olname
140 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
143 * Prepend the where directory so that the
144 * files are put where the user wants.
146 * We do a little jig here to handle Win32 files with
147 * a drive letter -- we simply change the drive
148 * from, for example, c: to c/ for
149 * every filename if a prefix is supplied.
153 if (jcr->where_bregexp) {
155 apply_bregexps(attr->fname, jcr->where_bregexp, &ret);
156 pm_strcpy(attr->ofname, ret);
158 if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
159 /* Always add prefix to hard links (FT_LNKSAVED) and
160 * on user request to soft links
163 if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
164 apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
165 pm_strcpy(attr->olname, ret);
168 pm_strcpy(attr->olname, attr->lname);
172 } else if (jcr->where[0] == 0) {
173 pm_strcpy(attr->ofname, attr->fname);
174 pm_strcpy(attr->olname, attr->lname);
178 int wherelen = strlen(jcr->where);
179 pm_strcpy(attr->ofname, jcr->where); /* copy prefix */
180 #if defined(HAVE_WIN32)
181 if (attr->fname[1] == ':') {
182 attr->fname[1] = '/'; /* convert : to / */
185 fn = attr->fname; /* take whole name */
186 /* Ensure where is terminated with a slash */
187 if (!IsPathSeparator(jcr->where[wherelen-1]) && !IsPathSeparator(fn[0])) {
188 pm_strcat(attr->ofname, "/");
190 pm_strcat(attr->ofname, fn); /* copy rest of name */
192 * Fixup link name -- if it is an absolute path
194 if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
196 /* Always add prefix to hard links (FT_LNKSAVED) and
197 * on user request to soft links
199 if (IsPathSeparator(attr->lname[0]) &&
200 (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
201 pm_strcpy(attr->olname, jcr->where);
208 #if defined(HAVE_WIN32)
209 if (attr->lname[1] == ':') {
210 attr->lname[1] = '/'; /* turn : into / */
213 fn = attr->lname; /* take whole name */
214 /* Ensure where is terminated with a slash */
216 !IsPathSeparator(jcr->where[wherelen-1]) &&
217 !IsPathSeparator(fn[0])) {
218 pm_strcat(attr->olname, "/");
220 pm_strcat(attr->olname, fn); /* copy rest of link */
223 #if defined(HAVE_WIN32)
224 strip_double_slashes(attr->ofname);
225 strip_double_slashes(attr->olname);
229 extern char *getuser(uid_t uid, char *name, int len);
230 extern char *getgroup(gid_t gid, char *name, int len);
233 * Print an ls style message, also send M_RESTORED
235 void print_ls_output(JCR *jcr, ATTR *attr)
239 char en1[30], en2[30];
244 jcr->id_list = new_guid_list();
247 p = encode_mode(attr->statp.st_mode, buf);
248 p += sprintf(p, " %2d ", (uint32_t)attr->statp.st_nlink);
249 p += sprintf(p, "%-8.8s %-8.8s",
250 guid->uid_to_name(attr->statp.st_uid, en1, sizeof(en1)),
251 guid->gid_to_name(attr->statp.st_gid, en2, sizeof(en2)));
252 p += sprintf(p, "%10.10s ", edit_uint64(attr->statp.st_size, ec1));
253 p = encode_time(attr->statp.st_ctime, p);
256 for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
259 if (attr->type == FT_LNK) {
265 for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
271 Dmsg1(20, "%s", buf);
272 Jmsg(jcr, M_RESTORED, 1, "%s", buf);