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