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 Copyright (C) 2003-2006 Kern Sibbald
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 version 2 as amended with additional clauses defined in the
14 file LICENSE in the main source directory.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 the file LICENSE for additional details.
29 ATTR *attr = (ATTR *)malloc(sizeof(ATTR));
30 memset(attr, 0, sizeof(ATTR));
31 attr->ofname = get_pool_memory(PM_FNAME);
32 attr->olname = get_pool_memory(PM_FNAME);
33 attr->attrEx = get_pool_memory(PM_FNAME);
37 void free_attr(ATTR *attr)
39 free_pool_memory(attr->olname);
40 free_pool_memory(attr->ofname);
41 free_pool_memory(attr->attrEx);
45 int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr)
49 * An Attributes record consists of:
54 * Link name (if file linked i.e. FT_LNK)
55 * Extended attributes (Win32)
56 * plus optional values determined by AR_ flags in upper bits of Type
60 attr->stream = stream;
61 Dmsg1(400, "Attr: %s\n", rec);
62 if (sscanf(rec, "%d %d", &attr->file_index, &attr->type) != 2) {
63 Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec);
64 Dmsg1(100, "\nError scanning attributes. %s\n", rec);
67 Dmsg2(400, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
68 if (attr->type & AR_DATA_STREAM) {
69 attr->data_stream = 1;
71 attr->data_stream = 0;
73 attr->type &= FT_MASK; /* keep only type bits */
75 while (*p++ != ' ') /* skip record file index */
77 while (*p++ != ' ') /* skip type */
80 attr->fname = p; /* set filname position */
81 while (*p++ != 0) /* skip filename */
83 attr->attr = p; /* set attributes position */
84 while (*p++ != 0) /* skip attributes */
86 attr->lname = p; /* set link position */
87 while (*p++ != 0) /* skip link */
89 pm_strcpy(attr->attrEx, p); /* copy extended attributes, if any */
91 if (attr->data_stream) {
93 while (*p++ != 0) /* skip extended attributes */
96 attr->data_stream = (int32_t)val;
98 Dmsg7(400, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s ds=%d\n",
99 attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
100 attr->attrEx, attr->data_stream);
106 static void strip_double_slashes(char *fname)
111 if (p && p[1] == '/') {
121 * Build attr->ofname from attr->fname and
122 * attr->olname from attr->olname
124 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
127 * Prepend the where directory so that the
128 * files are put where the user wants.
130 * We do a little jig here to handle Win32 files with
131 * a drive letter -- we simply change the drive
132 * from, for example, c: to c/ for
133 * every filename if a prefix is supplied.
136 if (jcr->where[0] == 0) {
137 pm_strcpy(attr->ofname, attr->fname);
138 pm_strcpy(attr->olname, attr->lname);
141 int wherelen = strlen(jcr->where);
142 pm_strcpy(attr->ofname, jcr->where); /* copy prefix */
143 #if defined(HAVE_WIN32)
144 if (attr->fname[1] == ':') {
145 attr->fname[1] = '/'; /* convert : to / */
148 fn = attr->fname; /* take whole name */
149 /* Ensure where is terminated with a slash */
150 if (jcr->where[wherelen-1] != '/' && fn[0] != '/') {
151 pm_strcat(attr->ofname, "/");
153 pm_strcat(attr->ofname, fn); /* copy rest of name */
155 * Fixup link name -- if it is an absolute path
157 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
162 if (attr->lname[0] == '/' &&
163 (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
164 pm_strcpy(attr->olname, jcr->where);
171 #if defined(HAVE_WIN32)
172 if (attr->lname[1] == ':') {
173 attr->lname[1] = '/'; /* turn : into / */
176 fn = attr->lname; /* take whole name */
177 /* Ensure where is terminated with a slash */
178 if (add_link && jcr->where[wherelen-1] != '/' && fn[0] != '/') {
179 pm_strcat(attr->olname, "/");
181 pm_strcat(attr->olname, fn); /* copy rest of link */
184 #if defined(HAVE_WIN32)
185 strip_double_slashes(attr->ofname);
186 strip_double_slashes(attr->olname);
190 extern char *getuser(uid_t uid, char *name, int len);
191 extern char *getgroup(gid_t gid, char *name, int len);
194 * Print an ls style message, also send M_RESTORED
196 void print_ls_output(JCR *jcr, ATTR *attr)
200 char en1[30], en2[30];
203 p = encode_mode(attr->statp.st_mode, buf);
204 p += sprintf(p, " %2d ", (uint32_t)attr->statp.st_nlink);
205 p += sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid, en1, sizeof(en1)),
206 getgroup(attr->statp.st_gid, en2, sizeof(en2)));
207 p += sprintf(p, "%10.10s ", edit_uint64(attr->statp.st_size, ec1));
208 p = encode_time(attr->statp.st_ctime, p);
211 for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
214 if (attr->type == FT_LNK) {
220 for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
226 Dmsg1(20, "%s", buf);
227 Jmsg(jcr, M_RESTORED, 1, "%s", buf);