]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/attr.c
Fix header file includes.
[bacula/bacula] / bacula / src / lib / attr.c
1 /*
2  *   attr.c  Unpack an Attribute record returned from the tape
3  *
4  *    Kern Sibbald, June MMIII  (code pulled from filed/restore.c and updated)
5  *
6  *   Version $Id$
7  */
8 /*
9    Copyright (C) 2003-2006 Kern Sibbald
10
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.
15
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.
20
21  */
22
23 #include "bacula.h"
24 #include "jcr.h"
25
26
27 ATTR *new_attr()
28 {
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);
34    return attr;
35 }
36
37 void free_attr(ATTR *attr)
38 {
39    free_pool_memory(attr->olname);
40    free_pool_memory(attr->ofname);
41    free_pool_memory(attr->attrEx);
42    free(attr);
43 }
44
45 int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr)
46 {
47    char *p;
48    /*
49     * An Attributes record consists of:
50     *    File_index
51     *    Type   (FT_types)
52     *    Filename
53     *    Attributes
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
57     *    Data_stream
58     *
59     */
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);
65       return 0;
66    }
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;
70    } else {
71       attr->data_stream = 0;
72    }
73    attr->type &= FT_MASK;             /* keep only type bits */
74    p = rec;
75    while (*p++ != ' ')               /* skip record file index */
76       { }
77    while (*p++ != ' ')               /* skip type */
78       { }
79
80    attr->fname = p;                   /* set filname position */
81    while (*p++ != 0)                  /* skip filename */
82       { }
83    attr->attr = p;                    /* set attributes position */
84    while (*p++ != 0)                  /* skip attributes */
85       { }
86    attr->lname = p;                   /* set link position */
87    while (*p++ != 0)                  /* skip link */
88       { }
89    pm_strcpy(attr->attrEx, p);        /* copy extended attributes, if any */
90
91    if (attr->data_stream) {
92       int64_t val;
93       while (*p++ != 0)               /* skip extended attributes */
94          { }
95       from_base64(&val, p);
96       attr->data_stream = (int32_t)val;
97    }
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);
101    *attr->ofname = 0;
102    *attr->olname = 0;
103    return 1;
104 }
105
106 static void strip_double_slashes(char *fname)
107 {
108    char *p = fname;
109    while (p && *p) {
110       p = strchr(p, '/');
111       if (p && p[1] == '/') {
112          strcpy(p, p+1);
113       }      
114       if (p) {
115          p++;
116       }
117    }
118 }
119
120 /*
121  * Build attr->ofname from attr->fname and
122  *       attr->olname from attr->olname
123  */
124 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
125 {
126    /*
127     * Prepend the where directory so that the
128     * files are put where the user wants.
129     *
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.
134     *
135     */
136    if (jcr->where[0] == 0) {
137       pm_strcpy(attr->ofname, attr->fname);
138       pm_strcpy(attr->olname, attr->lname);
139    } else {
140       const char *fn;
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 / */
146       }
147 #endif
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, "/");
152       }
153       pm_strcat(attr->ofname, fn); /* copy rest of name */
154       /*
155        * Fixup link name -- if it is an absolute path
156        */
157       if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
158          bool add_link;
159          /* Always add prefix to hard links (FT_LNKSAVED) and
160           *  on user request to soft links
161           */
162          if (attr->lname[0] == '/' &&
163              (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
164             pm_strcpy(attr->olname, jcr->where);
165             add_link = true;
166          } else {
167             attr->olname[0] = 0;
168             add_link = false;
169          }
170
171 #if defined(HAVE_WIN32)
172          if (attr->lname[1] == ':') {
173             attr->lname[1] = '/';    /* turn : into / */
174          }
175 #endif
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, "/");
180          }
181          pm_strcat(attr->olname, fn);     /* copy rest of link */
182       }
183    }
184 #if defined(HAVE_WIN32)
185       strip_double_slashes(attr->ofname);
186       strip_double_slashes(attr->olname);
187 #endif
188 }
189
190 extern char *getuser(uid_t uid, char *name, int len);
191 extern char *getgroup(gid_t gid, char *name, int len);
192
193 /*
194  * Print an ls style message, also send M_RESTORED
195  */
196 void print_ls_output(JCR *jcr, ATTR *attr)
197 {
198    char buf[5000];
199    char ec1[30];
200    char en1[30], en2[30];
201    char *p, *f;
202
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);
209    *p++ = ' ';
210    *p++ = ' ';
211    for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
212       *p++ = *f++;
213    }
214    if (attr->type == FT_LNK) {
215       *p++ = ' ';
216       *p++ = '-';
217       *p++ = '>';
218       *p++ = ' ';
219       /* Copy link name */
220       for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
221          *p++ = *f++;
222       }
223    }
224    *p++ = '\n';
225    *p = 0;
226    Dmsg1(20, "%s", buf);
227    Jmsg(jcr, M_RESTORED, 1, "%s", buf);
228 }