1 /*
2    BAREOS® - Backup Archiving REcovery Open Sourced
3 
4    Copyright (C) 2003-2010 Free Software Foundation Europe e.V.
5    Copyright (C) 2011-2012 Planets Communications B.V.
6    Copyright (C) 2013-2019 Bareos GmbH & Co. KG
7 
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12 
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    Affero General Public License for more details.
17 
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22 */
23 /*
24  * Kern Sibbald, April MMIII
25  */
26 /**
27  * @file
28  * Bareos low level File I/O routines.  This routine simulates
29  * open(), read(), write(), and close(), but using native routines.
30  * I.e. on Windows, we use Windows APIs.
31  */
32 
33 #include "include/bareos.h"
34 #include "find.h"
35 #include "lib/berrno.h"
36 
37 const int debuglevel = 200;
38 
39 int (*plugin_bopen)(BareosWinFilePacket* bfd,
40                     const char* fname,
41                     int flags,
42                     mode_t mode) = NULL;
43 int (*plugin_bclose)(BareosWinFilePacket* bfd) = NULL;
44 ssize_t (*plugin_bread)(BareosWinFilePacket* bfd,
45                         void* buf,
46                         size_t count) = NULL;
47 ssize_t (*plugin_bwrite)(BareosWinFilePacket* bfd,
48                          void* buf,
49                          size_t count) = NULL;
50 boffset_t (*plugin_blseek)(BareosWinFilePacket* bfd,
51                            boffset_t offset,
52                            int whence) = NULL;
53 
54 #ifdef HAVE_DARWIN_OS
55 #include <sys/paths.h>
56 #endif
57 
58 #if !defined(HAVE_FDATASYNC)
59 #define fdatasync(fd)
60 #endif
61 
62 #ifdef HAVE_WIN32
PauseMsg(const char * file,const char * func,int line,const char * msg)63 void PauseMsg(const char* file, const char* func, int line, const char* msg)
64 {
65   char buf[1000];
66   if (msg) {
67     Bsnprintf(buf, sizeof(buf), "%s:%s:%d %s", file, func, line, msg);
68   } else {
69     Bsnprintf(buf, sizeof(buf), "%s:%s:%d", file, func, line);
70   }
71   MessageBox(NULL, buf, "Pause", MB_OK);
72 }
73 #endif
74 
75 /* ===============================================================
76  *
77  *            U N I X   AND   W I N D O W S
78  *
79  * ===============================================================
80  */
81 
is_win32_stream(int stream)82 bool is_win32_stream(int stream)
83 {
84   switch (stream) {
85     case STREAM_WIN32_DATA:
86     case STREAM_WIN32_GZIP_DATA:
87     case STREAM_WIN32_COMPRESSED_DATA:
88     case STREAM_ENCRYPTED_WIN32_DATA:
89     case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
90     case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
91       return true;
92   }
93   return false;
94 }
95 
stream_to_ascii(int stream)96 const char* stream_to_ascii(int stream)
97 {
98   static char buf[20];
99 
100   switch (stream & STREAMMASK_TYPE) {
101     case STREAM_UNIX_ATTRIBUTES:
102       return _("Unix attributes");
103     case STREAM_FILE_DATA:
104       return _("File data");
105     case STREAM_MD5_DIGEST:
106       return _("MD5 digest");
107     case STREAM_GZIP_DATA:
108       return _("GZIP data");
109     case STREAM_COMPRESSED_DATA:
110       return _("Compressed data");
111     case STREAM_UNIX_ATTRIBUTES_EX:
112       return _("Extended attributes");
113     case STREAM_SPARSE_DATA:
114       return _("Sparse data");
115     case STREAM_SPARSE_GZIP_DATA:
116       return _("GZIP sparse data");
117     case STREAM_SPARSE_COMPRESSED_DATA:
118       return _("Compressed sparse data");
119     case STREAM_PROGRAM_NAMES:
120       return _("Program names");
121     case STREAM_PROGRAM_DATA:
122       return _("Program data");
123     case STREAM_SHA1_DIGEST:
124       return _("SHA1 digest");
125     case STREAM_WIN32_DATA:
126       return _("Win32 data");
127     case STREAM_WIN32_GZIP_DATA:
128       return _("Win32 GZIP data");
129     case STREAM_WIN32_COMPRESSED_DATA:
130       return _("Win32 compressed data");
131     case STREAM_MACOS_FORK_DATA:
132       return _("MacOS Fork data");
133     case STREAM_HFSPLUS_ATTRIBUTES:
134       return _("HFS+ attribs");
135     case STREAM_UNIX_ACCESS_ACL:
136       return _("Standard Unix ACL attribs");
137     case STREAM_UNIX_DEFAULT_ACL:
138       return _("Default Unix ACL attribs");
139     case STREAM_SHA256_DIGEST:
140       return _("SHA256 digest");
141     case STREAM_SHA512_DIGEST:
142       return _("SHA512 digest");
143     case STREAM_SIGNED_DIGEST:
144       return _("Signed digest");
145     case STREAM_ENCRYPTED_FILE_DATA:
146       return _("Encrypted File data");
147     case STREAM_ENCRYPTED_WIN32_DATA:
148       return _("Encrypted Win32 data");
149     case STREAM_ENCRYPTED_SESSION_DATA:
150       return _("Encrypted session data");
151     case STREAM_ENCRYPTED_FILE_GZIP_DATA:
152       return _("Encrypted GZIP data");
153     case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
154       return _("Encrypted compressed data");
155     case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
156       return _("Encrypted Win32 GZIP data");
157     case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
158       return _("Encrypted Win32 Compressed data");
159     case STREAM_ENCRYPTED_MACOS_FORK_DATA:
160       return _("Encrypted MacOS fork data");
161     case STREAM_ACL_AIX_TEXT:
162       return _("AIX Specific ACL attribs");
163     case STREAM_ACL_DARWIN_ACCESS_ACL:
164       return _("Darwin Specific ACL attribs");
165     case STREAM_ACL_FREEBSD_DEFAULT_ACL:
166       return _("FreeBSD Specific Default ACL attribs");
167     case STREAM_ACL_FREEBSD_ACCESS_ACL:
168       return _("FreeBSD Specific Access ACL attribs");
169     case STREAM_ACL_HPUX_ACL_ENTRY:
170       return _("HPUX Specific ACL attribs");
171     case STREAM_ACL_IRIX_DEFAULT_ACL:
172       return _("Irix Specific Default ACL attribs");
173     case STREAM_ACL_IRIX_ACCESS_ACL:
174       return _("Irix Specific Access ACL attribs");
175     case STREAM_ACL_LINUX_DEFAULT_ACL:
176       return _("Linux Specific Default ACL attribs");
177     case STREAM_ACL_LINUX_ACCESS_ACL:
178       return _("Linux Specific Access ACL attribs");
179     case STREAM_ACL_TRU64_DEFAULT_ACL:
180       return _("TRU64 Specific Default ACL attribs");
181     case STREAM_ACL_TRU64_ACCESS_ACL:
182       return _("TRU64 Specific Access ACL attribs");
183     case STREAM_ACL_SOLARIS_ACLENT:
184       return _("Solaris Specific POSIX ACL attribs");
185     case STREAM_ACL_SOLARIS_ACE:
186       return _("Solaris Specific NFSv4/ZFS ACL attribs");
187     case STREAM_ACL_AFS_TEXT:
188       return _("AFS Specific ACL attribs");
189     case STREAM_ACL_AIX_AIXC:
190       return _("AIX Specific POSIX ACL attribs");
191     case STREAM_ACL_AIX_NFS4:
192       return _("AIX Specific NFSv4 ACL attribs");
193     case STREAM_ACL_FREEBSD_NFS4_ACL:
194       return _("FreeBSD Specific NFSv4/ZFS ACL attribs");
195     case STREAM_ACL_HURD_DEFAULT_ACL:
196       return _("GNU Hurd Specific Default ACL attribs");
197     case STREAM_ACL_HURD_ACCESS_ACL:
198       return _("GNU Hurd Specific Access ACL attribs");
199     case STREAM_XATTR_HURD:
200       return _("GNU Hurd Specific Extended attribs");
201     case STREAM_XATTR_IRIX:
202       return _("IRIX Specific Extended attribs");
203     case STREAM_XATTR_TRU64:
204       return _("TRU64 Specific Extended attribs");
205     case STREAM_XATTR_AIX:
206       return _("AIX Specific Extended attribs");
207     case STREAM_XATTR_OPENBSD:
208       return _("OpenBSD Specific Extended attribs");
209     case STREAM_XATTR_SOLARIS_SYS:
210       return _(
211           "Solaris Specific Extensible attribs or System Extended attribs");
212     case STREAM_XATTR_SOLARIS:
213       return _("Solaris Specific Extended attribs");
214     case STREAM_XATTR_DARWIN:
215       return _("Darwin Specific Extended attribs");
216     case STREAM_XATTR_FREEBSD:
217       return _("FreeBSD Specific Extended attribs");
218     case STREAM_XATTR_LINUX:
219       return _("Linux Specific Extended attribs");
220     case STREAM_XATTR_NETBSD:
221       return _("NetBSD Specific Extended attribs");
222     default:
223       sprintf(buf, "%d", stream);
224       return (const char*)buf;
225   }
226 }
227 
228 /**
229  *  Convert a 64 bit little endian to a big endian
230  */
int64_LE2BE(int64_t * pBE,const int64_t v)231 static inline void int64_LE2BE(int64_t* pBE, const int64_t v)
232 {
233   /* convert little endian to big endian */
234   if (htonl(1) != 1L) { /* no work if on little endian machine */
235     memcpy(pBE, &v, sizeof(int64_t));
236   } else {
237     int i;
238     uint8_t rv[sizeof(int64_t)];
239     uint8_t* pv = (uint8_t*)&v;
240 
241     for (i = 0; i < 8; i++) { rv[i] = pv[7 - i]; }
242     memcpy(pBE, &rv, sizeof(int64_t));
243   }
244 }
245 
246 /**
247  *  Convert a 32 bit little endian to a big endian
248  */
int32_LE2BE(int32_t * pBE,const int32_t v)249 static inline void int32_LE2BE(int32_t* pBE, const int32_t v)
250 {
251   /* convert little endian to big endian */
252   if (htonl(1) != 1L) { /* no work if on little endian machine */
253     memcpy(pBE, &v, sizeof(int32_t));
254   } else {
255     int i;
256     uint8_t rv[sizeof(int32_t)];
257     uint8_t* pv = (uint8_t*)&v;
258 
259     for (i = 0; i < 4; i++) { rv[i] = pv[3 - i]; }
260     memcpy(pBE, &rv, sizeof(int32_t));
261   }
262 }
263 
264 /**
265  *  Read a BackupRead block and pull out the file data
266  */
processWin32BackupAPIBlock(BareosWinFilePacket * bfd,void * pBuffer,ssize_t dwSize)267 bool processWin32BackupAPIBlock(BareosWinFilePacket* bfd,
268                                 void* pBuffer,
269                                 ssize_t dwSize)
270 {
271   /* pByte contains the buffer
272      dwSize the len to be processed.  function assumes to be
273      called in successive incremental order over the complete
274      BackupRead stream beginning at pos 0 and ending at the end.
275    */
276 
277   PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT* pContext = &(bfd->win32DecompContext);
278   bool bContinue = false;
279   int64_t dwDataOffset = 0;
280   int64_t dwDataLen;
281 
282   /* Win32 Stream Header size without name of stream.
283    * = sizeof (WIN32_STREAM_ID)- sizeof(wchar_t *);
284    */
285   int32_t dwSizeHeader = 20;
286 
287   do {
288     if (pContext->liNextHeader >= dwSize) {
289       dwDataLen = dwSize - dwDataOffset;
290       bContinue = false; /* 1 iteration is enough */
291     } else {
292       dwDataLen = pContext->liNextHeader - dwDataOffset;
293       bContinue = true; /* multiple iterations may be necessary */
294     }
295 
296     /* flush */
297     /* copy block of real DATA */
298     if (pContext->bIsInData) {
299       if (bwrite(bfd, ((char*)pBuffer) + dwDataOffset, dwDataLen) !=
300           (ssize_t)dwDataLen)
301         return false;
302     }
303 
304     if (pContext->liNextHeader < dwSize) { /* is a header in this block ? */
305       int32_t dwOffsetTarget;
306       int32_t dwOffsetSource;
307 
308       if (pContext->liNextHeader < 0) {
309         /* start of header was before this block, so we
310          * continue with the part in the current block
311          */
312         dwOffsetTarget = -pContext->liNextHeader;
313         dwOffsetSource = 0;
314       } else {
315         /* start of header is inside of this block */
316         dwOffsetTarget = 0;
317         dwOffsetSource = pContext->liNextHeader;
318       }
319 
320       int32_t dwHeaderPartLen = dwSizeHeader - dwOffsetTarget;
321       bool bHeaderIsComplete;
322 
323       if (dwHeaderPartLen <= dwSize - dwOffsetSource) {
324         /* header (or rest of header) is completely available
325            in current block
326          */
327         bHeaderIsComplete = true;
328       } else {
329         /* header will continue in next block */
330         bHeaderIsComplete = false;
331         dwHeaderPartLen = dwSize - dwOffsetSource;
332       }
333 
334       /* copy the available portion of header to persistent copy */
335       memcpy(((char*)&pContext->header_stream) + dwOffsetTarget,
336              ((char*)pBuffer) + dwOffsetSource, dwHeaderPartLen);
337 
338       /* recalculate position of next header */
339       if (bHeaderIsComplete) {
340         /* convert stream name size (32 bit little endian) to machine type */
341         int32_t dwNameSize;
342         int32_LE2BE(&dwNameSize, pContext->header_stream.dwStreamNameSize);
343         dwDataOffset = dwNameSize + pContext->liNextHeader + dwSizeHeader;
344 
345         /* convert stream size (64 bit little endian) to machine type */
346         int64_LE2BE(&(pContext->liNextHeader), pContext->header_stream.Size);
347         pContext->liNextHeader += dwDataOffset;
348 
349         pContext->bIsInData =
350             pContext->header_stream.dwStreamId == WIN32_BACKUP_DATA;
351         if (dwDataOffset == dwSize) bContinue = false;
352       } else {
353         /* stop and continue with next block */
354         bContinue = false;
355         pContext->bIsInData = false;
356       }
357     }
358   } while (bContinue);
359 
360   /* set "NextHeader" relative to the beginning of the next block */
361   pContext->liNextHeader -= dwSize;
362 
363   return TRUE;
364 }
365 
366 /* ===============================================================
367  *
368  *            W I N D O W S
369  *
370  * ===============================================================
371  */
372 
373 #if defined(HAVE_WIN32)
374 
375 /* Imported Functions */
376 extern void unix_name_to_win32(POOLMEM*& win32_name, const char* name);
377 extern "C" HANDLE get_osfhandle(int fd);
378 
binit(BareosWinFilePacket * bfd)379 void binit(BareosWinFilePacket* bfd)
380 {
381   memset(bfd, 0, sizeof(BareosWinFilePacket));
382   bfd->fid = -1;
383   bfd->mode = BF_CLOSED;
384   bfd->use_backup_api = have_win32_api();
385   bfd->cmd_plugin = false;
386   bfd->pvContext = NULL;
387 }
388 
389 /**
390  * Enables using the Backup API (win32_data).
391  *   Returns 1 if function worked
392  *   Returns 0 if failed (i.e. do not have Backup API on this machine)
393  */
set_win32_backup(BareosWinFilePacket * bfd)394 bool set_win32_backup(BareosWinFilePacket* bfd)
395 {
396   /* We enable if possible here */
397   bfd->use_backup_api = have_win32_api();
398   return bfd->use_backup_api;
399 }
400 
SetPortableBackup(BareosWinFilePacket * bfd)401 bool SetPortableBackup(BareosWinFilePacket* bfd)
402 {
403   bfd->use_backup_api = false;
404   return true;
405 }
406 
SetCmdPlugin(BareosWinFilePacket * bfd,JobControlRecord * jcr)407 bool SetCmdPlugin(BareosWinFilePacket* bfd, JobControlRecord* jcr)
408 {
409   bfd->cmd_plugin = true;
410   bfd->jcr = jcr;
411   return true;
412 }
413 
414 /**
415  * Return 1 if we are NOT using Win32 BackupWrite()
416  * return 0 if are
417  */
IsPortableBackup(BareosWinFilePacket * bfd)418 bool IsPortableBackup(BareosWinFilePacket* bfd) { return !bfd->use_backup_api; }
419 
have_win32_api()420 bool have_win32_api() { return p_BackupRead && p_BackupWrite; }
421 
422 /**
423  * Return true  if we support the stream
424  *        false if we do not support the stream
425  *
426  *  This code is running under Win32, so we do not need #ifdef on MACOS ...
427  */
IsRestoreStreamSupported(int stream)428 bool IsRestoreStreamSupported(int stream)
429 {
430   switch (stream) {
431     /*
432      * Streams known not to be supported
433      */
434 #ifndef HAVE_LIBZ
435     case STREAM_GZIP_DATA:
436     case STREAM_SPARSE_GZIP_DATA:
437     case STREAM_WIN32_GZIP_DATA:
438 #endif
439     case STREAM_MACOS_FORK_DATA:
440     case STREAM_HFSPLUS_ATTRIBUTES:
441     case STREAM_ENCRYPTED_MACOS_FORK_DATA:
442       return false;
443 
444       /*
445        * Known streams
446        */
447 #ifdef HAVE_LIBZ
448     case STREAM_GZIP_DATA:
449     case STREAM_SPARSE_GZIP_DATA:
450     case STREAM_WIN32_GZIP_DATA:
451 #endif
452     case STREAM_COMPRESSED_DATA:
453     case STREAM_SPARSE_COMPRESSED_DATA:
454     case STREAM_WIN32_COMPRESSED_DATA:
455     case STREAM_WIN32_DATA:
456     case STREAM_UNIX_ATTRIBUTES:
457     case STREAM_FILE_DATA:
458     case STREAM_MD5_DIGEST:
459     case STREAM_UNIX_ATTRIBUTES_EX:
460     case STREAM_SPARSE_DATA:
461     case STREAM_PROGRAM_NAMES:
462     case STREAM_PROGRAM_DATA:
463     case STREAM_SHA1_DIGEST:
464 #ifdef HAVE_SHA2
465     case STREAM_SHA256_DIGEST:
466     case STREAM_SHA512_DIGEST:
467 #endif
468 #ifdef HAVE_CRYPTO
469     case STREAM_SIGNED_DIGEST:
470     case STREAM_ENCRYPTED_FILE_DATA:
471     case STREAM_ENCRYPTED_FILE_GZIP_DATA:
472     case STREAM_ENCRYPTED_WIN32_DATA:
473     case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
474     case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
475     case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
476 #endif      /* !HAVE_CRYPTO */
477     case 0: /* compatibility with old tapes */
478       return true;
479   }
480   return false;
481 }
482 
BgetHandle(BareosWinFilePacket * bfd)483 HANDLE BgetHandle(BareosWinFilePacket* bfd)
484 {
485   return (bfd->mode == BF_CLOSED) ? INVALID_HANDLE_VALUE : bfd->fh;
486 }
487 
488 /**
489  * Windows flags for the OpenEncryptedFileRaw functions.
490  */
491 #ifndef CREATE_FOR_EXPORT
492 #define CREATE_FOR_EXPORT 0
493 #endif
494 #ifndef CREATE_FOR_IMPORT
495 #define CREATE_FOR_IMPORT 1
496 #endif
497 #ifndef CREATE_FOR_DIR
498 #define CREATE_FOR_DIR 2
499 #endif
500 #ifndef OVERWRITE_HIDDEN
501 #define OVERWRITE_HIDDEN 4
502 #endif
503 
BopenEncrypted(BareosWinFilePacket * bfd,const char * fname,int flags,mode_t mode)504 static inline int BopenEncrypted(BareosWinFilePacket* bfd,
505                                  const char* fname,
506                                  int flags,
507                                  mode_t mode)
508 {
509   bool is_dir;
510   ULONG ulFlags = 0;
511   POOLMEM* win32_fname;
512   POOLMEM* win32_fname_wchar;
513 
514   if (!p_OpenEncryptedFileRawA && !p_OpenEncryptedFileRawW) {
515     Dmsg0(50,
516           "No p_OpenEncryptedFileRawA and no p_OpenEncryptedFileRawW!!!!!\n");
517     return 0;
518   }
519 
520   is_dir = S_ISDIR(mode);
521 
522   /*
523    * Convert to Windows path format
524    */
525   win32_fname = GetPoolMemory(PM_FNAME);
526   win32_fname_wchar = GetPoolMemory(PM_FNAME);
527 
528   unix_name_to_win32(win32_fname, (char*)fname);
529   if (p_OpenEncryptedFileRawW && p_MultiByteToWideChar) {
530     make_win32_path_UTF8_2_wchar(win32_fname_wchar, fname);
531   }
532 
533   /*
534    * See if we open the file for create or read-write.
535    */
536   if ((flags & O_CREAT) || (flags & O_WRONLY)) {
537     if (is_dir) {
538       ulFlags |= CREATE_FOR_IMPORT | OVERWRITE_HIDDEN | CREATE_FOR_DIR;
539     } else {
540       ulFlags |= CREATE_FOR_IMPORT | OVERWRITE_HIDDEN;
541     }
542     bfd->mode = BF_WRITE;
543   } else {
544     ulFlags = CREATE_FOR_EXPORT;
545     bfd->mode = BF_READ;
546   }
547 
548   if (p_OpenEncryptedFileRawW && p_MultiByteToWideChar) {
549     /*
550      * Unicode open.
551      */
552     Dmsg1(100, "OpenEncryptedFileRawW=%s\n", win32_fname);
553     if (p_OpenEncryptedFileRawW((LPCWSTR)win32_fname_wchar, ulFlags,
554                                 &(bfd->pvContext))) {
555       bfd->mode = BF_CLOSED;
556     }
557   } else {
558     /*
559      * ASCII open.
560      */
561     Dmsg1(100, "OpenEncryptedFileRawA=%s\n", win32_fname);
562     if (p_OpenEncryptedFileRawA(win32_fname_wchar, ulFlags,
563                                 &(bfd->pvContext))) {
564       bfd->mode = BF_CLOSED;
565     }
566   }
567 
568   FreePoolMemory(win32_fname_wchar);
569   FreePoolMemory(win32_fname);
570 
571   bfd->encrypted = true;
572 
573   return bfd->mode == BF_CLOSED ? -1 : 1;
574 }
575 
BopenNonencrypted(BareosWinFilePacket * bfd,const char * fname,int flags,mode_t mode)576 static inline int BopenNonencrypted(BareosWinFilePacket* bfd,
577                                     const char* fname,
578                                     int flags,
579                                     mode_t mode)
580 {
581   POOLMEM* win32_fname;
582   POOLMEM* win32_fname_wchar;
583   DWORD dwaccess, dwflags, dwshare;
584 
585   /*
586    * Convert to Windows path format
587    */
588   win32_fname = GetPoolMemory(PM_FNAME);
589   win32_fname_wchar = GetPoolMemory(PM_FNAME);
590 
591   unix_name_to_win32(win32_fname, (char*)fname);
592   if (bfd->cmd_plugin && plugin_bopen) {
593     int rtnstat;
594     Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
595     rtnstat = plugin_bopen(bfd, fname, flags, mode);
596     Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
597     if (rtnstat >= 0) {
598       if (flags & O_CREAT || flags & O_WRONLY) { /* Open existing for write */
599         Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
600         bfd->mode = BF_WRITE;
601       } else {
602         Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
603         bfd->mode = BF_READ;
604       }
605     } else {
606       bfd->mode = BF_CLOSED;
607       Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
608     }
609     FreePoolMemory(win32_fname_wchar);
610     FreePoolMemory(win32_fname);
611     return bfd->mode == BF_CLOSED ? -1 : 1;
612   }
613   Dmsg0(50, "=== NO plugin\n");
614 
615   if (!(p_CreateFileA || p_CreateFileW)) {
616     Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
617     return 0;
618   }
619 
620   if (p_CreateFileW && p_MultiByteToWideChar) {
621     make_win32_path_UTF8_2_wchar(win32_fname_wchar, fname);
622   }
623 
624   if (flags & O_CREAT) { /* Create */
625     if (bfd->use_backup_api) {
626       dwaccess = GENERIC_WRITE | FILE_ALL_ACCESS | WRITE_OWNER | WRITE_DAC |
627                  ACCESS_SYSTEM_SECURITY;
628       dwflags = FILE_FLAG_BACKUP_SEMANTICS;
629     } else {
630       dwaccess = GENERIC_WRITE;
631       dwflags = 0;
632     }
633 
634     /*
635      * Unicode open for create write
636      */
637     if (p_CreateFileW && p_MultiByteToWideChar) {
638       Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
639       bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
640                               dwaccess,      /* Requested access */
641                               0,             /* Shared mode */
642                               NULL,          /* SecurityAttributes */
643                               CREATE_ALWAYS, /* CreationDisposition */
644                               dwflags,       /* Flags and attributes */
645                               NULL);         /* TemplateFile */
646     } else {
647       /*
648        * ASCII open
649        */
650       Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
651       bfd->fh = p_CreateFileA(win32_fname, dwaccess, /* Requested access */
652                               0,                     /* Shared mode */
653                               NULL,                  /* SecurityAttributes */
654                               CREATE_ALWAYS,         /* CreationDisposition */
655                               dwflags,               /* Flags and attributes */
656                               NULL);                 /* TemplateFile */
657     }
658 
659     bfd->mode = BF_WRITE;
660   } else if (flags & O_WRONLY) {
661     /*
662      * Open existing for write
663      */
664     if (bfd->use_backup_api) {
665       dwaccess = GENERIC_READ | GENERIC_WRITE | WRITE_OWNER | WRITE_DAC;
666       if (flags & O_NOFOLLOW) {
667         dwflags = FILE_FLAG_BACKUP_SEMANTICS;
668       } else {
669         dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
670       }
671     } else {
672       dwaccess = GENERIC_READ | GENERIC_WRITE;
673       dwflags = 0;
674     }
675 
676     if (p_CreateFileW && p_MultiByteToWideChar) {
677       /*
678        * unicode open for open existing write
679        */
680       Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
681       bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
682                               dwaccess,      /* Requested access */
683                               0,             /* Shared mode */
684                               NULL,          /* SecurityAttributes */
685                               OPEN_EXISTING, /* CreationDisposition */
686                               dwflags,       /* Flags and attributes */
687                               NULL);         /* TemplateFile */
688     } else {
689       /*
690        * ASCII open
691        */
692       Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
693       bfd->fh = p_CreateFileA(win32_fname, dwaccess, /* Requested access */
694                               0,                     /* Shared mode */
695                               NULL,                  /* SecurityAttributes */
696                               OPEN_EXISTING,         /* CreationDisposition */
697                               dwflags,               /* Flags and attributes */
698                               NULL);                 /* TemplateFile */
699     }
700 
701     bfd->mode = BF_WRITE;
702   } else {
703     /*
704      * Open existing for read
705      */
706     if (bfd->use_backup_api) {
707       dwaccess = GENERIC_READ | READ_CONTROL | ACCESS_SYSTEM_SECURITY;
708       if (flags & O_NOFOLLOW) {
709         dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN;
710       } else {
711         dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN |
712                   FILE_FLAG_OPEN_REPARSE_POINT;
713       }
714       dwshare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
715     } else {
716       dwaccess = GENERIC_READ;
717       dwflags = 0;
718       dwshare = FILE_SHARE_READ | FILE_SHARE_WRITE;
719     }
720 
721     if (p_CreateFileW && p_MultiByteToWideChar) {
722       /*
723        * Unicode open for open existing read
724        */
725       Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
726       bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
727                               dwaccess,      /* Requested access */
728                               dwshare,       /* Share modes */
729                               NULL,          /* SecurityAttributes */
730                               OPEN_EXISTING, /* CreationDisposition */
731                               dwflags,       /* Flags and attributes */
732                               NULL);         /* TemplateFile */
733     } else {
734       /*
735        * ASCII open for open existing read
736        */
737       Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
738       bfd->fh = p_CreateFileA(win32_fname, dwaccess, /* Requested access */
739                               dwshare,               /* Share modes */
740                               NULL,                  /* SecurityAttributes */
741                               OPEN_EXISTING,         /* CreationDisposition */
742                               dwflags,               /* Flags and attributes */
743                               NULL);                 /* TemplateFile */
744     }
745 
746     bfd->mode = BF_READ;
747   }
748 
749   if (bfd->fh == INVALID_HANDLE_VALUE) {
750     bfd->lerror = GetLastError();
751     bfd->BErrNo = b_errno_win32;
752     errno = b_errno_win32;
753     bfd->mode = BF_CLOSED;
754   }
755 
756   bfd->errmsg = NULL;
757   bfd->lpContext = NULL;
758   bfd->win32DecompContext.bIsInData = false;
759   bfd->win32DecompContext.liNextHeader = 0;
760   FreePoolMemory(win32_fname_wchar);
761   FreePoolMemory(win32_fname);
762 
763   bfd->encrypted = false;
764 
765   return bfd->mode == BF_CLOSED ? -1 : 1;
766 }
767 
bopen(BareosWinFilePacket * bfd,const char * fname,int flags,mode_t mode,dev_t rdev)768 int bopen(BareosWinFilePacket* bfd,
769           const char* fname,
770           int flags,
771           mode_t mode,
772           dev_t rdev)
773 {
774   Dmsg4(100, "bopen: fname %s, flags %08o, mode %04o, rdev %u\n", fname, flags,
775         (mode & ~S_IFMT), rdev);
776 
777   /*
778    * If the FILE_ATTRIBUTES_DEDUPED_ITEM bit is set this is a deduped file
779    * we let the bopen function know it should open the file without the
780    * FILE_FLAG_OPEN_REPARSE_POINT flag by setting in the O_NOFOLLOW open flag.
781    */
782   if (rdev & FILE_ATTRIBUTES_DEDUPED_ITEM) { flags |= O_NOFOLLOW; }
783 
784   /*
785    * If the FILE_ATTRIBUTE_ENCRYPTED bit is set this is an file on an EFS
786    * filesystem. For that we need some special handling.
787    */
788   if (rdev & FILE_ATTRIBUTE_ENCRYPTED) {
789     return BopenEncrypted(bfd, fname, flags, mode);
790   } else {
791     return BopenNonencrypted(bfd, fname, flags, mode);
792   }
793 }
794 
795 /**
796  * Returns  0 on success
797  *         -1 on error
798  */
BcloseEncrypted(BareosWinFilePacket * bfd)799 static inline int BcloseEncrypted(BareosWinFilePacket* bfd)
800 {
801   if (bfd->mode == BF_CLOSED) {
802     Dmsg0(50, "=== BFD already closed.\n");
803     return 0;
804   }
805 
806   if (!p_CloseEncryptedFileRaw) {
807     Dmsg0(50, "No p_CloseEncryptedFileRaw !!!!!\n");
808     return 0;
809   }
810 
811   p_CloseEncryptedFileRaw(bfd->pvContext);
812   bfd->pvContext = NULL;
813   bfd->mode = BF_CLOSED;
814 
815   return 0;
816 }
817 
818 /**
819  * Returns  0 on success
820  *         -1 on error
821  */
BcloseNonencrypted(BareosWinFilePacket * bfd)822 static inline int BcloseNonencrypted(BareosWinFilePacket* bfd)
823 {
824   int status = 0;
825 
826   if (bfd->mode == BF_CLOSED) {
827     Dmsg0(50, "=== BFD already closed.\n");
828     return 0;
829   }
830 
831   if (bfd->cmd_plugin && plugin_bclose) {
832     status = plugin_bclose(bfd);
833     Dmsg0(50, "==== BFD closed!!!\n");
834     goto all_done;
835   }
836 
837   /*
838    * We need to tell the API to release the buffer it
839    *  allocated in lpContext.  We do so by calling the
840    *  API one more time, but with the Abort bit set.
841    */
842   if (bfd->use_backup_api && bfd->mode == BF_READ) {
843     BYTE buf[10];
844     if (bfd->lpContext && !p_BackupRead(bfd->fh, buf,   /* buffer */
845                                         (DWORD)0,       /* bytes to read */
846                                         &bfd->rw_bytes, /* bytes read */
847                                         1,              /* Abort */
848                                         1,              /* ProcessSecurity */
849                                         &bfd->lpContext)) { /* Read context */
850       errno = b_errno_win32;
851       status = -1;
852     }
853   } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
854     BYTE buf[10];
855     if (bfd->lpContext && !p_BackupWrite(bfd->fh, buf,   /* buffer */
856                                          (DWORD)0,       /* bytes to read */
857                                          &bfd->rw_bytes, /* bytes written */
858                                          1,              /* Abort */
859                                          1,              /* ProcessSecurity */
860                                          &bfd->lpContext)) { /* Write context */
861       errno = b_errno_win32;
862       status = -1;
863     }
864   }
865   if (!CloseHandle(bfd->fh)) {
866     status = -1;
867     errno = b_errno_win32;
868   }
869 
870 all_done:
871   if (bfd->errmsg) {
872     FreePoolMemory(bfd->errmsg);
873     bfd->errmsg = NULL;
874   }
875   bfd->mode = BF_CLOSED;
876   bfd->lpContext = NULL;
877   bfd->cmd_plugin = false;
878 
879   return status;
880 }
881 
882 /**
883  * Returns  0 on success
884  *         -1 on error
885  */
bclose(BareosWinFilePacket * bfd)886 int bclose(BareosWinFilePacket* bfd)
887 {
888   if (bfd->encrypted) {
889     return BcloseEncrypted(bfd);
890   } else {
891     return BcloseNonencrypted(bfd);
892   }
893 }
894 
895 /* Returns: bytes read on success
896  *           0         on EOF
897  *          -1         on error
898  */
bread(BareosWinFilePacket * bfd,void * buf,size_t count)899 ssize_t bread(BareosWinFilePacket* bfd, void* buf, size_t count)
900 {
901   bfd->rw_bytes = 0;
902 
903   if (bfd->cmd_plugin && plugin_bread) { return plugin_bread(bfd, buf, count); }
904 
905   if (bfd->use_backup_api) {
906     if (!p_BackupRead(bfd->fh, (BYTE*)buf, count, &bfd->rw_bytes,
907                       0,                  /* no Abort */
908                       1,                  /* Process Security */
909                       &bfd->lpContext)) { /* Context */
910       bfd->lerror = GetLastError();
911       bfd->BErrNo = b_errno_win32;
912       errno = b_errno_win32;
913       return -1;
914     }
915   } else {
916     if (!ReadFile(bfd->fh, buf, count, &bfd->rw_bytes, NULL)) {
917       bfd->lerror = GetLastError();
918       bfd->BErrNo = b_errno_win32;
919       errno = b_errno_win32;
920       return -1;
921     }
922   }
923 
924   return (ssize_t)bfd->rw_bytes;
925 }
926 
bwrite(BareosWinFilePacket * bfd,void * buf,size_t count)927 ssize_t bwrite(BareosWinFilePacket* bfd, void* buf, size_t count)
928 {
929   bfd->rw_bytes = 0;
930 
931   if (bfd->cmd_plugin && plugin_bwrite) {
932     return plugin_bwrite(bfd, buf, count);
933   }
934 
935   if (bfd->use_backup_api) {
936     if (!p_BackupWrite(bfd->fh, (BYTE*)buf, count, &bfd->rw_bytes,
937                        0,                  /* No abort */
938                        1,                  /* Process Security */
939                        &bfd->lpContext)) { /* Context */
940       bfd->lerror = GetLastError();
941       bfd->BErrNo = b_errno_win32;
942       errno = b_errno_win32;
943       return -1;
944     }
945   } else {
946     if (!WriteFile(bfd->fh, buf, count, &bfd->rw_bytes, NULL)) {
947       bfd->lerror = GetLastError();
948       bfd->BErrNo = b_errno_win32;
949       errno = b_errno_win32;
950       return -1;
951     }
952   }
953 
954   return (ssize_t)bfd->rw_bytes;
955 }
956 
IsBopen(BareosWinFilePacket * bfd)957 bool IsBopen(BareosWinFilePacket* bfd) { return bfd->mode != BF_CLOSED; }
958 
blseek(BareosWinFilePacket * bfd,boffset_t offset,int whence)959 boffset_t blseek(BareosWinFilePacket* bfd, boffset_t offset, int whence)
960 {
961   LONG offset_low = (LONG)offset;
962   LONG offset_high = (LONG)(offset >> 32);
963   DWORD dwResult;
964 
965   if (bfd->cmd_plugin && plugin_blseek) {
966     return plugin_blseek(bfd, offset, whence);
967   }
968 
969   dwResult = SetFilePointer(bfd->fh, offset_low, &offset_high, whence);
970 
971   if (dwResult == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) {
972     return (boffset_t)-1;
973   }
974 
975   return ((boffset_t)offset_high << 32) | dwResult;
976 }
977 
978 #else /* Unix systems */
979 
980 /* ===============================================================
981  *
982  *            U N I X
983  *
984  * ===============================================================
985  */
binit(BareosWinFilePacket * bfd)986 void binit(BareosWinFilePacket* bfd) { bfd->fid = -1; }
987 
have_win32_api()988 bool have_win32_api() { return false; /* no can do */ }
989 
990 /**
991  * Enables using the Backup API (win32_data).
992  *   Returns true  if function worked
993  *   Returns false if failed (i.e. do not have Backup API on this machine)
994  */
set_win32_backup(BareosWinFilePacket * bfd)995 bool set_win32_backup(BareosWinFilePacket* bfd)
996 {
997   return false; /* no can do */
998 }
999 
SetPortableBackup(BareosWinFilePacket * bfd)1000 bool SetPortableBackup(BareosWinFilePacket* bfd)
1001 {
1002   return true; /* no problem */
1003 }
1004 
1005 /**
1006  * Return true  if we are writing in portable format
1007  * return false if not
1008  */
IsPortableBackup(BareosWinFilePacket * bfd)1009 bool IsPortableBackup(BareosWinFilePacket* bfd)
1010 {
1011   return true; /* portable by definition */
1012 }
1013 
set_prog(BareosWinFilePacket * bfd,char * prog,JobControlRecord * jcr)1014 bool set_prog(BareosWinFilePacket* bfd, char* prog, JobControlRecord* jcr)
1015 {
1016   return false;
1017 }
1018 
SetCmdPlugin(BareosWinFilePacket * bfd,JobControlRecord * jcr)1019 bool SetCmdPlugin(BareosWinFilePacket* bfd, JobControlRecord* jcr)
1020 {
1021   bfd->cmd_plugin = true;
1022   bfd->jcr = jcr;
1023   return true;
1024 }
1025 
1026 /**
1027  * This code is running on a non-Win32 machine
1028  */
IsRestoreStreamSupported(int stream)1029 bool IsRestoreStreamSupported(int stream)
1030 {
1031   /* No Win32 backup on this machine */
1032   switch (stream) {
1033 #ifndef HAVE_LIBZ
1034     case STREAM_GZIP_DATA:
1035     case STREAM_SPARSE_GZIP_DATA:
1036     case STREAM_WIN32_GZIP_DATA:
1037 #endif
1038 #ifndef HAVE_DARWIN_OS
1039     case STREAM_MACOS_FORK_DATA:
1040     case STREAM_HFSPLUS_ATTRIBUTES:
1041 #endif
1042       return false;
1043 
1044       /* Known streams */
1045 #ifdef HAVE_LIBZ
1046     case STREAM_GZIP_DATA:
1047     case STREAM_SPARSE_GZIP_DATA:
1048     case STREAM_WIN32_GZIP_DATA:
1049 #endif
1050     case STREAM_COMPRESSED_DATA:
1051     case STREAM_SPARSE_COMPRESSED_DATA:
1052     case STREAM_WIN32_COMPRESSED_DATA:
1053     case STREAM_ENCRYPTED_FILE_COMPRESSED_DATA:
1054     case STREAM_ENCRYPTED_WIN32_COMPRESSED_DATA:
1055     case STREAM_WIN32_DATA:
1056     case STREAM_UNIX_ATTRIBUTES:
1057     case STREAM_FILE_DATA:
1058     case STREAM_MD5_DIGEST:
1059     case STREAM_UNIX_ATTRIBUTES_EX:
1060     case STREAM_SPARSE_DATA:
1061     case STREAM_PROGRAM_NAMES:
1062     case STREAM_PROGRAM_DATA:
1063     case STREAM_SHA1_DIGEST:
1064 #ifdef HAVE_SHA2
1065     case STREAM_SHA256_DIGEST:
1066     case STREAM_SHA512_DIGEST:
1067 #endif
1068 #ifdef HAVE_CRYPTO
1069     case STREAM_SIGNED_DIGEST:
1070     case STREAM_ENCRYPTED_FILE_DATA:
1071     case STREAM_ENCRYPTED_FILE_GZIP_DATA:
1072     case STREAM_ENCRYPTED_WIN32_DATA:
1073     case STREAM_ENCRYPTED_WIN32_GZIP_DATA:
1074 #endif
1075 #ifdef HAVE_DARWIN_OS
1076     case STREAM_MACOS_FORK_DATA:
1077     case STREAM_HFSPLUS_ATTRIBUTES:
1078 #ifdef HAVE_CRYPTO
1079     case STREAM_ENCRYPTED_MACOS_FORK_DATA:
1080 #endif /* HAVE_CRYPTO */
1081 #endif /* HAVE_DARWIN_OS */
1082     case 0: /* compatibility with old tapes */
1083       return true;
1084   }
1085   return false;
1086 }
1087 
bopen(BareosWinFilePacket * bfd,const char * fname,int flags,mode_t mode,dev_t rdev)1088 int bopen(BareosWinFilePacket* bfd,
1089           const char* fname,
1090           int flags,
1091           mode_t mode,
1092           dev_t rdev)
1093 {
1094   Dmsg4(100, "bopen: fname %s, flags %08o, mode %04o, rdev %u\n", fname, flags,
1095         (mode & ~S_IFMT), rdev);
1096 
1097   if (bfd->cmd_plugin && plugin_bopen) {
1098     Dmsg1(400, "call plugin_bopen fname=%s\n", fname);
1099     bfd->fid = plugin_bopen(bfd, fname, flags, mode);
1100     Dmsg1(400, "Plugin bopen stat=%d\n", bfd->fid);
1101     return bfd->fid;
1102   }
1103 
1104   /* Normal file open */
1105   Dmsg1(debuglevel, "open file %s\n", fname);
1106 
1107   /* We use fnctl to set O_NOATIME if requested to avoid open error */
1108   bfd->fid = open(fname, flags & ~O_NOATIME, mode);
1109 
1110   /* Set O_NOATIME if possible */
1111   if (bfd->fid != -1 && flags & O_NOATIME) {
1112     int oldflags = fcntl(bfd->fid, F_GETFL, 0);
1113     if (oldflags == -1) {
1114       bfd->BErrNo = errno;
1115       close(bfd->fid);
1116       bfd->fid = -1;
1117     } else {
1118       int ret = fcntl(bfd->fid, F_SETFL, oldflags | O_NOATIME);
1119       /* EPERM means setting O_NOATIME was not allowed  */
1120       if (ret == -1 && errno != EPERM) {
1121         bfd->BErrNo = errno;
1122         close(bfd->fid);
1123         bfd->fid = -1;
1124       }
1125     }
1126   }
1127   bfd->BErrNo = errno;
1128   bfd->flags_ = flags;
1129   Dmsg1(400, "Open file %d\n", bfd->fid);
1130   errno = bfd->BErrNo;
1131 
1132   bfd->win32DecompContext.bIsInData = false;
1133   bfd->win32DecompContext.liNextHeader = 0;
1134 
1135 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_WILLNEED)
1136   if (bfd->fid != -1 && flags & O_RDONLY) {
1137     int status = posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_WILLNEED);
1138     Dmsg2(400, "Did posix_fadvise on %s status=%d\n", fname, status);
1139   }
1140 #endif
1141 
1142   return bfd->fid;
1143 }
1144 
1145 #ifdef HAVE_DARWIN_OS
1146 /**
1147  * Open the resource fork of a file.
1148  */
BopenRsrc(BareosWinFilePacket * bfd,const char * fname,int flags,mode_t mode)1149 int BopenRsrc(BareosWinFilePacket* bfd,
1150               const char* fname,
1151               int flags,
1152               mode_t mode)
1153 {
1154   POOLMEM* rsrc_fname;
1155 
1156   rsrc_fname = GetPoolMemory(PM_FNAME);
1157   PmStrcpy(rsrc_fname, fname);
1158   PmStrcat(rsrc_fname, _PATH_RSRCFORKSPEC);
1159   bopen(bfd, rsrc_fname, flags, mode, 0);
1160   FreePoolMemory(rsrc_fname);
1161 
1162   return bfd->fid;
1163 }
1164 #else
BopenRsrc(BareosWinFilePacket * bfd,const char * fname,int flags,mode_t mode)1165 int BopenRsrc(BareosWinFilePacket* bfd,
1166               const char* fname,
1167               int flags,
1168               mode_t mode)
1169 {
1170   return -1;
1171 }
1172 #endif
1173 
bclose(BareosWinFilePacket * bfd)1174 int bclose(BareosWinFilePacket* bfd)
1175 {
1176   int status;
1177 
1178   if (bfd->fid == -1) { return 0; }
1179 
1180   Dmsg1(400, "Close file %d\n", bfd->fid);
1181 
1182   if (bfd->cmd_plugin && plugin_bclose) {
1183     status = plugin_bclose(bfd);
1184     bfd->fid = -1;
1185     bfd->cmd_plugin = false;
1186   } else {
1187 #if defined(HAVE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
1188     if (bfd->flags_ & O_RDONLY) {
1189       fdatasync(bfd->fid); /* sync the file */
1190       /* Tell OS we don't need it any more */
1191       posix_fadvise(bfd->fid, 0, 0, POSIX_FADV_DONTNEED);
1192     }
1193 #endif
1194 
1195     /* Close normal file */
1196     status = close(bfd->fid);
1197     bfd->BErrNo = errno;
1198     bfd->fid = -1;
1199     bfd->cmd_plugin = false;
1200   }
1201 
1202   return status;
1203 }
1204 
bread(BareosWinFilePacket * bfd,void * buf,size_t count)1205 ssize_t bread(BareosWinFilePacket* bfd, void* buf, size_t count)
1206 {
1207   ssize_t status;
1208 
1209   if (bfd->cmd_plugin && plugin_bread) { return plugin_bread(bfd, buf, count); }
1210 
1211   status = read(bfd->fid, buf, count);
1212   bfd->BErrNo = errno;
1213   return status;
1214 }
1215 
bwrite(BareosWinFilePacket * bfd,void * buf,size_t count)1216 ssize_t bwrite(BareosWinFilePacket* bfd, void* buf, size_t count)
1217 {
1218   ssize_t status;
1219 
1220   if (bfd->cmd_plugin && plugin_bwrite) {
1221     return plugin_bwrite(bfd, buf, count);
1222   }
1223   status = write(bfd->fid, buf, count);
1224   bfd->BErrNo = errno;
1225   return status;
1226 }
1227 
IsBopen(BareosWinFilePacket * bfd)1228 bool IsBopen(BareosWinFilePacket* bfd) { return bfd->fid >= 0; }
1229 
blseek(BareosWinFilePacket * bfd,boffset_t offset,int whence)1230 boffset_t blseek(BareosWinFilePacket* bfd, boffset_t offset, int whence)
1231 {
1232   boffset_t pos;
1233 
1234   if (bfd->cmd_plugin && plugin_bwrite) {
1235     return plugin_blseek(bfd, offset, whence);
1236   }
1237   pos = (boffset_t)lseek(bfd->fid, offset, whence);
1238   bfd->BErrNo = errno;
1239   return pos;
1240 }
1241 #endif
1242