2 Bacula® - The Network Backup Solution
4 Copyright (C) 2003-2010 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 Kern Sibbald.
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)
40 ATTR *new_attr(JCR *jcr)
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);
52 void free_attr(ATTR *attr)
54 free_pool_memory(attr->olname);
55 free_pool_memory(attr->ofname);
56 free_pool_memory(attr->attrEx);
60 int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, int32_t reclen, 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, "%d %d", &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 if (attr->type == FT_RESTORE_FIRST) {
106 /* We have an object, so do a binary copy */
107 object_len = reclen + rec - p;
108 attr->attrEx = check_pool_memory_size(attr->attrEx, object_len + 1);
109 memcpy(attr->attrEx, p, object_len);
110 /* Add a EOS for those who attempt to print the object */
111 p = attr->attrEx + object_len;
114 pm_strcpy(attr->attrEx, p); /* copy extended attributes, if any */
115 if (attr->data_stream) {
117 while (*p++ != 0) /* skip extended attributes */
119 from_base64(&val, p);
120 attr->data_stream = (int32_t)val;
123 Dmsg7(400, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s ds=%d\n",
124 attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
125 attr->attrEx, attr->data_stream);
131 #if defined(HAVE_WIN32)
132 static void strip_double_slashes(char *fname)
136 p = strpbrk(p, "/\\");
138 if (IsPathSeparator(p[1])) {
148 * Build attr->ofname from attr->fname and
149 * attr->olname from attr->olname
151 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
154 * Prepend the where directory so that the
155 * files are put where the user wants.
157 * We do a little jig here to handle Win32 files with
158 * a drive letter -- we simply change the drive
159 * from, for example, c: to c/ for
160 * every filename if a prefix is supplied.
164 if (jcr->where_bregexp) {
166 apply_bregexps(attr->fname, jcr->where_bregexp, &ret);
167 pm_strcpy(attr->ofname, ret);
169 if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
170 /* Always add prefix to hard links (FT_LNKSAVED) and
171 * on user request to soft links
174 if ((attr->type == FT_LNKSAVED || jcr->prefix_links)) {
175 apply_bregexps(attr->lname, jcr->where_bregexp, &ret);
176 pm_strcpy(attr->olname, ret);
179 pm_strcpy(attr->olname, attr->lname);
183 } else if (jcr->where[0] == 0) {
184 pm_strcpy(attr->ofname, attr->fname);
185 pm_strcpy(attr->olname, attr->lname);
189 int wherelen = strlen(jcr->where);
190 pm_strcpy(attr->ofname, jcr->where); /* copy prefix */
191 #if defined(HAVE_WIN32)
192 if (attr->fname[1] == ':') {
193 attr->fname[1] = '/'; /* convert : to / */
196 fn = attr->fname; /* take whole name */
197 /* Ensure where is terminated with a slash */
198 if (!IsPathSeparator(jcr->where[wherelen-1]) && !IsPathSeparator(fn[0])) {
199 pm_strcat(attr->ofname, "/");
201 pm_strcat(attr->ofname, fn); /* copy rest of name */
203 * Fixup link name -- if it is an absolute path
205 if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
207 /* Always add prefix to hard links (FT_LNKSAVED) and
208 * on user request to soft links
210 if (IsPathSeparator(attr->lname[0]) &&
211 (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
212 pm_strcpy(attr->olname, jcr->where);
219 #if defined(HAVE_WIN32)
220 if (attr->lname[1] == ':') {
221 attr->lname[1] = '/'; /* turn : into / */
224 fn = attr->lname; /* take whole name */
225 /* Ensure where is terminated with a slash */
227 !IsPathSeparator(jcr->where[wherelen-1]) &&
228 !IsPathSeparator(fn[0])) {
229 pm_strcat(attr->olname, "/");
231 pm_strcat(attr->olname, fn); /* copy rest of link */
234 #if defined(HAVE_WIN32)
235 strip_double_slashes(attr->ofname);
236 strip_double_slashes(attr->olname);
240 extern char *getuser(uid_t uid, char *name, int len);
241 extern char *getgroup(gid_t gid, char *name, int len);
244 * Print an ls style message, also send M_RESTORED
246 void print_ls_output(JCR *jcr, ATTR *attr)
250 char en1[30], en2[30];
254 if (attr->type == FT_DELETED) { /* TODO: change this to get last seen values */
255 bsnprintf(buf, sizeof(buf),
256 "---------- - - - - ---------- -------- %s\n", attr->ofname);
257 Dmsg1(20, "%s", buf);
258 Jmsg(jcr, M_RESTORED, 1, "%s", buf);
263 jcr->id_list = new_guid_list();
266 p = encode_mode(attr->statp.st_mode, buf);
267 p += sprintf(p, " %2d ", (uint32_t)attr->statp.st_nlink);
268 p += sprintf(p, "%-8.8s %-8.8s",
269 guid->uid_to_name(attr->statp.st_uid, en1, sizeof(en1)),
270 guid->gid_to_name(attr->statp.st_gid, en2, sizeof(en2)));
271 p += sprintf(p, "%12.12s ", edit_int64(attr->statp.st_size, ec1));
272 p = encode_time(attr->statp.st_ctime, p);
275 for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
278 if (attr->type == FT_LNK) {
284 for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
290 Dmsg1(20, "%s", buf);
291 Jmsg(jcr, M_RESTORED, 1, "%s", buf);