]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/attr.c
4091331aa478317cf6348578a28764267583149d
[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 /*
10    Copyright (C) 2003-2004 Kern Sibbald and John Walker
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License as
14    published by the Free Software Foundation; either version 2 of
15    the License, or (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20    General Public License for more details.
21
22    You should have received a copy of the GNU General Public
23    License along with this program; if not, write to the Free
24    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25    MA 02111-1307, USA.
26
27  */
28
29 #include "bacula.h"
30 #include "jcr.h"
31
32 extern const int win32_client;
33
34 ATTR *new_attr()
35 {
36    ATTR *attr = (ATTR *)malloc(sizeof(ATTR));
37    memset(attr, 0, sizeof(ATTR));
38    attr->ofname = get_pool_memory(PM_FNAME);
39    attr->olname = get_pool_memory(PM_FNAME);
40    attr->attrEx = get_pool_memory(PM_FNAME);
41    return attr;
42 }
43
44 void free_attr(ATTR *attr)
45 {
46    free_pool_memory(attr->olname);
47    free_pool_memory(attr->ofname);
48    free_pool_memory(attr->attrEx);
49    free(attr);
50 }
51
52 int unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr)
53 {
54    char *p;
55    /*              
56     * An Attributes record consists of:
57     *    File_index
58     *    Type   (FT_types)
59     *    Filename
60     *    Attributes
61     *    Link name (if file linked i.e. FT_LNK)
62     *    Extended attributes (Win32)
63     *  plus optional values determined by AR_ flags in upper bits of Type
64     *    Data_stream
65     *
66     */
67    attr->stream = stream;
68    Dmsg1(100, "Attr: %s\n", rec);
69    if (sscanf(rec, "%d %d", &attr->file_index, &attr->type) != 2) {
70       Jmsg(jcr, M_FATAL, 0, _("Error scanning attributes: %s\n"), rec);
71       Dmsg1(100, "\nError scanning attributes. %s\n", rec);
72       return 0;
73    }
74    Dmsg2(100, "Got Attr: FilInx=%d type=%d\n", attr->file_index, attr->type);
75    if (attr->type & AR_DATA_STREAM) {
76       attr->data_stream = 1;
77    } else {
78       attr->data_stream = 0;
79    }
80    attr->type &= FT_MASK;             /* keep only type bits */
81    p = rec;
82    while (*p++ != ' ')               /* skip record file index */
83       { }
84    while (*p++ != ' ')               /* skip type */
85       { }
86    
87    attr->fname = p;                   /* set filname position */
88    while (*p++ != 0)                  /* skip filename */
89       { }
90    attr->attr = p;                    /* set attributes position */
91    while (*p++ != 0)                  /* skip attributes */
92       { }
93    attr->lname = p;                   /* set link position */
94    while (*p++ != 0)                  /* skip link */
95       { }
96    pm_strcpy(attr->attrEx, p);        /* copy extended attributes, if any */
97
98    if (attr->data_stream) {
99       int64_t val;
100       while (*p++ != 0)               /* skip extended attributes */
101          { }
102       from_base64(&val, p);
103       attr->data_stream = (int32_t)val;
104    }
105    Dmsg7(200, "unpack_attr FI=%d Type=%d fname=%s attr=%s lname=%s attrEx=%s ds=%d\n",
106       attr->file_index, attr->type, attr->fname, attr->attr, attr->lname,
107       attr->attrEx, attr->data_stream);
108    *attr->ofname = 0;
109    *attr->olname = 0;
110    return 1;
111 }
112
113 /*
114  * Build attr->ofname from attr->fname and
115  *       attr->olname from attr->olname 
116  */
117 void build_attr_output_fnames(JCR *jcr, ATTR *attr)
118 {
119    /*
120     * Prepend the where directory so that the
121     * files are put where the user wants.
122     *
123     * We do a little jig here to handle Win32 files with
124     *   a drive letter -- we simply change the drive
125     *   from, for example, c: to c/ for
126     *   every filename if a prefix is supplied.
127     *     
128     */
129    if (jcr->where[0] == 0) {
130       pm_strcpy(attr->ofname, attr->fname);
131       pm_strcpy(attr->olname, attr->lname);
132    } else {
133       const char *fn;
134       int wherelen = strlen(jcr->where);
135       pm_strcpy(attr->ofname, jcr->where);  /* copy prefix */
136       if (win32_client && attr->fname[1] == ':') {
137          attr->fname[1] = '/';     /* convert : to / */
138       }
139       fn = attr->fname;            /* take whole name */
140       /* Ensure where is terminated with a slash */
141       if (jcr->where[wherelen-1] != '/' && fn[0] != '/') {
142          pm_strcat(attr->ofname, "/");
143       }   
144       pm_strcat(attr->ofname, fn); /* copy rest of name */
145       /*
146        * Fixup link name -- if it is an absolute path
147        */
148       if (attr->type == FT_LNKSAVED || attr->type == FT_LNK) {
149          bool add_link;
150          /* Always add prefix to hard links (FT_LNKSAVED) and
151           *  on user request to soft links
152           */
153          if (attr->lname[0] == '/' &&
154              (attr->type == FT_LNKSAVED || jcr->prefix_links)) {
155             pm_strcpy(attr->olname, jcr->where);
156             add_link = true;
157          } else {
158             attr->olname[0] = 0;
159             add_link = false;
160          }
161          if (win32_client && attr->lname[1] == ':') {
162             attr->lname[1] = '/';    /* turn : into / */
163          }
164          fn = attr->lname;       /* take whole name */
165          /* Ensure where is terminated with a slash */
166          if (add_link && jcr->where[wherelen-1] != '/' && fn[0] != '/') {
167             pm_strcat(attr->olname, "/");
168          }   
169          pm_strcat(attr->olname, fn);     /* copy rest of link */
170       }
171    }
172 }
173
174 extern char *getuser(uid_t uid, char *name, int len);
175 extern char *getgroup(gid_t gid, char *name, int len);
176
177 /*
178  * Print an ls style message, also send M_RESTORED
179  */
180 void print_ls_output(JCR *jcr, ATTR *attr)
181 {
182    char buf[5000]; 
183    char ec1[30];
184    char en1[30], en2[30];
185    char *p, *f;
186
187    p = encode_mode(attr->statp.st_mode, buf);
188    p += sprintf(p, "  %2d ", (uint32_t)attr->statp.st_nlink);
189    p += sprintf(p, "%-8.8s %-8.8s", getuser(attr->statp.st_uid, en1, sizeof(en1)),
190                 getgroup(attr->statp.st_gid, en2, sizeof(en2)));
191    p += sprintf(p, "%8.8s ", edit_uint64(attr->statp.st_size, ec1));
192    p = encode_time(attr->statp.st_ctime, p);
193    *p++ = ' ';
194    *p++ = ' ';
195    for (f=attr->ofname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
196       *p++ = *f++;
197    }
198    if (attr->type == FT_LNK) {
199       *p++ = ' ';
200       *p++ = '-';
201       *p++ = '>';
202       *p++ = ' ';
203       /* Copy link name */
204       for (f=attr->olname; *f && (p-buf) < (int)sizeof(buf)-10; ) {
205          *p++ = *f++;
206       }
207    }
208    *p++ = '\n';
209    *p = 0;
210    Dmsg1(20, "%s", buf);
211    Jmsg(jcr, M_RESTORED, 1, "%s", buf);
212 }