]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/create_file.c
56b2df9298947e38e654e24872156ba5ca7fc6e2
[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-2006 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 amended 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    Dmsg3(200, "type=%d newmode=%x file=%s\n", attr->type, 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             Qmsg(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             Qmsg(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          Qmsg(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_RAW:                       /* raw device to be written */
108    case FT_FIFO:                      /* FIFO to be written to */
109    case FT_LNKSAVED:                  /* Hard linked, file already saved */
110    case FT_LNK:
111    case FT_SPEC:                      /* fifo, ... to be backed up */
112    case FT_REGE:                      /* empty file */
113    case FT_REG:                       /* regular file */
114       /* 
115        * Note, we do not delete FT_RAW because these are device files
116        *  or FIFOs that should already exist. If we blow it away,
117        *  we may blow away a FIFO that is being used to read the
118        *  restore data, or we may blow away a partition definition.
119        */
120       if (exists && attr->type != FT_RAW && attr->type != FT_FIFO) {
121          /* Get rid of old copy */
122          if (unlink(attr->ofname) == -1) {
123             berrno be;
124             Qmsg(jcr, M_ERROR, 0, _("File %s already exists and could not be replaced. ERR=%s.\n"),
125                attr->ofname, be.strerror());
126             /* Continue despite error */
127          }
128       }
129       /*
130        * Here we do some preliminary work for all the above
131        *   types to create the path to the file if it does
132        *   not already exist.  Below, we will split to
133        *   do the file type specific work
134        */
135       pnl = separate_path_and_file(jcr, attr->fname, attr->ofname);
136       if (pnl < 0) {
137          return CF_ERROR;
138       }
139
140       /*
141        * If path length is <= 0 we are making a file in the root
142        *  directory. Assume that the directory already exists.
143        */
144       if (pnl > 0) {
145          char savechr;
146          savechr = attr->ofname[pnl];
147          attr->ofname[pnl] = 0;                 /* terminate path */
148
149          if (!path_already_seen(jcr, attr->ofname, pnl)) {
150             Dmsg1(100, "Make path %s\n", attr->ofname);
151             /*
152              * If we need to make the directory, ensure that it is with
153              * execute bit set (i.e. parent_mode), and preserve what already
154              * exists. Normally, this should do nothing.
155              */
156             if (make_path(jcr, attr->ofname, parent_mode, parent_mode, uid, gid, 1, NULL) != 0) {
157                Dmsg1(10, "Could not make path. %s\n", attr->ofname);
158                attr->ofname[pnl] = savechr;     /* restore full name */
159                return CF_ERROR;
160             }
161          }
162          attr->ofname[pnl] = savechr;           /* restore full name */
163       }
164
165       /* Now we do the specific work for each file type */
166       switch(attr->type) {
167       case FT_REGE:
168       case FT_REG:
169          Dmsg1(100, "Create file %s\n", attr->ofname);
170          mode =  O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; /*  O_NOFOLLOW; */
171          if (IS_CTG(attr->statp.st_mode)) {
172             mode |= O_CTG;               /* set contiguous bit if needed */
173          }
174          Dmsg1(50, "Create file: %s\n", attr->ofname);
175          if (is_bopen(bfd)) {
176             Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
177             bclose(bfd);
178          }
179       
180
181          if ((bopen(bfd, attr->ofname, mode, S_IRUSR | S_IWUSR)) < 0) {
182             berrno be;
183             be.set_errno(bfd->berrno);
184             Qmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"),
185                   attr->ofname, be.strerror());
186             return CF_ERROR;
187          }
188          return CF_EXTRACT;
189
190 #ifndef HAVE_WIN32  // none of these exists on MS Windows
191       case FT_RAW:                    /* Bacula raw device e.g. /dev/sda1 */
192       case FT_FIFO:                   /* Bacula fifo to save data */
193       case FT_SPEC:
194          if (S_ISFIFO(attr->statp.st_mode)) {
195             Dmsg1(200, "Restore fifo: %s\n", attr->ofname);
196             if (mkfifo(attr->ofname, attr->statp.st_mode) != 0 && errno != EEXIST) {
197                berrno be;
198                Qmsg2(jcr, M_ERROR, 0, _("Cannot make fifo %s: ERR=%s\n"),
199                      attr->ofname, be.strerror());
200                return CF_ERROR;
201             }
202          } else if(S_ISSOCK(attr->statp.st_mode)) {
203              Dmsg1(200, "Skipping restore of socket: %s\n", attr->ofname);
204          } else {
205             Dmsg1(200, "Restore node: %s\n", attr->ofname);
206             if (mknod(attr->ofname, attr->statp.st_mode, attr->statp.st_rdev) != 0 && errno != EEXIST) {
207                berrno be;
208                Qmsg2(jcr, M_ERROR, 0, _("Cannot make node %s: ERR=%s\n"),
209                      attr->ofname, be.strerror());
210                return CF_ERROR;
211             }
212          }
213          if (attr->type == FT_RAW || attr->type == FT_FIFO) {
214             btimer_t *tid;
215             Dmsg1(200, "FT_RAW|FT_FIFO %s\n", attr->ofname);
216             mode =  O_WRONLY | O_BINARY;
217             /* Timeout open() in 60 seconds */
218             if (attr->type == FT_FIFO) {
219                Dmsg0(200, "Set FIFO timer\n");
220                tid = start_thread_timer(pthread_self(), 60);
221             } else {
222                tid = NULL;
223             }
224             if (is_bopen(bfd)) {
225                Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
226             }
227             Dmsg2(200, "open %s mode=0x%x\n", attr->ofname, mode);
228             if ((bopen(bfd, attr->ofname, mode, 0)) < 0) {
229                berrno be;
230                be.set_errno(bfd->berrno);
231                Qmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
232                      attr->ofname, be.strerror());
233                stop_thread_timer(tid);
234                return CF_ERROR;
235             }
236             stop_thread_timer(tid);
237             return CF_EXTRACT;
238          }
239          Dmsg1(200, "FT_SPEC %s\n", attr->ofname);
240          return CF_CREATED;
241
242       case FT_LNK:
243          Dmsg2(130, "FT_LNK should restore: %s -> %s\n", attr->ofname, attr->olname);
244          if (symlink(attr->olname, attr->ofname) != 0 && errno != EEXIST) {
245             berrno be;
246             Qmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"),
247                   attr->ofname, attr->olname, be.strerror());
248             return CF_ERROR;
249          }
250          return CF_CREATED;
251
252       case FT_LNKSAVED:                  /* Hard linked, file already saved */
253          Dmsg2(130, "Hard link %s => %s\n", attr->ofname, attr->olname);
254          if (link(attr->olname, attr->ofname) != 0) {
255             berrno be;
256             Qmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"),
257                   attr->ofname, attr->olname, be.strerror());
258             return CF_ERROR;
259          }
260          return CF_CREATED;
261 #endif
262       } /* End inner switch */
263
264    case FT_DIRBEGIN:
265    case FT_DIREND:
266       Dmsg2(200, "Make dir mode=%o dir=%s\n", new_mode, attr->ofname);
267       if (make_path(jcr, attr->ofname, new_mode, parent_mode, uid, gid, 0, NULL) != 0) {
268          return CF_ERROR;
269       }
270       /*
271        * If we are using the Win32 Backup API, we open the
272        *   directory so that the security info will be read
273        *   and saved.
274        */
275       if (!is_portable_backup(bfd)) {
276          if (is_bopen(bfd)) {
277             Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
278          }
279          if ((bopen(bfd, attr->ofname, O_WRONLY|O_BINARY, 0)) < 0) {
280             berrno be;
281             be.set_errno(bfd->berrno);
282 #ifdef HAVE_WIN32
283             /* Check for trying to create a drive, if so, skip */
284             if (attr->ofname[1] == ':' && attr->ofname[2] == '/' && attr->ofname[3] == 0) {
285                return CF_SKIP;
286             }
287 #endif
288             Qmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
289                   attr->ofname, be.strerror());
290             return CF_ERROR;
291          }
292          return CF_EXTRACT;
293       } else {
294          return CF_CREATED;
295       }
296
297    /* The following should not occur */
298    case FT_NOACCESS:
299    case FT_NOFOLLOW:
300    case FT_NOSTAT:
301    case FT_DIRNOCHG:
302    case FT_NOCHG:
303    case FT_ISARCH:
304    case FT_NORECURSE:
305    case FT_NOFSCHG:
306    case FT_NOOPEN:
307       Qmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), attr->fname, attr->type);
308       break;
309    default:
310       Qmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), attr->type, attr->fname);
311       break;
312    }
313    return CF_ERROR;
314 }
315
316 /*
317  *  Returns: > 0 index into path where last path char is.
318  *           0  no path
319  *           -1 filename is zero length
320  */
321 static int separate_path_and_file(JCR *jcr, char *fname, char *ofile)
322 {
323    char *f, *p;
324    int fnl, pnl;
325
326    /* Separate pathname and filename */
327    for (p=f=ofile; *p; p++) {
328       if (*p == '/') {
329          f = p;                    /* possible filename */
330       }
331    }
332    if (*f == '/') {
333       f++;
334    }
335
336    fnl = p - f;
337    if (fnl == 0) {
338       /* The filename length must not be zero here because we
339        *  are dealing with a file (i.e. FT_REGE or FT_REG).
340        */
341       Qmsg1(jcr, M_ERROR, 0, _("Zero length filename: %s\n"), fname);
342       return -1;
343    }
344    pnl = f - ofile - 1;
345    return pnl;
346 }
347
348 /*
349  * Primitive caching of path to prevent recreating a pathname
350  *   each time as long as we remain in the same directory.
351  */
352 static int path_already_seen(JCR *jcr, char *path, int pnl)
353 {
354    if (!jcr->cached_path) {
355       jcr->cached_path = get_pool_memory(PM_FNAME);
356    }
357    if (jcr->cached_pnl == pnl && strcmp(path, jcr->cached_path) == 0) {
358       return 1;
359    }
360    pm_strcpy(&jcr->cached_path, path);
361    jcr->cached_pnl = pnl;
362    return 0;
363 }