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