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, "%ld %ld", &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 #if defined(HAVE_WIN32)
107 static void strip_double_slashes(char *fname)
112 if (p && p[1] == '/') {
123 * Build attr->ofname from attr->fname and
124 * attr->olname from attr->olname
126 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
129 * Prepend the where directory so that the
130 * files are put where the user wants.
132 * We do a little jig here to handle Win32 files with
133 * a drive letter -- we simply change the drive
134 * from, for example, c: to c/ for
135 * every filename if a prefix is supplied.
138 if (jcr->where[0] == 0) {
139 pm_strcpy(attr->ofname, attr->fname);
140 pm_strcpy(attr->olname, attr->lname);
143 int wherelen = strlen(jcr->where);
144 pm_strcpy(attr->ofname, jcr->where); /* copy prefix */
145 #if defined(HAVE_WIN32)
146 if (attr->fname[1] == ':') {
147 attr->fname[1] = '/'; /* convert : to / */
150 fn = attr->fname; /* take whole name */
151 /* Ensure where is terminated with a slash */
152 if (jcr->where[wherelen-1] != '/' && fn[0] != '/') {
153 pm_strcat(attr->ofname, "/");
155 pm_strcat(attr->ofname, fn); /* copy rest of name */
157 * Fixup link name -- if it is an absolute path
159 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
164 if (attr->lname[0] == '/' &&
165 (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
166 pm_strcpy(attr->olname, jcr->where);
173 #if defined(HAVE_WIN32)
174 if (attr->lname[1] == ':') {
175 attr->lname[1] = '/'; /* turn : into / */
178 fn = attr->lname; /* take whole name */
179 /* Ensure where is terminated with a slash */
180 if (add_link && jcr->where[wherelen-1] != '/' && fn[0] != '/') {
181 pm_strcat(attr->olname, "/");
183 pm_strcat(attr->olname, fn); /* copy rest of link */
186 #if defined(HAVE_WIN32)
187 strip_double_slashes(attr->ofname);
188 strip_double_slashes(attr->olname);
192 extern char *getuser(uid_t uid, char *name, int len);
193 extern char *getgroup(gid_t gid, char *name, int len);
196 * Print an ls style message, also send M_RESTORED
198 void print_ls_output(JCR *jcr, ATTR *attr)
202 char en1[30], en2[30];
205 p = encode_mode(attr->statp.st_mode, buf);
206 p += sprintf(p, " %2d ", (uint32_t)attr->statp.st_nlink);
207 p += sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid, en1, sizeof(en1)),
208 getgroup(attr->statp.st_gid, en2, sizeof(en2)));
209 p += sprintf(p, "%10.10s ", edit_uint64(attr->statp.st_size, ec1));
210 p = encode_time(attr->statp.st_ctime, p);
213 for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
216 if (attr->type == FT_LNK) {
222 for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
228 Dmsg1(20, "%s", buf);
229 Jmsg(jcr, M_RESTORED, 1, "%s", buf);