]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/create_file.c
8b01761b77dbef65a5091cace88873b98d2f0c60
[bacula/bacula] / bacula / src / findlib / create_file.c
1 /*
2  *  Create a file, and reset the modes
3  *
4  *    Kern Sibbald, November MM
5  *
6  *   Version $Id$
7  *
8  */
9 /*
10    Copyright (C) 2000-2005 Kern Sibbald
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
14    version 2 as ammended with additional clauses defined in the
15    file LICENSE in the main source directory.
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 
20    the file LICENSE for additional details.
21
22  */
23
24 #include "bacula.h"
25 #include "find.h"
26
27 #ifndef S_IRWXUGO
28 #define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO)
29 #endif
30
31 #ifndef IS_CTG
32 #define IS_CTG(x) 0
33 #define O_CTG 0
34 #endif
35
36 static int separate_path_and_file(JCR *jcr, char *fname, char *ofile);
37 static int path_already_seen(JCR *jcr, char *path, int pnl);
38
39
40 /*
41  * Create the file, or the directory
42  *
43  *  fname is the original filename
44  *  ofile is the output filename (may be in a different directory)
45  *
46  * Returns:  CF_SKIP     if file should be skipped
47  *           CF_ERROR    on error
48  *           CF_EXTRACT  file created and data to restore
49  *           CF_CREATED  file created no data to restore
50  *
51  *   Note, we create the file here, except for special files,
52  *     we do not set the attributes because we want to first
53  *     write the file, then when the writing is done, set the
54  *     attributes.
55  *   So, we return with the file descriptor open for normal
56  *     files.
57  *
58  */
59 int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace)
60 {
61    int new_mode, parent_mode, mode;
62    uid_t uid;
63    gid_t gid;
64    int pnl;
65    bool exists = false;
66    struct stat mstatp;
67
68    if (is_win32_stream(attr->data_stream)) {
69       set_win32_backup(bfd);
70    } else {
71       set_portable_backup(bfd);
72    }
73
74    new_mode = attr->statp.st_mode;
75    Dmsg2(300, "newmode=%x file=%s\n", new_mode, attr->ofname);
76    parent_mode = S_IWUSR | S_IXUSR | new_mode;
77    gid = attr->statp.st_gid;
78    uid = attr->statp.st_uid;
79
80    Dmsg2(400, "Replace=%c %d\n", (char)replace, replace);
81    if (lstat(attr->ofname, &mstatp) == 0) {
82       exists = true;
83       switch (replace) {
84       case REPLACE_IFNEWER:
85          if (attr->statp.st_mtime <= mstatp.st_mtime) {
86             Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not newer: %s\n"), attr->ofname);
87             return CF_SKIP;
88          }
89          break;
90
91       case REPLACE_IFOLDER:
92          if (attr->statp.st_mtime >= mstatp.st_mtime) {
93             Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Not older: %s\n"), attr->ofname);
94             return CF_SKIP;
95          }
96          break;
97
98       case REPLACE_NEVER:
99          Jmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), attr->ofname);
100          return CF_SKIP;
101
102       case REPLACE_ALWAYS:
103          break;
104       }
105    }
106    switch (attr->type) {
107    case FT_LNKSAVED:                  /* Hard linked, file already saved */
108    case FT_LNK:
109    case FT_RAW:
110    case FT_FIFO:
111    case FT_SPEC:
112    case FT_REGE:                      /* empty file */
113    case FT_REG:                       /* regular file */
114       if (exists) {
115          /* Get rid of old copy */
116          if (unlink(attr->ofname) == -1) {
117             berrno be;
118             Jmsg(jcr, M_ERROR, 0, _("File %s already exists and could not be replaced. ERR=%s.\n"),
119                attr->ofname, be.strerror());
120             /* Continue despite error */
121          }
122       }
123       /*
124        * Here we do some preliminary work for all the above
125        *   types to create the path to the file if it does
126        *   not already exist.  Below, we will split to
127        *   do the file type specific work
128        */
129       pnl = separate_path_and_file(jcr, attr->fname, attr->ofname);
130       if (pnl < 0) {
131          return CF_ERROR;
132       }
133
134       /*
135        * If path length is <= 0 we are making a file in the root
136        *  directory. Assume that the directory already exists.
137        */
138       if (pnl > 0) {
139          char savechr;
140          savechr = attr->ofname[pnl];
141          attr->ofname[pnl] = 0;                 /* terminate path */
142
143          if (!path_already_seen(jcr, attr->ofname, pnl)) {
144             Dmsg1(50, "Make path %s\n", attr->ofname);
145             /*
146              * If we need to make the directory, ensure that it is with
147              * execute bit set (i.e. parent_mode), and preserve what already
148              * exists. Normally, this should do nothing.
149              */
150             if (make_path(jcr, attr->ofname, parent_mode, parent_mode, uid, gid, 1, NULL) != 0) {
151                Dmsg1(10, "Could not make path. %s\n", attr->ofname);
152                attr->ofname[pnl] = savechr;     /* restore full name */
153                return CF_ERROR;
154             }
155          }
156          attr->ofname[pnl] = savechr;           /* restore full name */
157       }
158
159       /* Now we do the specific work for each file type */
160       switch(attr->type) {
161       case FT_REGE:
162       case FT_REG:
163          Dmsg1(100, "Create file %s\n", attr->ofname);
164          mode =  O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; /*  O_NOFOLLOW; */
165          if (IS_CTG(attr->statp.st_mode)) {
166             mode |= O_CTG;               /* set contiguous bit if needed */
167          }
168          Dmsg1(50, "Create file: %s\n", attr->ofname);
169          if (is_bopen(bfd)) {
170             Jmsg1(jcr, M_ERROR, 0, "bpkt already open fid=%d\n", bfd->fid);
171             bclose(bfd);
172          }
173          if ((bopen(bfd, attr->ofname, mode, S_IRUSR | S_IWUSR)) < 0) {
174             berrno be;
175             be.set_errno(bfd->berrno);
176             Jmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"),
177                   attr->ofname, be.strerror());
178             return CF_ERROR;
179          }
180          return CF_EXTRACT;
181 #ifndef HAVE_WIN32  // none of these exists on MS Windows
182       case FT_RAW:                    /* Bacula raw device e.g. /dev/sda1 */
183       case FT_FIFO:                   /* Bacula fifo to save data */
184       case FT_SPEC:
185          if (S_ISFIFO(attr->statp.st_mode)) {
186             Dmsg1(200, "Restore fifo: %s\n", attr->ofname);
187             if (mkfifo(attr->ofname, attr->statp.st_mode) != 0 && errno != EEXIST) {
188                berrno be;
189                Jmsg2(jcr, M_ERROR, 0, _("Cannot make fifo %s: ERR=%s\n"),
190                      attr->ofname, be.strerror());
191                return CF_ERROR;
192             }
193          } else {
194             Dmsg1(200, "Restore node: %s\n", attr->ofname);
195             if (mknod(attr->ofname, attr->statp.st_mode, attr->statp.st_rdev) != 0 && errno != EEXIST) {
196                berrno be;
197                Jmsg2(jcr, M_ERROR, 0, _("Cannot make node %s: ERR=%s\n"),
198                      attr->ofname, be.strerror());
199                return CF_ERROR;
200             }
201          }
202          if (attr->type == FT_RAW || attr->type == FT_FIFO) {
203             btimer_t *tid;
204             Dmsg1(200, "FT_RAW|FT_FIFO %s\n", attr->ofname);
205             mode =  O_WRONLY | O_BINARY;
206             /* Timeout open() in 60 seconds */
207             if (attr->type == FT_FIFO) {
208                tid = start_thread_timer(pthread_self(), 60);
209             } else {
210                tid = NULL;
211             }
212             if (is_bopen(bfd)) {
213                Jmsg1(jcr, M_ERROR, 0, "bpkt already open fid=%d\n", bfd->fid);
214             }
215             if ((bopen(bfd, attr->ofname, mode, 0)) < 0) {
216                berrno be;
217                be.set_errno(bfd->berrno);
218                Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
219                      attr->ofname, be.strerror());
220                stop_thread_timer(tid);
221                return CF_ERROR;
222             }
223             stop_thread_timer(tid);
224             return CF_EXTRACT;
225          }
226          Dmsg1(200, "FT_SPEC %s\n", attr->ofname);
227          return CF_CREATED;
228
229       case FT_LNK:
230          Dmsg2(130, "FT_LNK should restore: %s -> %s\n", attr->ofname, attr->olname);
231          if (symlink(attr->olname, attr->ofname) != 0 && errno != EEXIST) {
232             berrno be;
233             Jmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"),
234                   attr->ofname, attr->olname, be.strerror());
235             return CF_ERROR;
236          }
237          return CF_CREATED;
238
239       case FT_LNKSAVED:                  /* Hard linked, file already saved */
240          Dmsg2(130, "Hard link %s => %s\n", attr->ofname, attr->olname);
241          if (link(attr->olname, attr->ofname) != 0) {
242             berrno be;
243             Jmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"),
244                   attr->ofname, attr->olname, be.strerror());
245             return CF_ERROR;
246          }
247          return CF_CREATED;
248 #endif
249       } /* End inner switch */
250
251    case FT_DIRBEGIN:
252    case FT_DIREND:
253       Dmsg2(200, "Make dir mode=%o dir=%s\n", new_mode, attr->ofname);
254       if (make_path(jcr, attr->ofname, new_mode, parent_mode, uid, gid, 0, NULL) != 0) {
255          return CF_ERROR;
256       }
257       /*
258        * If we are using the Win32 Backup API, we open the
259        *   directory so that the security info will be read
260        *   and saved.
261        */
262       if (!is_portable_backup(bfd)) {
263          if (is_bopen(bfd)) {
264             Jmsg1(jcr, M_ERROR, 0, "bpkt already open fid=%d\n", bfd->fid);
265          }
266          if ((bopen(bfd, attr->ofname, O_WRONLY|O_BINARY, 0)) < 0) {
267             berrno be;
268             be.set_errno(bfd->berrno);
269 #ifdef HAVE_WIN32
270             /* Check for trying to create a drive, if so, skip */
271             if (attr->ofname[1] == ':' && attr->ofname[2] == '/' && attr->ofname[3] == 0) {
272                return CF_SKIP;
273             }
274 #endif
275             Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
276                   attr->ofname, be.strerror());
277             return CF_ERROR;
278          }
279          return CF_EXTRACT;
280       } else {
281          return CF_CREATED;
282       }
283
284    /* The following should not occur */
285    case FT_NOACCESS:
286    case FT_NOFOLLOW:
287    case FT_NOSTAT:
288    case FT_DIRNOCHG:
289    case FT_NOCHG:
290    case FT_ISARCH:
291    case FT_NORECURSE:
292    case FT_NOFSCHG:
293    case FT_NOOPEN:
294       Jmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), attr->fname, attr->type);
295       break;
296    default:
297       Jmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), attr->type, attr->fname);
298       break;
299    }
300    return CF_ERROR;
301 }
302
303 /*
304  *  Returns: > 0 index into path where last path char is.
305  *           0  no path
306  *           -1 filename is zero length
307  */
308 static int separate_path_and_file(JCR *jcr, char *fname, char *ofile)
309 {
310    char *f, *p;
311    int fnl, pnl;
312
313    /* Separate pathname and filename */
314    for (p=f=ofile; *p; p++) {
315       if (*p == '/') {
316          f = p;                    /* possible filename */
317       }
318    }
319    if (*f == '/') {
320       f++;
321    }
322
323    fnl = p - f;
324    if (fnl == 0) {
325       /* The filename length must not be zero here because we
326        *  are dealing with a file (i.e. FT_REGE or FT_REG).
327        */
328       Jmsg1(jcr, M_ERROR, 0, _("Zero length filename: %s\n"), fname);
329       return -1;
330    }
331    pnl = f - ofile - 1;
332    return pnl;
333 }
334
335 /*
336  * Primitive caching of path to prevent recreating a pathname
337  *   each time as long as we remain in the same directory.
338  */
339 static int path_already_seen(JCR *jcr, char *path, int pnl)
340 {
341    if (!jcr->cached_path) {
342       jcr->cached_path = get_pool_memory(PM_FNAME);
343    }
344    if (jcr->cached_pnl == pnl && strcmp(path, jcr->cached_path) == 0) {
345       return 1;
346    }
347    pm_strcpy(&jcr->cached_path, path);
348    jcr->cached_pnl = pnl;
349    return 0;
350 }