]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/file_dev.c
Big backport from Enterprise
[bacula/bacula] / bacula / src / stored / file_dev.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2017 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *
21  *   file_dev.c  -- low level operations on file devices
22  *
23  *     written by, Kern Sibbald, MM
24  *     separated from dev.c February 2014
25  *
26  */
27
28 #include "bacula.h"
29 #include "stored.h"
30
31 static const int dbglvl = 100;
32
33 /* Imported functions */
34 const char *mode_to_str(int mode);
35
36
37 /* default primitives are designed for file */
38 int DEVICE::d_open(const char *pathname, int flags)
39 {
40    return ::open(pathname, flags | O_CLOEXEC);
41 }
42
43 int DEVICE::d_close(int fd)
44 {
45    return ::close(fd);
46 }
47
48 int DEVICE::d_ioctl(int fd, ioctl_req_t request, char *mt_com)
49 {
50 #ifdef HAVE_WIN32
51    return -1;
52 #else
53    return ::ioctl(fd, request, mt_com);
54 #endif
55 }
56
57 ssize_t DEVICE::d_read(int fd, void *buffer, size_t count)
58 {
59    return ::read(fd, buffer, count);
60 }
61
62 ssize_t DEVICE::d_write(int fd, const void *buffer, size_t count)
63 {
64    return ::write(fd, buffer, count);
65 }
66
67 /* Rewind file device */
68 bool DEVICE::rewind(DCR *dcr)
69
70 {
71    Enter(dbglvl);
72    Dmsg3(400, "rewind res=%d fd=%d %s\n", num_reserved(), m_fd, print_name());
73    state &= ~(ST_EOT|ST_EOF|ST_WEOT);  /* remove EOF/EOT flags */
74    block_num = file = 0;
75    file_size = 0;
76    file_addr = 0;
77    if (m_fd < 0) {
78       Mmsg1(errmsg, _("Rewind failed: device %s is not open.\n"), print_name());
79       return false;
80    }
81    if (is_file()) {
82       if (lseek(dcr, (boffset_t)0, SEEK_SET) < 0) {
83          berrno be;
84          dev_errno = errno;
85          Mmsg2(errmsg, _("lseek error on %s. ERR=%s.\n"),
86             print_name(), be.bstrerror());
87          return false;
88       }
89    }
90    return true;
91 }
92
93 /*
94  * Reposition the device to file, block
95  * Returns: false on failure
96  *          true  on success
97  */
98 bool DEVICE::reposition(DCR *dcr, uint64_t raddr)
99 {
100    if (!is_open()) {
101       dev_errno = EBADF;
102       Mmsg0(errmsg, _("Bad call to reposition. Device not open\n"));
103       Emsg0(M_FATAL, 0, errmsg);
104       return false;
105    }
106
107    Dmsg1(100, "===== lseek to %llu\n", raddr);
108    if (lseek(dcr, (boffset_t)raddr, SEEK_SET) == (boffset_t)-1) {
109       berrno be;
110       dev_errno = errno;
111       Mmsg2(errmsg, _("lseek error on %s. ERR=%s.\n"),
112          print_name(), be.bstrerror());
113       return false;
114    }
115    file_addr = raddr;
116    return true;
117 }
118
119
120 /* Seek to specified place */
121 boffset_t DEVICE::lseek(DCR *dcr, boffset_t offset, int whence)
122 {
123 #if defined(HAVE_WIN32)
124   return ::_lseeki64(m_fd, (__int64)offset, whence);
125 #else
126   return ::lseek(m_fd, offset, whence);
127 #endif
128 }
129
130 /*
131  * Open a file device. For Aligned type we open both Volumes
132  */
133 bool file_dev::open_device(DCR *dcr, int omode)
134 {
135    POOL_MEM archive_name(PM_FNAME);
136    struct stat sp;
137
138    Enter(dbglvl);
139    if (DEVICE::open_device(dcr, omode)) {
140       Leave(dbglvl);
141       return true;
142    }
143    omode = openmode;
144
145    get_autochanger_loaded_slot(dcr);
146
147    /*
148     * Handle opening of File Autochanger
149     */
150
151    pm_strcpy(archive_name, dev_name);
152    /*
153     * If this is a virtual autochanger (i.e. changer_res != NULL)
154     *  we simply use the device name, assuming it has been
155     *  appropriately setup by the "autochanger".
156     */
157    if (!device->changer_res || device->changer_command[0] == 0 ||
158         strcmp(device->changer_command, "/dev/null") == 0) {
159       if (VolCatInfo.VolCatName[0] == 0) {
160          Mmsg(errmsg, _("Could not open file device %s. No Volume name given.\n"),
161             print_name());
162          if (dcr->jcr) {
163             pm_strcpy(dcr->jcr->errmsg, errmsg);
164          }
165          clear_opened();
166          Leave(dbglvl);
167          return false;
168       }
169
170       /* If not /dev/null concatenate VolumeName */
171       if (!is_null()) {
172          if (!IsPathSeparator(archive_name.c_str()[strlen(archive_name.c_str())-1])) {
173             pm_strcat(archive_name, "/");
174          }
175          pm_strcat(archive_name, getVolCatName());
176       }
177    }
178
179    mount(1);                          /* do mount if required */
180
181    set_mode(omode);
182    /* If creating file, give 0640 permissions */
183    Dmsg3(100, "open disk: mode=%s open(%s, 0x%x, 0640)\n", mode_to_str(omode),
184          archive_name.c_str(), mode);
185    /* Use system open() */
186    if ((m_fd = ::open(archive_name.c_str(), mode|O_CLOEXEC, 0640)) < 0) {
187       berrno be;
188       dev_errno = errno;
189       Mmsg3(errmsg, _("Could not open(%s,%s,0640): ERR=%s\n"),
190             archive_name.c_str(), mode_to_str(omode), be.bstrerror());
191       Dmsg1(40, "open failed: %s", errmsg);
192    } else {
193       /* Open is OK, now let device get control */
194       Dmsg2(40, "Did open(%s,%s,0640)\n", archive_name.c_str(), mode_to_str(omode));
195       device_specific_open(dcr);
196    }
197    if (m_fd >= 0) {
198       dev_errno = 0;
199       file = 0;
200       file_addr = 0;
201
202       /* Refresh the underline device id */
203       if (fstat(m_fd, &sp) == 0) {
204          devno = sp.st_dev;
205       }
206    } else {
207       if (dcr->jcr) {
208          pm_strcpy(dcr->jcr->errmsg, errmsg);
209       }
210    }
211    Dmsg1(100, "open dev: disk fd=%d opened, aligned=%d\n", m_fd);
212
213    state |= preserve;                 /* reset any important state info */
214    Leave(dbglvl);
215    return m_fd >= 0;
216 }
217
218 /*
219  * Truncate a volume.  If this is aligned disk, we
220  *    truncate both volumes.
221  */
222 bool DEVICE::truncate(DCR *dcr)
223 {
224    struct stat st;
225    DEVICE *dev = this;
226
227    Dmsg1(100, "truncate %s\n", print_name());
228    switch (dev_type) {
229    case B_VTL_DEV:
230    case B_VTAPE_DEV:
231    case B_TAPE_DEV:
232       /* maybe we should rewind and write and eof ???? */
233       return true;                    /* we don't really truncate tapes */
234    default:
235       break;
236    }
237
238    /* Do truncate for 1 or 2 devices */
239    Dmsg2(100, "Truncate adata=%d fd=%d\n", dev->adata, dev->m_fd);
240    if (ftruncate(dev->m_fd, 0) != 0) {
241       berrno be;
242       Mmsg2(errmsg, _("Unable to truncate device %s. ERR=%s\n"),
243             print_name(), be.bstrerror());
244       return false;
245    }
246
247    /*
248     * Check for a successful ftruncate() and issue a work-around for devices
249     * (mostly cheap NAS) that don't support truncation.
250     * Workaround supplied by Martin Schmid as a solution to bug #1011.
251     * 1. close file
252     * 2. delete file
253     * 3. open new file with same mode
254     * 4. change ownership to original
255     */
256
257    if (fstat(dev->m_fd, &st) != 0) {
258       berrno be;
259       Mmsg2(errmsg, _("Unable to stat device %s. ERR=%s\n"),
260             print_name(), be.bstrerror());
261       return false;
262    }
263
264    if (st.st_size != 0) {             /* ftruncate() didn't work */
265       POOL_MEM archive_name(PM_FNAME);
266
267       pm_strcpy(archive_name, dev_name);
268       if (!IsPathSeparator(archive_name.c_str()[strlen(archive_name.c_str())-1])) {
269          pm_strcat(archive_name, "/");
270       }
271       pm_strcat(archive_name, dcr->VolumeName);
272       if (dev->is_adata()) {
273          pm_strcat(archive_name, ADATA_EXTENSION);
274       }
275
276       Mmsg2(errmsg, _("Device %s doesn't support ftruncate(). Recreating file %s.\n"),
277             print_name(), archive_name.c_str());
278
279       /* Close file and blow it away */
280       ::close(dev->m_fd);
281       ::unlink(archive_name.c_str());
282
283       /* Recreate the file -- of course, empty */
284       dev->set_mode(CREATE_READ_WRITE);
285       if ((dev->m_fd = ::open(archive_name.c_str(), mode|O_CLOEXEC, st.st_mode)) < 0) {
286          berrno be;
287          dev_errno = errno;
288          Mmsg2(errmsg, _("Could not reopen: %s, ERR=%s\n"), archive_name.c_str(),
289                be.bstrerror());
290          Dmsg1(40, "reopen failed: %s", errmsg);
291          Emsg0(M_FATAL, 0, errmsg);
292          return false;
293       }
294
295       /* Reset proper owner */
296       chown(archive_name.c_str(), st.st_uid, st.st_gid);
297    }
298    return true;
299 }
300
301
302 /*
303  * (Un)mount the device
304  */
305 bool DEVICE::mount_file(int mount, int dotimeout)
306 {
307    POOL_MEM ocmd(PM_FNAME);
308    POOLMEM *results;
309    DIR* dp;
310    char *icmd;
311    struct dirent *entry, *result;
312    int status, tries, name_max, count;
313    berrno be;
314
315    Dsm_check(200);
316    if (mount) {
317       icmd = device->mount_command;
318    } else {
319       icmd = device->unmount_command;
320    }
321
322    clear_freespace_ok();
323    edit_mount_codes(ocmd, icmd);
324
325    Dmsg2(100, "mount_file: cmd=%s mounted=%d\n", ocmd.c_str(), !!is_mounted());
326
327    if (dotimeout) {
328       /* Try at most 10 times to (un)mount the device. This should perhaps be configurable. */
329       tries = 10;
330    } else {
331       tries = 1;
332    }
333    results = get_memory(4000);
334
335    /* If busy retry each second */
336    Dmsg1(100, "mount_file run_prog=%s\n", ocmd.c_str());
337    while ((status = run_program_full_output(ocmd.c_str(), max_open_wait/2, results)) != 0) {
338       /* Doesn't work with internationalization (This is not a problem) */
339       if (mount && fnmatch("*is already mounted on*", results, 0) == 0) {
340          break;
341       }
342       if (!mount && fnmatch("* not mounted*", results, 0) == 0) {
343          break;
344       }
345       if (tries-- > 0) {
346          /* Sometimes the device cannot be mounted because it is already mounted.
347           * Try to unmount it, then remount it */
348          if (mount) {
349             Dmsg1(400, "Trying to unmount the device %s...\n", print_name());
350             mount_file(0, 0);
351          }
352          bmicrosleep(1, 0);
353          continue;
354       }
355       Dmsg5(100, "Device %s cannot be %smounted. stat=%d result=%s ERR=%s\n", print_name(),
356            (mount ? "" : "un"), status, results, be.bstrerror(status));
357       Mmsg(errmsg, _("Device %s cannot be %smounted. ERR=%s\n"),
358            print_name(), (mount ? "" : "un"), be.bstrerror(status));
359
360       /*
361        * Now, just to be sure it is not mounted, try to read the filesystem.
362        */
363       name_max = pathconf(".", _PC_NAME_MAX);
364       if (name_max < 1024) {
365          name_max = 1024;
366       }
367
368       if (!(dp = opendir(device->mount_point))) {
369          berrno be;
370          dev_errno = errno;
371          Dmsg3(100, "mount_file: failed to open dir %s (dev=%s), ERR=%s\n",
372                device->mount_point, print_name(), be.bstrerror());
373          goto get_out;
374       }
375
376       entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
377       count = 0;
378       while (1) {
379          if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
380             dev_errno = EIO;
381             Dmsg2(129, "mount_file: failed to find suitable file in dir %s (dev=%s)\n",
382                   device->mount_point, print_name());
383             break;
384          }
385          if ((strcmp(result->d_name, ".")) && (strcmp(result->d_name, "..")) && (strcmp(result->d_name, ".keep"))) {
386             count++; /* result->d_name != ., .. or .keep (Gentoo-specific) */
387             break;
388          } else {
389             Dmsg2(129, "mount_file: ignoring %s in %s\n", result->d_name, device->mount_point);
390          }
391       }
392       free(entry);
393       closedir(dp);
394
395       Dmsg1(100, "mount_file: got %d files in the mount point (not counting ., .. and .keep)\n", count);
396
397       if (count > 0) {
398          /* If we got more than ., .. and .keep */
399          /*   there must be something mounted */
400          if (mount) {
401             Dmsg1(100, "Did Mount by count=%d\n", count);
402             break;
403          } else {
404             /* An unmount request. We failed to unmount - report an error */
405             set_mounted(true);
406             free_pool_memory(results);
407             Dmsg0(200, "== error mount=1 wanted unmount\n");
408             return false;
409          }
410       }
411 get_out:
412       set_mounted(false);
413       free_pool_memory(results);
414       Dmsg0(200, "============ mount=0\n");
415       Dsm_check(200);
416       return false;
417    }
418
419    set_mounted(mount);              /* set/clear mounted flag */
420    free_pool_memory(results);
421    /* Do not check free space when unmounting */
422    Dmsg1(200, "============ mount=%d\n", mount);
423    return true;
424 }
425
426 /*
427  * Check if the current position on the volume corresponds to
428  *  what is in the catalog.
429  *
430  */
431 bool file_dev::is_eod_valid(DCR *dcr)
432 {
433    JCR *jcr = dcr->jcr;
434
435    if (has_cap(CAP_LSEEK)) {
436       char ed1[50], ed2[50];
437       boffset_t ameta_size, adata_size, size;
438
439       ameta_size = lseek(dcr, (boffset_t)0, SEEK_END);
440       adata_size = get_adata_size(dcr);
441       size = ameta_size + adata_size;
442       if (VolCatInfo.VolCatAmetaBytes == (uint64_t)ameta_size &&
443           VolCatInfo.VolCatAdataBytes == (uint64_t)adata_size) {
444          if (is_aligned()) {
445             Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volumes \"%s\""
446                  " ameta size=%s adata size=%s\n"), dcr->VolumeName,
447                  edit_uint64_with_commas(VolCatInfo.VolCatAmetaBytes, ed1),
448                  edit_uint64_with_commas(VolCatInfo.VolCatAdataBytes, ed2));
449          } else {
450             Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\""
451                  " size=%s\n"), dcr->VolumeName,
452                  edit_uint64_with_commas(VolCatInfo.VolCatAmetaBytes, ed1));
453          }
454       } else if ((uint64_t)ameta_size >= VolCatInfo.VolCatAmetaBytes &&
455                  (uint64_t)adata_size >= VolCatInfo.VolCatAdataBytes) {
456          if ((uint64_t)ameta_size != VolCatInfo.VolCatAmetaBytes) {
457             Jmsg(jcr, M_WARNING, 0, _("For Volume \"%s\":\n"
458                "   The sizes do not match! Metadata Volume=%s Catalog=%s\n"
459                "   Correcting Catalog\n"),
460                dcr->VolumeName, edit_uint64_with_commas(ameta_size, ed1),
461                edit_uint64_with_commas(VolCatInfo.VolCatAmetaBytes, ed2));
462          }
463          if ((uint64_t)adata_size != VolCatInfo.VolCatAdataBytes) {
464             Jmsg(jcr, M_WARNING, 0, _("For aligned Volume \"%s\":\n"
465                "   Aligned sizes do not match! Aligned Volume=%s Catalog=%s\n"
466                "   Correcting Catalog\n"),
467                dcr->VolumeName, edit_uint64_with_commas(adata_size, ed1),
468                edit_uint64_with_commas(VolCatInfo.VolCatAdataBytes, ed2));
469          }
470          VolCatInfo.VolCatAmetaBytes = ameta_size;
471          VolCatInfo.VolCatAdataBytes = adata_size;
472          VolCatInfo.VolCatBytes = size;
473          VolCatInfo.VolCatFiles = (uint32_t)(size >> 32);
474          if (!dir_update_volume_info(dcr, false, true)) {
475             Jmsg(jcr, M_WARNING, 0, _("Error updating Catalog\n"));
476             dcr->mark_volume_in_error();
477             return false;
478          }
479       } else {
480          Mmsg(jcr->errmsg, _("Bacula cannot write on disk Volume \"%s\" because: "
481               "The sizes do not match! Volume=%s Catalog=%s\n"),
482               dcr->VolumeName,
483               edit_uint64_with_commas(size, ed1),
484               edit_uint64_with_commas(VolCatInfo.VolCatBytes, ed2));
485          Jmsg(jcr, M_ERROR, 0, jcr->errmsg);
486          Dmsg0(100, jcr->errmsg);
487          dcr->mark_volume_in_error();
488          return false;
489       }
490    }
491    return true;
492 }
493
494
495 /*
496  * Position device to end of medium (end of data)
497  *  Returns: true  on succes
498  *           false on error
499  */
500 bool file_dev::eod(DCR *dcr)
501 {
502    boffset_t pos;
503
504    Enter(100);
505    if (m_fd < 0) {
506       dev_errno = EBADF;
507       Mmsg1(errmsg, _("Bad call to eod. Device %s not open\n"), print_name());
508       Dmsg1(100, "%s", errmsg);
509       return false;
510    }
511
512    if (at_eot()) {
513       Leave(100);
514       return true;
515    }
516    clear_eof();         /* remove EOF flag */
517    block_num = file = 0;
518    file_size = 0;
519    file_addr = 0;
520    if (is_fifo()) {
521       Leave(100);
522       return true;
523    }
524    pos = lseek(dcr, (boffset_t)0, SEEK_END);
525    Dmsg1(200, "====== Seek to %lld\n", pos);
526    if (pos >= 0) {
527       update_pos(dcr);
528       set_eot();
529       Leave(100);
530       return true;
531    }
532    dev_errno = errno;
533    berrno be;
534    Mmsg2(errmsg, _("lseek error on %s. ERR=%s.\n"),
535           print_name(), be.bstrerror());
536    Dmsg1(100, "%s", errmsg);
537    Leave(100);
538    return false;
539 }
540
541 const char *file_dev::print_type()
542 {
543    return "File";
544 }