]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/bfile.c
UTF-8 support for win32 finished
[bacula/bacula] / bacula / src / findlib / bfile.c
1 /*
2  *  Bacula low level File I/O routines.  This routine simulates
3  *    open(), read(), write(), and close(), but using native routines.
4  *    I.e. on Windows, we use Windows APIs.
5  *
6  *    Kern Sibbald, April MMIII
7  *
8  *   Version $Id$
9  *
10  */
11 /*
12    Copyright (C) 2003-2005 Kern Sibbald
13
14    This program is free software; you can redistribute it and/or
15    modify it under the terms of the GNU General Public License as
16    published by the Free Software Foundation; either version 2 of
17    the License, or (at your option) any later version.
18
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22    General Public License for more details.
23
24    You should have received a copy of the GNU General Public
25    License along with this program; if not, write to the Free
26    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27    MA 02111-1307, USA.
28
29  */
30
31 #include "bacula.h"
32 #include "find.h"
33
34 bool    (*python_set_prog)(JCR *jcr, const char *prog) = NULL;
35 int     (*python_open)(BFILE *bfd, const char *fname, int flags, mode_t mode) = NULL;
36 int     (*python_close)(BFILE *bfd) = NULL;
37 ssize_t (*python_read)(BFILE *bfd, void *buf, size_t count) = NULL;
38 ssize_t (*python_write)(BFILE *bfd, void *buf, size_t count) = NULL;
39
40 #ifdef HAVE_DARWIN_OS
41 #include <sys/paths.h>
42 #endif
43
44 /* ===============================================================
45  *
46  *            U N I X   AND   W I N D O W S
47  *
48  * ===============================================================
49  */
50
51 bool is_win32_stream(int stream)
52 {
53    switch (stream) {
54    case STREAM_WIN32_DATA:
55    case STREAM_WIN32_GZIP_DATA:
56       return true;
57    }
58    return false;
59 }
60
61 const char *stream_to_ascii(int stream)
62 {
63    static char buf[20];
64
65    switch (stream) {
66    case STREAM_GZIP_DATA:
67       return "GZIP data";
68    case STREAM_SPARSE_GZIP_DATA:
69       return "GZIP sparse data";
70    case STREAM_WIN32_DATA:
71       return "Win32 data";
72    case STREAM_WIN32_GZIP_DATA:
73       return "Win32 GZIP data";
74    case STREAM_UNIX_ATTRIBUTES:
75       return "File attributes";
76    case STREAM_FILE_DATA:
77       return "File data";
78    case STREAM_MD5_SIGNATURE:
79       return "MD5 signature";
80    case STREAM_UNIX_ATTRIBUTES_EX:
81       return "Extended attributes";
82    case STREAM_SPARSE_DATA:
83       return "Sparse data";
84    case STREAM_PROGRAM_NAMES:
85       return "Program names";
86    case STREAM_PROGRAM_DATA:
87       return "Program data";
88    case STREAM_SHA1_SIGNATURE:
89       return "SHA1 signature";
90    case STREAM_MACOS_FORK_DATA:
91       return "HFS+ resource fork";
92    case STREAM_HFSPLUS_ATTRIBUTES:
93       return "HFS+ Finder Info";
94    default:
95       sprintf(buf, "%d", stream);
96       return (const char *)buf;
97    }
98 }
99
100
101
102 /* ===============================================================
103  *
104  *            W I N D O W S
105  *
106  * ===============================================================
107  */
108
109 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
110
111 void unix_name_to_win32(POOLMEM **win32_name, char *name);
112 extern "C" HANDLE get_osfhandle(int fd);
113
114
115
116 void binit(BFILE *bfd)
117 {
118    memset(bfd, 0, sizeof(BFILE));
119    bfd->fid = -1;
120    bfd->mode = BF_CLOSED;
121    bfd->use_backup_api = have_win32_api();
122 }
123
124 /*
125  * Enables using the Backup API (win32_data).
126  *   Returns 1 if function worked
127  *   Returns 0 if failed (i.e. do not have Backup API on this machine)
128  */
129 bool set_win32_backup(BFILE *bfd)
130 {
131    /* We enable if possible here */
132    bfd->use_backup_api = have_win32_api();
133    return bfd->use_backup_api;
134 }
135
136
137 bool set_portable_backup(BFILE *bfd)
138 {
139    bfd->use_backup_api = false;
140    return true;
141 }
142
143 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
144 {
145    bfd->prog = prog;
146    bfd->jcr = jcr;
147    return false;
148 }
149
150 /*
151  * Return 1 if we are NOT using Win32 BackupWrite()
152  * return 0 if are
153  */
154 bool is_portable_backup(BFILE *bfd)
155 {
156    return !bfd->use_backup_api;
157 }
158
159 bool have_win32_api()
160 {
161    return p_BackupRead && p_BackupWrite;
162 }
163
164
165
166 /*
167  * Return 1 if we support the stream
168  *        0 if we do not support the stream
169  */
170 bool is_stream_supported(int stream)
171 {
172    /* No Win32 backup on this machine */
173    switch (stream) {
174 #ifndef HAVE_LIBZ
175    case STREAM_GZIP_DATA:
176    case STREAM_SPARSE_GZIP_DATA:
177       return 0;
178 #endif
179    case STREAM_WIN32_DATA:
180    case STREAM_WIN32_GZIP_DATA:
181       return have_win32_api();
182
183    case STREAM_MACOS_FORK_DATA:
184    case STREAM_HFSPLUS_ATTRIBUTES:
185       return false;
186
187    /* Known streams */
188 #ifdef HAVE_LIBZ
189    case STREAM_GZIP_DATA:
190    case STREAM_SPARSE_GZIP_DATA:
191 #endif
192    case STREAM_UNIX_ATTRIBUTES:
193    case STREAM_FILE_DATA:
194    case STREAM_MD5_SIGNATURE:
195    case STREAM_UNIX_ATTRIBUTES_EX:
196    case STREAM_SPARSE_DATA:
197    case STREAM_PROGRAM_NAMES:
198    case STREAM_PROGRAM_DATA:
199    case STREAM_SHA1_SIGNATURE:
200    case 0:                            /* compatibility with old tapes */
201       return true;
202    }
203    return false;
204 }
205
206 HANDLE bget_handle(BFILE *bfd)
207 {
208    return bfd->fh;
209 }
210
211 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
212 {
213    POOLMEM *win32_fname;
214    DWORD dwaccess, dwflags, dwshare;
215    WCHAR win32_fname_wchar[MAX_PATH_UNICODE];
216
217    /* Convert to Windows path format */
218    win32_fname = get_pool_memory(PM_FNAME);
219    unix_name_to_win32(&win32_fname, (char *)fname);
220
221    if (!(p_CreateFileA || p_CreateFileW))
222       return 0;
223
224    if (p_CreateFileW){         
225    UTF8_2_wchar(win32_fname_wchar, win32_fname, MAX_PATH_UNICODE);
226    }
227
228    if (flags & O_CREAT) {             /* Create */
229       if (bfd->use_backup_api) {
230          dwaccess = GENERIC_WRITE|FILE_ALL_ACCESS|WRITE_OWNER|WRITE_DAC|ACCESS_SYSTEM_SECURITY;
231          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
232       } else {
233          dwaccess = GENERIC_WRITE;
234          dwflags = 0;
235       }
236
237    // unicode or ansii open for create write
238    if (p_CreateFileW) {   
239       bfd->fh = p_CreateFileW(win32_fname_wchar,
240              dwaccess,                /* Requested access */
241              0,                       /* Shared mode */
242              NULL,                    /* SecurityAttributes */
243              CREATE_ALWAYS,           /* CreationDisposition */
244              dwflags,                 /* Flags and attributes */
245              NULL);                   /* TemplateFile */
246    }
247    else {
248       bfd->fh = p_CreateFileA(win32_fname,
249              dwaccess,                /* Requested access */
250              0,                       /* Shared mode */
251              NULL,                    /* SecurityAttributes */
252              CREATE_ALWAYS,           /* CreationDisposition */
253              dwflags,                 /* Flags and attributes */
254              NULL);                   /* TemplateFile */
255    }
256
257
258       bfd->mode = BF_WRITE;
259
260    } else if (flags & O_WRONLY) {     /* Open existing for write */
261       if (bfd->use_backup_api) {
262          dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC;
263          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
264       } else {
265          dwaccess = GENERIC_WRITE;
266          dwflags = 0;
267       }
268
269    // unicode or ansii open for open existing write
270    if (p_CreateFileW) {   
271       bfd->fh = p_CreateFileW(win32_fname_wchar,
272              dwaccess,                /* Requested access */
273              0,                       /* Shared mode */
274              NULL,                    /* SecurityAttributes */
275              OPEN_EXISTING,           /* CreationDisposition */
276              dwflags,                 /* Flags and attributes */
277              NULL);                   /* TemplateFile */
278    }
279    else {
280       bfd->fh = p_CreateFileA(win32_fname,
281              dwaccess,                /* Requested access */
282              0,                       /* Shared mode */
283              NULL,                    /* SecurityAttributes */
284              OPEN_EXISTING,           /* CreationDisposition */
285              dwflags,                 /* Flags and attributes */
286              NULL);                   /* TemplateFile */
287
288    }
289
290       bfd->mode = BF_WRITE;
291
292    } else {                           /* Read */
293       if (bfd->use_backup_api) {
294          dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY;
295          dwflags = FILE_FLAG_BACKUP_SEMANTICS;
296          dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE;
297       } else {
298          dwaccess = GENERIC_READ;
299          dwflags = 0;
300          dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE;
301       }
302
303       // unicode or ansii open for open existing read
304    if (p_CreateFileW) {   
305       bfd->fh = p_CreateFileW(win32_fname_wchar,
306              dwaccess,                /* Requested access */
307              dwshare,                 /* Share modes */
308              NULL,                    /* SecurityAttributes */
309              OPEN_EXISTING,           /* CreationDisposition */
310              dwflags,                 /* Flags and attributes */
311              NULL);                   /* TemplateFile */
312    }
313    else {
314       bfd->fh = p_CreateFileA(win32_fname,
315              dwaccess,                /* Requested access */
316              dwshare,                 /* Share modes */
317              NULL,                    /* SecurityAttributes */
318              OPEN_EXISTING,           /* CreationDisposition */
319              dwflags,                 /* Flags and attributes */
320              NULL);                   /* TemplateFile */
321    }
322
323       bfd->mode = BF_READ;
324    }
325
326    if (bfd->fh == INVALID_HANDLE_VALUE) {
327       bfd->lerror = GetLastError();
328       bfd->berrno = b_errno_win32;
329       errno = b_errno_win32;
330       bfd->mode = BF_CLOSED;
331    }
332    bfd->errmsg = NULL;
333    bfd->lpContext = NULL;
334    free_pool_memory(win32_fname);
335    return bfd->mode == BF_CLOSED ? -1 : 1;
336 }
337
338 /*
339  * Returns  0 on success
340  *         -1 on error
341  */
342 int bclose(BFILE *bfd)
343 {
344    int stat = 0;
345
346    if (bfd->errmsg) {
347       free_pool_memory(bfd->errmsg);
348       bfd->errmsg = NULL;
349    }
350    if (bfd->mode == BF_CLOSED) {
351       return 0;
352    }
353    if (bfd->use_backup_api && bfd->mode == BF_READ) {
354       BYTE buf[10];
355       if (!bfd->lpContext && !p_BackupRead(bfd->fh,
356               buf,                    /* buffer */
357               (DWORD)0,               /* bytes to read */
358               &bfd->rw_bytes,         /* bytes read */
359               1,                      /* Abort */
360               1,                      /* ProcessSecurity */
361               &bfd->lpContext)) {     /* Read context */
362          errno = b_errno_win32;
363          stat = -1;
364       }
365    } else if (bfd->use_backup_api && bfd->mode == BF_WRITE) {
366       BYTE buf[10];
367       if (!bfd->lpContext && !p_BackupWrite(bfd->fh,
368               buf,                    /* buffer */
369               (DWORD)0,               /* bytes to read */
370               &bfd->rw_bytes,         /* bytes written */
371               1,                      /* Abort */
372               1,                      /* ProcessSecurity */
373               &bfd->lpContext)) {     /* Write context */
374          errno = b_errno_win32;
375          stat = -1;
376       }
377    }
378    if (!CloseHandle(bfd->fh)) {
379       stat = -1;
380       errno = b_errno_win32;
381    }
382    bfd->mode = BF_CLOSED;
383    bfd->lpContext = NULL;
384    return stat;
385 }
386
387 /* Returns: bytes read on success
388  *           0         on EOF
389  *          -1         on error
390  */
391 ssize_t bread(BFILE *bfd, void *buf, size_t count)
392 {
393    bfd->rw_bytes = 0;
394
395    if (bfd->use_backup_api) {
396       if (!p_BackupRead(bfd->fh,
397            (BYTE *)buf,
398            count,
399            &bfd->rw_bytes,
400            0,                           /* no Abort */
401            1,                           /* Process Security */
402            &bfd->lpContext)) {          /* Context */
403          bfd->lerror = GetLastError();
404          bfd->berrno = b_errno_win32;
405          errno = b_errno_win32;
406          return -1;
407       }
408    } else {
409       if (!ReadFile(bfd->fh,
410            buf,
411            count,
412            &bfd->rw_bytes,
413            NULL)) {
414          bfd->lerror = GetLastError();
415          bfd->berrno = b_errno_win32;
416          errno = b_errno_win32;
417          return -1;
418       }
419    }
420
421    return (ssize_t)bfd->rw_bytes;
422 }
423
424 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
425 {
426    bfd->rw_bytes = 0;
427
428    if (bfd->use_backup_api) {
429       if (!p_BackupWrite(bfd->fh,
430            (BYTE *)buf,
431            count,
432            &bfd->rw_bytes,
433            0,                           /* No abort */
434            1,                           /* Process Security */
435            &bfd->lpContext)) {          /* Context */
436          bfd->lerror = GetLastError();
437          bfd->berrno = b_errno_win32;
438          errno = b_errno_win32;
439          return -1;
440       }
441    } else {
442       if (!WriteFile(bfd->fh,
443            buf,
444            count,
445            &bfd->rw_bytes,
446            NULL)) {
447          bfd->lerror = GetLastError();
448          bfd->berrno = b_errno_win32;
449          errno = b_errno_win32;
450          return -1;
451       }
452    }
453    return (ssize_t)bfd->rw_bytes;
454 }
455
456 bool is_bopen(BFILE *bfd)
457 {
458    return bfd->mode != BF_CLOSED;
459 }
460
461 off_t blseek(BFILE *bfd, off_t offset, int whence)
462 {
463    /* ****FIXME**** this must be implemented if we want to read Win32 Archives */
464    return -1;
465 }
466
467 #else  /* Unix systems */
468
469 /* ===============================================================
470  *
471  *            U N I X
472  *
473  * ===============================================================
474  */
475 void binit(BFILE *bfd)
476 {
477    memset(bfd, 0, sizeof(BFILE));
478    bfd->fid = -1;
479 }
480
481 bool have_win32_api()
482 {
483    return false;                       /* no can do */
484 }
485
486 /*
487  * Enables using the Backup API (win32_data).
488  *   Returns true  if function worked
489  *   Returns false if failed (i.e. do not have Backup API on this machine)
490  */
491 bool set_win32_backup(BFILE *bfd)
492 {
493    return false;                       /* no can do */
494 }
495
496
497 bool set_portable_backup(BFILE *bfd)
498 {
499    return true;                        /* no problem */
500 }
501
502 /*
503  * Return true  if we are writing in portable format
504  * return false if not
505  */
506 bool is_portable_backup(BFILE *bfd)
507 {
508    return true;                       /* portable by definition */
509 }
510
511 bool set_prog(BFILE *bfd, char *prog, JCR *jcr)
512 {
513 #ifdef HAVE_PYTHON
514    if (bfd->prog && strcmp(prog, bfd->prog) == 0) {
515       return true;                    /* already setup */
516    }
517
518    if (python_set_prog(jcr, prog)) {
519       Dmsg1(000, "Set prog=%s\n", prog);
520       bfd->prog = prog;
521       bfd->jcr = jcr;
522       return true;
523    }
524 #endif
525    Dmsg0(000, "No prog set\n");
526    bfd->prog = NULL;
527    return false;
528
529 }
530
531
532 bool is_stream_supported(int stream)
533 {
534    /* No Win32 backup on this machine */
535    switch (stream) {
536 #ifndef HAVE_LIBZ
537    case STREAM_GZIP_DATA:
538    case STREAM_SPARSE_GZIP_DATA:
539 #endif
540    case STREAM_WIN32_DATA:
541    case STREAM_WIN32_GZIP_DATA:
542 #ifndef HAVE_DARWIN_OS
543    case STREAM_MACOS_FORK_DATA:
544    case STREAM_HFSPLUS_ATTRIBUTES:
545 #endif
546       return false;
547
548    /* Known streams */
549 #ifdef HAVE_LIBZ
550    case STREAM_GZIP_DATA:
551    case STREAM_SPARSE_GZIP_DATA:
552 #endif
553    case STREAM_UNIX_ATTRIBUTES:
554    case STREAM_FILE_DATA:
555    case STREAM_MD5_SIGNATURE:
556    case STREAM_UNIX_ATTRIBUTES_EX:
557    case STREAM_SPARSE_DATA:
558    case STREAM_PROGRAM_NAMES:
559    case STREAM_PROGRAM_DATA:
560    case STREAM_SHA1_SIGNATURE:
561 #ifdef HAVE_DARWIN_OS
562    case STREAM_MACOS_FORK_DATA:
563    case STREAM_HFSPLUS_ATTRIBUTES:
564 #endif
565    case 0:                            /* compatibility with old tapes */
566       return true;
567
568    }
569    return 0;
570 }
571
572 /* Old file reader code */
573 #ifdef xxx
574    if (bfd->prog) {
575       POOLMEM *ecmd = get_pool_memory(PM_FNAME);
576       ecmd = edit_job_codes(bfd->jcr, ecmd, bfd->prog, fname);
577       const char *pmode;
578       if (flags & O_RDONLY) {
579          pmode = "r";
580       } else {
581          pmode = "w";
582       }
583       bfd->bpipe = open_bpipe(ecmd, 0, pmode);
584       if (bfd->bpipe == NULL) {
585          bfd->berrno = errno;
586          bfd->fid = -1;
587          free_pool_memory(ecmd);
588          return -1;
589       }
590       free_pool_memory(ecmd);
591       if (flags & O_RDONLY) {
592          bfd->fid = fileno(bfd->bpipe->rfd);
593       } else {
594          bfd->fid = fileno(bfd->bpipe->wfd);
595       }
596       errno = 0;
597       return bfd->fid;
598    }
599 #endif
600
601
602 int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
603 {
604    /* Open reader/writer program */
605    if (bfd->prog) {
606       Dmsg1(000, "Open file %d\n", bfd->fid);
607       return python_open(bfd, fname, flags, mode);
608    }
609
610    /* Normal file open */
611    bfd->fid = open(fname, flags, mode);
612    bfd->berrno = errno;
613    Dmsg1(400, "Open file %d\n", bfd->fid);
614    errno = bfd->berrno;
615    return bfd->fid;
616 }
617
618 #ifdef HAVE_DARWIN_OS
619 /* Open the resource fork of a file. */
620 int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
621 {
622    POOLMEM *rsrc_fname;
623    size_t fname_len;
624
625    fname_len = strlen(fname);
626    rsrc_fname = get_pool_memory(PM_FNAME);
627    bstrncpy(rsrc_fname, fname, fname_len + 1);
628    bstrncpy(rsrc_fname + fname_len, _PATH_RSRCFORKSPEC,
629       strlen(_PATH_RSRCFORKSPEC) + 1);
630    bopen(bfd, rsrc_fname, flags, mode);
631    free_pool_memory(rsrc_fname);
632    return bfd->fid;
633 }
634 #endif
635
636
637 int bclose(BFILE *bfd)
638 {
639    int stat;
640
641    Dmsg1(400, "Close file %d\n", bfd->fid);
642
643    /* Close reader/writer program */
644    if (bfd->prog) {
645       return python_close(bfd);
646    }
647
648    if (bfd->fid == -1) {
649       return 0;
650    }
651
652    /* Close normal file */
653    stat = close(bfd->fid);
654    bfd->berrno = errno;
655    bfd->fid = -1;
656    return stat;
657 }
658
659 ssize_t bread(BFILE *bfd, void *buf, size_t count)
660 {
661    ssize_t stat;
662
663    if (bfd->prog) {
664       return python_read(bfd, buf, count);
665    }
666    stat = read(bfd->fid, buf, count);
667    bfd->berrno = errno;
668    return stat;
669 }
670
671 ssize_t bwrite(BFILE *bfd, void *buf, size_t count)
672 {
673    ssize_t stat;
674
675    if (bfd->prog) {
676       return python_write(bfd, buf, count);
677    }
678    stat = write(bfd->fid, buf, count);
679    bfd->berrno = errno;
680    return stat;
681 }
682
683 bool is_bopen(BFILE *bfd)
684 {
685    return bfd->fid >= 0;
686 }
687
688 off_t blseek(BFILE *bfd, off_t offset, int whence)
689 {
690     off_t pos;
691     pos = lseek(bfd->fid, offset, whence);
692     bfd->berrno = errno;
693     return pos;
694 }
695
696 #endif