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