]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/file_dev.c
Apply patches from bugs #2325 and #2326 to fix FIFO bugs
[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\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    Dmsg2(100, "Truncate adata=%d fd=%d\n", dev->adata, dev->m_fd);
239    if (ftruncate(dev->m_fd, 0) != 0) {
240       berrno be;
241       Mmsg2(errmsg, _("Unable to truncate device %s. ERR=%s\n"),
242             print_name(), be.bstrerror());
243       return false;
244    }
245
246    /*
247     * Check for a successful ftruncate() and issue a work-around for devices
248     * (mostly cheap NAS) that don't support truncation.
249     * Workaround supplied by Martin Schmid as a solution to bug #1011.
250     * 1. close file
251     * 2. delete file
252     * 3. open new file with same mode
253     * 4. change ownership to original
254     */
255
256    if (fstat(dev->m_fd, &st) != 0) {
257       berrno be;
258       Mmsg2(errmsg, _("Unable to stat device %s. ERR=%s\n"),
259             print_name(), be.bstrerror());
260       return false;
261    }
262
263    if (st.st_size != 0) {             /* ftruncate() didn't work */
264       POOL_MEM archive_name(PM_FNAME);
265
266       pm_strcpy(archive_name, dev_name);
267       if (!IsPathSeparator(archive_name.c_str()[strlen(archive_name.c_str())-1])) {
268          pm_strcat(archive_name, "/");
269       }
270       pm_strcat(archive_name, dcr->VolumeName);
271       if (dev->is_adata()) {
272          pm_strcat(archive_name, ADATA_EXTENSION);
273       }
274
275       Mmsg2(errmsg, _("Device %s doesn't support ftruncate(). Recreating file %s.\n"),
276             print_name(), archive_name.c_str());
277
278       /* Close file and blow it away */
279       ::close(dev->m_fd);
280       ::unlink(archive_name.c_str());
281
282       /* Recreate the file -- of course, empty */
283       dev->set_mode(CREATE_READ_WRITE);
284       if ((dev->m_fd = ::open(archive_name.c_str(), mode|O_CLOEXEC, st.st_mode)) < 0) {
285          berrno be;
286          dev_errno = errno;
287          Mmsg2(errmsg, _("Could not reopen: %s, ERR=%s\n"), archive_name.c_str(),
288                be.bstrerror());
289          Dmsg1(40, "reopen failed: %s", errmsg);
290          Emsg0(M_FATAL, 0, errmsg);
291          return false;
292       }
293
294       /* Reset proper owner */
295       chown(archive_name.c_str(), st.st_uid, st.st_gid);
296    }
297    return true;
298 }
299
300
301 /*
302  * (Un)mount the device
303  */
304 bool DEVICE::mount_file(int mount, int dotimeout)
305 {
306    POOL_MEM ocmd(PM_FNAME);
307    POOLMEM *results;
308    DIR* dp;
309    char *icmd;
310    struct dirent *entry, *result;
311    int status, tries, name_max, count;
312    berrno be;
313
314    Dsm_check(200);
315    if (mount) {
316       icmd = device->mount_command;
317    } else {
318       icmd = device->unmount_command;
319    }
320
321    clear_freespace_ok();
322    edit_mount_codes(ocmd, icmd);
323
324    Dmsg2(100, "mount_file: cmd=%s mounted=%d\n", ocmd.c_str(), !!is_mounted());
325
326    if (dotimeout) {
327       /* Try at most 10 times to (un)mount the device. This should perhaps be configurable. */
328       tries = 10;
329    } else {
330       tries = 1;
331    }
332    results = get_memory(4000);
333
334    /* If busy retry each second */
335    Dmsg1(100, "mount_file run_prog=%s\n", ocmd.c_str());
336    while ((status = run_program_full_output(ocmd.c_str(), max_open_wait/2, results)) != 0) {
337       /* Doesn't work with internationalization (This is not a problem) */
338       if (mount && fnmatch("*is already mounted on*", results, 0) == 0) {
339          break;
340       }
341       if (!mount && fnmatch("* not mounted*", results, 0) == 0) {
342          break;
343       }
344       if (tries-- > 0) {
345          /* Sometimes the device cannot be mounted because it is already mounted.
346           * Try to unmount it, then remount it */
347          if (mount) {
348             Dmsg1(400, "Trying to unmount the device %s...\n", print_name());
349             mount_file(0, 0);
350          }
351          bmicrosleep(1, 0);
352          continue;
353       }
354       Dmsg5(100, "Device %s cannot be %smounted. stat=%d result=%s ERR=%s\n", print_name(),
355            (mount ? "" : "un"), status, results, be.bstrerror(status));
356       Mmsg(errmsg, _("Device %s cannot be %smounted. ERR=%s\n"),
357            print_name(), (mount ? "" : "un"), be.bstrerror(status));
358
359       /*
360        * Now, just to be sure it is not mounted, try to read the filesystem.
361        */
362       name_max = pathconf(".", _PC_NAME_MAX);
363       if (name_max < 1024) {
364          name_max = 1024;
365       }
366
367       if (!(dp = opendir(device->mount_point))) {
368          berrno be;
369          dev_errno = errno;
370          Dmsg3(100, "mount_file: failed to open dir %s (dev=%s), ERR=%s\n",
371                device->mount_point, print_name(), be.bstrerror());
372          goto get_out;
373       }
374
375       entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 1000);
376       count = 0;
377       while (1) {
378          if ((readdir_r(dp, entry, &result) != 0) || (result == NULL)) {
379             dev_errno = EIO;
380             Dmsg2(129, "mount_file: failed to find suitable file in dir %s (dev=%s)\n",
381                   device->mount_point, print_name());
382             break;
383          }
384          if ((strcmp(result->d_name, ".")) && (strcmp(result->d_name, "..")) && (strcmp(result->d_name, ".keep"))) {
385             count++; /* result->d_name != ., .. or .keep (Gentoo-specific) */
386             break;
387          } else {
388             Dmsg2(129, "mount_file: ignoring %s in %s\n", result->d_name, device->mount_point);
389          }
390       }
391       free(entry);
392       closedir(dp);
393
394       Dmsg1(100, "mount_file: got %d files in the mount point (not counting ., .. and .keep)\n", count);
395
396       if (count > 0) {
397          /* If we got more than ., .. and .keep */
398          /*   there must be something mounted */
399          if (mount) {
400             Dmsg1(100, "Did Mount by count=%d\n", count);
401             break;
402          } else {
403             /* An unmount request. We failed to unmount - report an error */
404             set_mounted(true);
405             free_pool_memory(results);
406             Dmsg0(200, "== error mount=1 wanted unmount\n");
407             return false;
408          }
409       }
410 get_out:
411       set_mounted(false);
412       free_pool_memory(results);
413       Dmsg0(200, "============ mount=0\n");
414       Dsm_check(200);
415       return false;
416    }
417
418    set_mounted(mount);              /* set/clear mounted flag */
419    free_pool_memory(results);
420    /* Do not check free space when unmounting */
421    Dmsg1(200, "============ mount=%d\n", mount);
422    return true;
423 }
424
425 /*
426  * Check if the current position on the volume corresponds to
427  *  what is in the catalog.
428  *
429  */
430 bool file_dev::is_eod_valid(DCR *dcr)
431 {
432    JCR *jcr = dcr->jcr;
433
434    if (has_cap(CAP_LSEEK)) {
435       char ed1[50], ed2[50];
436       boffset_t ameta_size, adata_size, size;
437
438       ameta_size = lseek(dcr, (boffset_t)0, SEEK_END);
439       adata_size = get_adata_size(dcr);
440       size = ameta_size + adata_size;
441       if (VolCatInfo.VolCatAmetaBytes == (uint64_t)ameta_size &&
442           VolCatInfo.VolCatAdataBytes == (uint64_t)adata_size) {
443          if (is_aligned()) {
444             Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volumes \"%s\""
445                  " ameta size=%s adata size=%s\n"), dcr->VolumeName,
446                  edit_uint64_with_commas(VolCatInfo.VolCatAmetaBytes, ed1),
447                  edit_uint64_with_commas(VolCatInfo.VolCatAdataBytes, ed2));
448          } else {
449             Jmsg(jcr, M_INFO, 0, _("Ready to append to end of Volume \"%s\""
450                  " size=%s\n"), dcr->VolumeName,
451                  edit_uint64_with_commas(VolCatInfo.VolCatAmetaBytes, ed1));
452          }
453       } else if ((uint64_t)ameta_size >= VolCatInfo.VolCatAmetaBytes &&
454                  (uint64_t)adata_size >= VolCatInfo.VolCatAdataBytes) {
455          if ((uint64_t)ameta_size != VolCatInfo.VolCatAmetaBytes) {
456             Jmsg(jcr, M_WARNING, 0, _("For Volume \"%s\":\n"
457                "   The sizes do not match! Metadata Volume=%s Catalog=%s\n"
458                "   Correcting Catalog\n"),
459                dcr->VolumeName, edit_uint64_with_commas(ameta_size, ed1),
460                edit_uint64_with_commas(VolCatInfo.VolCatAmetaBytes, ed2));
461          }
462          if ((uint64_t)adata_size != VolCatInfo.VolCatAdataBytes) {
463             Jmsg(jcr, M_WARNING, 0, _("For aligned Volume \"%s\":\n"
464                "   Aligned sizes do not match! Aligned Volume=%s Catalog=%s\n"
465                "   Correcting Catalog\n"),
466                dcr->VolumeName, edit_uint64_with_commas(adata_size, ed1),
467                edit_uint64_with_commas(VolCatInfo.VolCatAdataBytes, ed2));
468          }
469          VolCatInfo.VolCatAmetaBytes = ameta_size;
470          VolCatInfo.VolCatAdataBytes = adata_size;
471          VolCatInfo.VolCatBytes = size;
472          VolCatInfo.VolCatFiles = (uint32_t)(size >> 32);
473          if (!dir_update_volume_info(dcr, false, true)) {
474             Jmsg(jcr, M_WARNING, 0, _("Error updating Catalog\n"));
475             dcr->mark_volume_in_error();
476             return false;
477          }
478       } else {
479          Mmsg(jcr->errmsg, _("Bacula cannot write on disk Volume \"%s\" because: "
480               "The sizes do not match! Volume=%s Catalog=%s\n"),
481               dcr->VolumeName,
482               edit_uint64_with_commas(size, ed1),
483               edit_uint64_with_commas(VolCatInfo.VolCatBytes, ed2));
484          Jmsg(jcr, M_ERROR, 0, jcr->errmsg);
485          Dmsg0(100, jcr->errmsg);
486          dcr->mark_volume_in_error();
487          return false;
488       }
489    }
490    return true;
491 }
492
493
494 /*
495  * Position device to end of medium (end of data)
496  *  Returns: true  on succes
497  *           false on error
498  */
499 bool file_dev::eod(DCR *dcr)
500 {
501    boffset_t pos;
502
503    Enter(100);
504    if (m_fd < 0) {
505       dev_errno = EBADF;
506       Mmsg1(errmsg, _("Bad call to eod. Device %s not open\n"), print_name());
507       Dmsg1(100, "%s", errmsg);
508       return false;
509    }
510
511    if (at_eot()) {
512       Leave(100);
513       return true;
514    }
515    clear_eof();         /* remove EOF flag */
516    block_num = file = 0;
517    file_size = 0;
518    file_addr = 0;
519    if (is_fifo()) {
520       Leave(100);
521       return true;
522    }
523    pos = lseek(dcr, (boffset_t)0, SEEK_END);
524    Dmsg1(200, "====== Seek to %lld\n", pos);
525    if (pos >= 0) {
526       update_pos(dcr);
527       set_eot();
528       Leave(100);
529       return true;
530    }
531    dev_errno = errno;
532    berrno be;
533    Mmsg2(errmsg, _("lseek error on %s. ERR=%s.\n"),
534           print_name(), be.bstrerror());
535    Dmsg1(100, "%s", errmsg);
536    Leave(100);
537    return false;
538 }
539
540 const char *file_dev::print_type()
541 {
542    return "File";
543 }