]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/create_file.c
This commit was manufactured by cvs2svn to create tag
[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 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    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       /* 
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) {
121          /* Get rid of old copy */
122          if (unlink(attr->ofname) == -1) {
123             berrno be;
124             Jmsg(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             Jmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
177             bclose(bfd);
178          }
179          /*
180           * If the open fails, we attempt to cd into the directory
181           *  and create the file with a relative path rather than
182           *  the full absolute path.  This is for Win32 where
183           *  path names may be too long to create.
184           */
185          if ((bopen(bfd, attr->ofname, mode, S_IRUSR | S_IWUSR)) < 0) {
186             berrno be;
187             int stat;
188             Dmsg2(000, "bopen failed errno=%d: ERR=%s\n", bfd->berrno,  
189                be.strerror(bfd->berrno));
190             if (strlen(attr->ofname) > 250) {   /* Microsoft limitation */
191                char savechr;
192                char *p, *e;
193                struct saved_cwd cwd;
194                savechr = attr->ofname[pnl];
195                attr->ofname[pnl] = 0;                 /* terminate path */
196                Dmsg1(000, "Do chdir %s\n", attr->ofname);
197                if (save_cwd(&cwd) != 0) {
198                   Jmsg0(jcr, M_ERROR, 0, _("Could not save_dirn"));
199                   attr->ofname[pnl] = savechr;
200                   return CF_ERROR;
201                }
202                p = attr->ofname;
203                while ((e = strchr(p, '/'))) {
204                   *e = 0;
205                   if (chdir(p) < 0) {
206                      berrno be;
207                      Jmsg2(jcr, M_ERROR, 0, _("Could not chdir to %s: ERR=%s\n"),
208                            attr->ofname, be.strerror());
209                      restore_cwd(&cwd, NULL, NULL);
210                      free_cwd(&cwd);
211                      attr->ofname[pnl] = savechr;
212                      *e = '/';
213                      return CF_ERROR;
214                   }
215                   *e = '/';
216                   p = e + 1;
217                }
218                if (chdir(p) < 0) {
219                   berrno be;
220                   Jmsg2(jcr, M_ERROR, 0, _("Could not chdir to %s: ERR=%s\n"),
221                         attr->ofname, be.strerror());
222                   restore_cwd(&cwd, NULL, NULL);
223                   free_cwd(&cwd);
224                   attr->ofname[pnl] = savechr;
225                   return CF_ERROR;
226                }
227                attr->ofname[pnl] = savechr;
228                Dmsg1(000, "Do open %s\n", &attr->ofname[pnl+1]);
229                if ((bopen(bfd, &attr->ofname[pnl+1], mode, S_IRUSR | S_IWUSR)) < 0) {
230                   stat = CF_ERROR;
231                } else {
232                   stat = CF_EXTRACT;
233                }
234                restore_cwd(&cwd, NULL, NULL);
235                free_cwd(&cwd);
236                if (stat == CF_EXTRACT) {
237                   return CF_EXTRACT;
238                }
239             }
240             Jmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"),
241                   attr->ofname, be.strerror(bfd->berrno));
242             return CF_ERROR;
243          }
244          return CF_EXTRACT;
245 #ifndef HAVE_WIN32  // none of these exists on MS Windows
246       case FT_RAW:                    /* Bacula raw device e.g. /dev/sda1 */
247       case FT_FIFO:                   /* Bacula fifo to save data */
248       case FT_SPEC:
249          if (S_ISFIFO(attr->statp.st_mode)) {
250             Dmsg1(200, "Restore fifo: %s\n", attr->ofname);
251             if (mkfifo(attr->ofname, attr->statp.st_mode) != 0 && errno != EEXIST) {
252                berrno be;
253                Jmsg2(jcr, M_ERROR, 0, _("Cannot make fifo %s: ERR=%s\n"),
254                      attr->ofname, be.strerror());
255                return CF_ERROR;
256             }
257          } else {
258             Dmsg1(200, "Restore node: %s\n", attr->ofname);
259             if (mknod(attr->ofname, attr->statp.st_mode, attr->statp.st_rdev) != 0 && errno != EEXIST) {
260                berrno be;
261                Jmsg2(jcr, M_ERROR, 0, _("Cannot make node %s: ERR=%s\n"),
262                      attr->ofname, be.strerror());
263                return CF_ERROR;
264             }
265          }
266          if (attr->type == FT_RAW || attr->type == FT_FIFO) {
267             btimer_t *tid;
268             Dmsg1(200, "FT_RAW|FT_FIFO %s\n", attr->ofname);
269             mode =  O_WRONLY | O_BINARY;
270             /* Timeout open() in 60 seconds */
271             if (attr->type == FT_FIFO) {
272                tid = start_thread_timer(pthread_self(), 60);
273             } else {
274                tid = NULL;
275             }
276             if (is_bopen(bfd)) {
277                Jmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
278             }
279             if ((bopen(bfd, attr->ofname, mode, 0)) < 0) {
280                berrno be;
281                be.set_errno(bfd->berrno);
282                Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
283                      attr->ofname, be.strerror());
284                stop_thread_timer(tid);
285                return CF_ERROR;
286             }
287             stop_thread_timer(tid);
288             return CF_EXTRACT;
289          }
290          Dmsg1(200, "FT_SPEC %s\n", attr->ofname);
291          return CF_CREATED;
292
293       case FT_LNK:
294          Dmsg2(130, "FT_LNK should restore: %s -> %s\n", attr->ofname, attr->olname);
295          if (symlink(attr->olname, attr->ofname) != 0 && errno != EEXIST) {
296             berrno be;
297             Jmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"),
298                   attr->ofname, attr->olname, be.strerror());
299             return CF_ERROR;
300          }
301          return CF_CREATED;
302
303       case FT_LNKSAVED:                  /* Hard linked, file already saved */
304          Dmsg2(130, "Hard link %s => %s\n", attr->ofname, attr->olname);
305          if (link(attr->olname, attr->ofname) != 0) {
306             berrno be;
307             Jmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"),
308                   attr->ofname, attr->olname, be.strerror());
309             return CF_ERROR;
310          }
311          return CF_CREATED;
312 #endif
313       } /* End inner switch */
314
315    case FT_DIRBEGIN:
316    case FT_DIREND:
317       Dmsg2(200, "Make dir mode=%o dir=%s\n", new_mode, attr->ofname);
318       if (make_path(jcr, attr->ofname, new_mode, parent_mode, uid, gid, 0, NULL) != 0) {
319          return CF_ERROR;
320       }
321       /*
322        * If we are using the Win32 Backup API, we open the
323        *   directory so that the security info will be read
324        *   and saved.
325        */
326       if (!is_portable_backup(bfd)) {
327          if (is_bopen(bfd)) {
328             Jmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
329          }
330          if ((bopen(bfd, attr->ofname, O_WRONLY|O_BINARY, 0)) < 0) {
331             berrno be;
332             be.set_errno(bfd->berrno);
333 #ifdef HAVE_WIN32
334             /* Check for trying to create a drive, if so, skip */
335             if (attr->ofname[1] == ':' && attr->ofname[2] == '/' && attr->ofname[3] == 0) {
336                return CF_SKIP;
337             }
338 #endif
339             Jmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
340                   attr->ofname, be.strerror());
341             return CF_ERROR;
342          }
343          return CF_EXTRACT;
344       } else {
345          return CF_CREATED;
346       }
347
348    /* The following should not occur */
349    case FT_NOACCESS:
350    case FT_NOFOLLOW:
351    case FT_NOSTAT:
352    case FT_DIRNOCHG:
353    case FT_NOCHG:
354    case FT_ISARCH:
355    case FT_NORECURSE:
356    case FT_NOFSCHG:
357    case FT_NOOPEN:
358       Jmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), attr->fname, attr->type);
359       break;
360    default:
361       Jmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), attr->type, attr->fname);
362       break;
363    }
364    return CF_ERROR;
365 }
366
367 /*
368  *  Returns: > 0 index into path where last path char is.
369  *           0  no path
370  *           -1 filename is zero length
371  */
372 static int separate_path_and_file(JCR *jcr, char *fname, char *ofile)
373 {
374    char *f, *p;
375    int fnl, pnl;
376
377    /* Separate pathname and filename */
378    for (p=f=ofile; *p; p++) {
379       if (*p == '/') {
380          f = p;                    /* possible filename */
381       }
382    }
383    if (*f == '/') {
384       f++;
385    }
386
387    fnl = p - f;
388    if (fnl == 0) {
389       /* The filename length must not be zero here because we
390        *  are dealing with a file (i.e. FT_REGE or FT_REG).
391        */
392       Jmsg1(jcr, M_ERROR, 0, _("Zero length filename: %s\n"), fname);
393       return -1;
394    }
395    pnl = f - ofile - 1;
396    return pnl;
397 }
398
399 /*
400  * Primitive caching of path to prevent recreating a pathname
401  *   each time as long as we remain in the same directory.
402  */
403 static int path_already_seen(JCR *jcr, char *path, int pnl)
404 {
405    if (!jcr->cached_path) {
406       jcr->cached_path = get_pool_memory(PM_FNAME);
407    }
408    if (jcr->cached_pnl == pnl && strcmp(path, jcr->cached_path) == 0) {
409       return 1;
410    }
411    pm_strcpy(&jcr->cached_path, path);
412    jcr->cached_pnl = pnl;
413    return 0;
414 }