From 8fe6141bea03b596916c458eac78507b3a587403 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sun, 24 Jun 2007 17:27:12 +0000 Subject: [PATCH] kes Implement Windows reparse points -- similar to directories, but we do not descend into it. This is a first cut. They seem to be backed up, but restore is not yet tested. kes Remove restore_blocking in tls code when shutting a socket to leave it in blocking mode. Hopefully this will fix the encryption bug reported by Frank Sweetser. kes When opening a file for backup, tell the OS that we are going to read it sequentially -- optimization. kes Change variable names in authenticate_director() to not conflict with member names in bat. Caused great confusion with compiler, but no warnings. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@5077 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/baconfig.h | 3 +- bacula/src/filed/backup.c | 5 +- bacula/src/filed/estimate.c | 21 +-- bacula/src/filed/status.c | 5 +- bacula/src/filed/verify.c | 3 +- bacula/src/findlib/bfile.c | 34 +++-- bacula/src/findlib/bfile.h | 2 + bacula/src/findlib/create_file.c | 4 + bacula/src/findlib/find.c | 1 + bacula/src/findlib/find_one.c | 6 +- bacula/src/lib/bsock.c | 2 +- bacula/src/lib/tls.c | 5 +- bacula/src/version.h | 2 +- bacula/src/win32/compat/compat.cpp | 215 ++++++++++++++++------------- bacula/technotes-2.1 | 13 +- 15 files changed, 184 insertions(+), 137 deletions(-) diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index 6fa3fd6b2f..ae5bddbf9f 100644 --- a/bacula/src/baconfig.h +++ b/bacula/src/baconfig.h @@ -267,12 +267,13 @@ void InitWinAPIWrapper(); #define FT_NOOPEN 15 /* Could not open directory */ #define FT_RAW 16 /* Raw block device */ #define FT_FIFO 17 /* Raw fifo device */ -/* This directory packet is sent to the FD file processing routine so +/* The DIRBEGIN packet is sent to the FD file processing routine so * that it can filter packets, but otherwise, it is not used * or saved */ #define FT_DIRBEGIN 18 /* Directory at beginning (not saved) */ #define FT_INVALIDFS 19 /* File system not allowed for */ #define FT_INVALIDDT 20 /* Drive type not allowed for */ +#define FT_REPARSE 21 /* Win NTFS reparse point */ /* Definitions for upper part of type word (see above). */ #define AR_DATA_STREAM (1<<16) /* Data stream id present */ diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index e4651c7c19..db9193e716 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -273,6 +273,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) Jmsg(jcr, M_INFO, 1, _(" Disallowed drive type. Will not descend into %s\n"), ff_pkt->fname); break; + case FT_REPARSE: case FT_DIREND: Dmsg1(130, "FT_DIREND: %s\n", ff_pkt->link); break; @@ -441,6 +442,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) do_read = ff_pkt->statp.st_size > 0; #endif } else if (ff_pkt->type == FT_RAW || ff_pkt->type == FT_FIFO || + ff_pkt->type == FT_REPARSE || (!is_portable_backup(&ff_pkt->bfd) && ff_pkt->type == FT_DIREND)) { do_read = true; } @@ -453,6 +455,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level) tid = NULL; } int noatime = ff_pkt->flags & FO_NOATIME ? O_NOATIME : 0; + ff_pkt->bfd.reparse_point = ff_pkt->type == FT_REPARSE; if (bopen(&ff_pkt->bfd, ff_pkt->fname, O_RDONLY | O_BINARY | noatime, 0) < 0) { ff_pkt->ff_errno = errno; berrno be; @@ -1068,7 +1071,7 @@ static bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_strea stat = sd->fsend("%ld %d %s%c%s%c%s%c%s%c", jcr->JobFiles, ff_pkt->type, ff_pkt->fname, 0, attribs, 0, ff_pkt->link, 0, attribsEx, 0); - } else if (ff_pkt->type == FT_DIREND) { + } else if (ff_pkt->type == FT_DIREND || ff_pkt->type == FT_REPARSE) { /* Here link is the canonical filename (i.e. with trailing slash) */ stat = sd->fsend("%ld %d %s%c%s%c%c%s%c", jcr->JobFiles, ff_pkt->type, ff_pkt->link, 0, attribs, 0, 0, attribsEx, 0); diff --git a/bacula/src/filed/estimate.c b/bacula/src/filed/estimate.c index 26f9bd8866..70d0154fb4 100644 --- a/bacula/src/filed/estimate.c +++ b/bacula/src/filed/estimate.c @@ -1,16 +1,7 @@ -/* - * Bacula File Daemon estimate.c - * Make and estimate of the number of files and size to be saved. - * - * Kern Sibbald, September MMI - * - * Version $Id$ - * - */ /* Bacula® - The Network Backup Solution - Copyright (C) 2001-2006 Free Software Foundation Europe e.V. + Copyright (C) 2001-2007 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -34,6 +25,15 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * Bacula File Daemon estimate.c + * Make and estimate of the number of files and size to be saved. + * + * Kern Sibbald, September MMI + * + * Version $Id$ + * + */ #include "bacula.h" #include "filed.h" @@ -76,6 +76,7 @@ static int tally_file(FF_PKT *ff_pkt, void *ijcr, bool top_level) case FT_NOFSCHG: case FT_INVALIDFS: case FT_INVALIDDT: + case FT_REPARSE: case FT_DIREND: case FT_SPEC: case FT_RAW: diff --git a/bacula/src/filed/status.c b/bacula/src/filed/status.c index 07e0f6b2e1..866cc18dd6 100644 --- a/bacula/src/filed/status.c +++ b/bacula/src/filed/status.c @@ -174,8 +174,9 @@ void output_status(void sendit(const char *msg, int len, void *sarg), void *arg) edit_uint64_with_commas(njcr->JobBytes, b2), edit_uint64_with_commas(bps, b3)); sendit(msg.c_str(), len, arg); - len = Mmsg(msg, _(" Files Examined=%s\n"), - edit_uint64_with_commas(njcr->num_files_examined, b1)); + len = Mmsg(msg, _(" Files Examined=%s Errors=%d\n"), + edit_uint64_with_commas(njcr->num_files_examined, b1), + njcr->JobErrors); sendit(msg.c_str(), len, arg); if (njcr->JobFiles > 0) { njcr->lock(); diff --git a/bacula/src/filed/verify.c b/bacula/src/filed/verify.c index 18ebe09d7f..e42dcf5f6b 100644 --- a/bacula/src/filed/verify.c +++ b/bacula/src/filed/verify.c @@ -104,6 +104,7 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt, bool top_level) case FT_DIRBEGIN: jcr->num_files_examined--; /* correct file count */ return 1; /* ignored */ + case FT_REPARSE: case FT_DIREND: Dmsg1(30, "FT_DIR saving: %s\n", ff_pkt->fname); break; @@ -190,7 +191,7 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt, bool top_level) stat = bnet_fsend(dir, "%d %d %s %s%c%s%c%s%c", jcr->JobFiles, STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname, 0, attribs, 0, ff_pkt->link, 0); - } else if (ff_pkt->type == FT_DIREND) { + } else if (ff_pkt->type == FT_DIREND || ff_pkt->type == FT_REPARSE) { /* Here link is the canonical filename (i.e. with trailing slash) */ stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles, STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->link, diff --git a/bacula/src/findlib/bfile.c b/bacula/src/findlib/bfile.c index d98ba1afae..03b51431b5 100644 --- a/bacula/src/findlib/bfile.c +++ b/bacula/src/findlib/bfile.c @@ -1,13 +1,3 @@ -/* - * Bacula low level File I/O routines. This routine simulates - * open(), read(), write(), and close(), but using native routines. - * I.e. on Windows, we use Windows APIs. - * - * Kern Sibbald, April MMIII - * - * Version $Id$ - * - */ /* Bacula® - The Network Backup Solution @@ -35,6 +25,16 @@ (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, Switzerland, email:ftf@fsfeurope.org. */ +/* + * Bacula low level File I/O routines. This routine simulates + * open(), read(), write(), and close(), but using native routines. + * I.e. on Windows, we use Windows APIs. + * + * Kern Sibbald, April MMIII + * + * Version $Id$ + * + */ #include "bacula.h" #include "find.h" @@ -417,8 +417,8 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) dwflags = 0; } - // unicode or ascii open for create write if (p_CreateFileW && p_MultiByteToWideChar) { + // unicode open for create write bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar, dwaccess, /* Requested access */ 0, /* Shared mode */ @@ -427,6 +427,7 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) dwflags, /* Flags and attributes */ NULL); /* TemplateFile */ } else { + // ascii open bfd->fh = p_CreateFileA(win32_fname, dwaccess, /* Requested access */ 0, /* Shared mode */ @@ -441,14 +442,14 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) } else if (flags & O_WRONLY) { /* Open existing for write */ if (bfd->use_backup_api) { dwaccess = GENERIC_WRITE|WRITE_OWNER|WRITE_DAC; - dwflags = FILE_FLAG_BACKUP_SEMANTICS; + dwflags = FILE_FLAG_BACKUP_SEMANTICS; } else { dwaccess = GENERIC_WRITE; dwflags = 0; } - // unicode or ascii open for open existing write if (p_CreateFileW && p_MultiByteToWideChar) { + // unicode open for open existing write bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar, dwaccess, /* Requested access */ 0, /* Shared mode */ @@ -457,6 +458,7 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) dwflags, /* Flags and attributes */ NULL); /* TemplateFile */ } else { + // ascii open bfd->fh = p_CreateFileA(win32_fname, dwaccess, /* Requested access */ 0, /* Shared mode */ @@ -472,7 +474,8 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) } else { /* Read */ if (bfd->use_backup_api) { dwaccess = GENERIC_READ|READ_CONTROL|ACCESS_SYSTEM_SECURITY; - dwflags = FILE_FLAG_BACKUP_SEMANTICS; + dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN | + FILE_FLAG_OPEN_REPARSE_POINT; dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE; } else { dwaccess = GENERIC_READ; @@ -480,8 +483,8 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) dwshare = FILE_SHARE_READ|FILE_SHARE_WRITE; } - // unicode or ascii open for open existing read if (p_CreateFileW && p_MultiByteToWideChar) { + // unicode open for open existing read bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar, dwaccess, /* Requested access */ dwshare, /* Share modes */ @@ -490,6 +493,7 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode) dwflags, /* Flags and attributes */ NULL); /* TemplateFile */ } else { + // ascii open bfd->fh = p_CreateFileA(win32_fname, dwaccess, /* Requested access */ dwshare, /* Share modes */ diff --git a/bacula/src/findlib/bfile.h b/bacula/src/findlib/bfile.h index ffbb08270f..ed3f6c6d28 100644 --- a/bacula/src/findlib/bfile.h +++ b/bacula/src/findlib/bfile.h @@ -103,6 +103,7 @@ struct BFILE { Python_IO pio; /* Python I/O routines */ PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT win32DecompContext; /* context for decomposition of win32 backup streams */ int use_backup_decomp; /* set if using BackupRead Stream Decomposition */ + bool reparse_point; /* set if reparse point */ }; HANDLE bget_handle(BFILE *bfd); @@ -126,6 +127,7 @@ struct BFILE { Python_IO pio; /* Python I/O routines */ PROCESS_WIN32_BACKUPAPIBLOCK_CONTEXT win32DecompContext; /* context for decomposition of win32 backup streams */ int use_backup_decomp; /* set if using BackupRead Stream Decomposition */ + bool reparse_point; /* not used in Unix */ }; #endif diff --git a/bacula/src/findlib/create_file.c b/bacula/src/findlib/create_file.c index 05416ced82..12f7c487ba 100644 --- a/bacula/src/findlib/create_file.c +++ b/bacula/src/findlib/create_file.c @@ -78,6 +78,7 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) bool exists = false; struct stat mstatp; + bfd->reparse_point = false; if (is_win32_stream(attr->data_stream)) { set_win32_backup(bfd); } else { @@ -350,6 +351,9 @@ int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace) #endif } /* End inner switch */ + case FT_REPARSE: + bfd->reparse_point = true; + /* Fall through wanted */ case FT_DIRBEGIN: case FT_DIREND: Dmsg2(200, "Make dir mode=%o dir=%s\n", new_mode, attr->ofname); diff --git a/bacula/src/findlib/find.c b/bacula/src/findlib/find.c index dd1bbdabf4..0bffa6abe4 100644 --- a/bacula/src/findlib/find.c +++ b/bacula/src/findlib/find.c @@ -376,6 +376,7 @@ static int our_callback(FF_PKT *ff, void *hpkt, bool top_level) case FT_INVALIDFS: case FT_INVALIDDT: case FT_NOOPEN: + case FT_REPARSE: // return ff->callback(ff, hpkt, top_level); /* These items can be filtered */ diff --git a/bacula/src/findlib/find_one.c b/bacula/src/findlib/find_one.c index 81c892651e..723d45ccf7 100644 --- a/bacula/src/findlib/find_one.c +++ b/bacula/src/findlib/find_one.c @@ -511,6 +511,10 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, } else { ff_pkt->type = FT_DIRBEGIN; } + /* We have set st_rdev to 1 if it is a reparse point, otherwise 0 */ + if (have_win32_api() && ff_pkt->statp.st_rdev) { + ff_pkt->type = FT_REPARSE; + } /* * Note, we return the directory to the calling program (handle_file) * when we first see the directory (FT_DIRBEGIN. @@ -520,7 +524,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, * in the directory is seen (i.e. the FT_DIREND). */ rtn_stat = handle_file(ff_pkt, pkt, top_level); - if (rtn_stat < 1) { /* ignore or error status */ + if (rtn_stat < 1 || ff_pkt->type == FT_REPARSE) { /* ignore or error status */ free(link); return rtn_stat; } diff --git a/bacula/src/lib/bsock.c b/bacula/src/lib/bsock.c index 88841f322f..32a163acc8 100644 --- a/bacula/src/lib/bsock.c +++ b/bacula/src/lib/bsock.c @@ -802,7 +802,7 @@ void BSOCK::close() free_tls_connection(bsock->tls); bsock->tls = NULL; } - if (bsock->is_timed_out() || bsock->is_terminated()) { + if (bsock->is_timed_out()) { shutdown(bsock->m_fd, SHUT_RDWR); /* discard any pending I/O */ } socketClose(bsock->m_fd); /* normal close */ diff --git a/bacula/src/lib/tls.c b/bacula/src/lib/tls.c index dd3aba8438..1acb404e56 100644 --- a/bacula/src/lib/tls.c +++ b/bacula/src/lib/tls.c @@ -569,7 +569,7 @@ void tls_bsock_shutdown(BSOCK *bsock) int flags; /* Set socket blocking for shutdown */ - flags = bsock->set_blocking(); + bsock->set_blocking(); err = SSL_shutdown(bsock->tls->openssl); @@ -585,9 +585,6 @@ void tls_bsock_shutdown(BSOCK *bsock) openssl_post_errors(M_ERROR, _("TLS shutdown failure.")); break; } - - /* Restore saved flags */ - bsock->restore_blocking(flags); } /* Does all the manual labor for tls_bsock_readn() and tls_bsock_writen() */ diff --git a/bacula/src/version.h b/bacula/src/version.h index 9467de874d..6315fe8404 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -3,7 +3,7 @@ */ #undef VERSION -#define VERSION "2.1.21" +#define VERSION "2.1.22" #define BDATE "24 June 2007" #define LSMDATE "24Jun07" diff --git a/bacula/src/win32/compat/compat.cpp b/bacula/src/win32/compat/compat.cpp index 88918b4ba7..5f50e3fd11 100644 --- a/bacula/src/win32/compat/compat.cpp +++ b/bacula/src/win32/compat/compat.cpp @@ -603,7 +603,7 @@ statDir(const char *file, struct stat *sb) HANDLE h = INVALID_HANDLE_VALUE; - // use unicode or ascii + // use unicode if (p_FindFirstFileW) { POOLMEM* pwszBuf = get_pool_memory (PM_FNAME); make_win32_path_UTF8_2_wchar(&pwszBuf, file); @@ -617,8 +617,9 @@ statDir(const char *file, struct stat *sb) pftLastAccessTime = &info_w.ftLastAccessTime; pftLastWriteTime = &info_w.ftLastWriteTime; pftCreationTime = &info_w.ftCreationTime; - } - else if (p_FindFirstFileA) { + + // use ASCII + } else if (p_FindFirstFileA) { h = p_FindFirstFileA(file, &info_a); pdwFileAttributes = &info_a.dwFileAttributes; @@ -629,127 +630,135 @@ statDir(const char *file, struct stat *sb) pftCreationTime = &info_a.ftCreationTime; } - if (h == INVALID_HANDLE_VALUE) { - const char *err = errorString(); - Dmsg2(99, "FindFirstFile(%s):%s\n", file, err); - LocalFree((void *)err); - errno = b_errno_win32; - return -1; - } + if (h == INVALID_HANDLE_VALUE) { + const char *err = errorString(); + Dmsg2(99, "FindFirstFile(%s):%s\n", file, err); + LocalFree((void *)err); + errno = b_errno_win32; + return -1; + } - sb->st_mode = 0777; /* start with everything */ - if (*pdwFileAttributes & FILE_ATTRIBUTE_READONLY) - sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH); - if (*pdwFileAttributes & FILE_ATTRIBUTE_SYSTEM) - sb->st_mode &= ~S_IRWXO; /* remove everything for other */ - if (*pdwFileAttributes & FILE_ATTRIBUTE_HIDDEN) - sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */ - sb->st_mode |= S_IFDIR; - - sb->st_size = *pnFileSizeHigh; - sb->st_size <<= 32; - sb->st_size |= *pnFileSizeLow; - sb->st_blksize = 4096; - sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096; - - sb->st_atime = cvt_ftime_to_utime(*pftLastAccessTime); - sb->st_mtime = cvt_ftime_to_utime(*pftLastWriteTime); - sb->st_ctime = cvt_ftime_to_utime(*pftCreationTime); - FindClose(h); + sb->st_mode = 0777; /* start with everything */ + if (*pdwFileAttributes & FILE_ATTRIBUTE_READONLY) + sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH); + if (*pdwFileAttributes & FILE_ATTRIBUTE_SYSTEM) + sb->st_mode &= ~S_IRWXO; /* remove everything for other */ + if (*pdwFileAttributes & FILE_ATTRIBUTE_HIDDEN) + sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */ + sb->st_mode |= S_IFDIR; - return 0; + /* Use st_rdev to store reparse attribute */ + sb->st_rdev = (*pdwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0; + + + sb->st_size = *pnFileSizeHigh; + sb->st_size <<= 32; + sb->st_size |= *pnFileSizeLow; + sb->st_blksize = 4096; + sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096; + + sb->st_atime = cvt_ftime_to_utime(*pftLastAccessTime); + sb->st_mtime = cvt_ftime_to_utime(*pftLastWriteTime); + sb->st_ctime = cvt_ftime_to_utime(*pftCreationTime); + FindClose(h); + + return 0; } int fstat(int fd, struct stat *sb) { - BY_HANDLE_FILE_INFORMATION info; - char tmpbuf[1024]; + BY_HANDLE_FILE_INFORMATION info; + char tmpbuf[1024]; - if (!GetFileInformationByHandle((HANDLE)fd, &info)) { - const char *err = errorString(); - Dmsg2(99, "GetfileInformationByHandle(%s): %s\n", tmpbuf, err); - LocalFree((void *)err); - errno = b_errno_win32; - return -1; - } + if (!GetFileInformationByHandle((HANDLE)fd, &info)) { + const char *err = errorString(); + Dmsg2(99, "GetfileInformationByHandle(%s): %s\n", tmpbuf, err); + LocalFree((void *)err); + errno = b_errno_win32; + return -1; + } - sb->st_dev = info.dwVolumeSerialNumber; - sb->st_ino = info.nFileIndexHigh; - sb->st_ino <<= 32; - sb->st_ino |= info.nFileIndexLow; - sb->st_nlink = (short)info.nNumberOfLinks; - if (sb->st_nlink > 1) { - Dmsg1(99, "st_nlink=%d\n", sb->st_nlink); - } + sb->st_dev = info.dwVolumeSerialNumber; + sb->st_ino = info.nFileIndexHigh; + sb->st_ino <<= 32; + sb->st_ino |= info.nFileIndexLow; + sb->st_nlink = (short)info.nNumberOfLinks; + if (sb->st_nlink > 1) { + Dmsg1(99, "st_nlink=%d\n", sb->st_nlink); + } - sb->st_mode = 0777; /* start with everything */ - if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) - sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH); - if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) - sb->st_mode &= ~S_IRWXO; /* remove everything for other */ - if (info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) - sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */ - sb->st_mode |= S_IFREG; - - sb->st_size = info.nFileSizeHigh; - sb->st_size <<= 32; - sb->st_size |= info.nFileSizeLow; - sb->st_blksize = 4096; - sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096; - sb->st_atime = cvt_ftime_to_utime(info.ftLastAccessTime); - sb->st_mtime = cvt_ftime_to_utime(info.ftLastWriteTime); - sb->st_ctime = cvt_ftime_to_utime(info.ftCreationTime); + sb->st_mode = 0777; /* start with everything */ + if (info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) + sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH); + if (info.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) + sb->st_mode &= ~S_IRWXO; /* remove everything for other */ + if (info.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) + sb->st_mode |= S_ISVTX; /* use sticky bit -> hidden */ + sb->st_mode |= S_IFREG; + + /* Use st_rdev to store reparse attribute */ + sb->st_rdev = (info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0; + + sb->st_size = info.nFileSizeHigh; + sb->st_size <<= 32; + sb->st_size |= info.nFileSizeLow; + sb->st_blksize = 4096; + sb->st_blocks = (uint32_t)(sb->st_size + 4095)/4096; + sb->st_atime = cvt_ftime_to_utime(info.ftLastAccessTime); + sb->st_mtime = cvt_ftime_to_utime(info.ftLastWriteTime); + sb->st_ctime = cvt_ftime_to_utime(info.ftCreationTime); - return 0; + return 0; } static int stat2(const char *file, struct stat *sb) { - HANDLE h; - int rval = 0; - char tmpbuf[1024]; - conv_unix_to_win32_path(file, tmpbuf, 1024); + HANDLE h; + int rval = 0; + char tmpbuf[1024]; + conv_unix_to_win32_path(file, tmpbuf, 1024); - DWORD attr = (DWORD)-1; + DWORD attr = (DWORD)-1; - if (p_GetFileAttributesW) { + if (p_GetFileAttributesW) { POOLMEM* pwszBuf = get_pool_memory(PM_FNAME); make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf); attr = p_GetFileAttributesW((LPCWSTR) pwszBuf); free_pool_memory(pwszBuf); - } else if (p_GetFileAttributesA) { - attr = p_GetFileAttributesA(tmpbuf); - } + } else if (p_GetFileAttributesA) { + attr = p_GetFileAttributesA(tmpbuf); + } - if (attr == (DWORD)-1) { - const char *err = errorString(); - Dmsg2(99, "GetFileAttributes(%s): %s\n", tmpbuf, err); - LocalFree((void *)err); - errno = b_errno_win32; - return -1; - } + if (attr == (DWORD)-1) { + const char *err = errorString(); + Dmsg2(99, "GetFileAttributes(%s): %s\n", tmpbuf, err); + LocalFree((void *)err); + errno = b_errno_win32; + return -1; + } - if (attr & FILE_ATTRIBUTE_DIRECTORY) - return statDir(tmpbuf, sb); + if (attr & FILE_ATTRIBUTE_DIRECTORY) { + return statDir(tmpbuf, sb); + } - h = CreateFileA(tmpbuf, GENERIC_READ, - FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + h = CreateFileA(tmpbuf, GENERIC_READ, + FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (h == INVALID_HANDLE_VALUE) { - const char *err = errorString(); - Dmsg2(99, "Cannot open file for stat (%s):%s\n", tmpbuf, err); - LocalFree((void *)err); - errno = b_errno_win32; - return -1; - } + if (h == INVALID_HANDLE_VALUE) { + const char *err = errorString(); + Dmsg2(99, "Cannot open file for stat (%s):%s\n", tmpbuf, err); + LocalFree((void *)err); + errno = b_errno_win32; + return -1; + } - rval = fstat((int)h, sb); - CloseHandle(h); - - return rval; + rval = fstat((int)h, sb); + CloseHandle(h); + + return rval; } int @@ -803,6 +812,9 @@ stat(const char *file, struct stat *sb) sb->st_mode |= S_IFREG; } + /* Use st_rdev to store reparse attribute */ + sb->st_rdev = (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0; + sb->st_nlink = 1; sb->st_size = data.nFileSizeHigh; sb->st_size <<= 32; @@ -815,6 +827,12 @@ stat(const char *file, struct stat *sb) return 0; } +/* + * We write our own ftruncate because the one in the + * Microsoft library mrcrt.dll does not truncate + * files greater than 2GB. + * KES - May 2007 + */ int win32_ftruncate(int fd, int64_t length) { /* Set point we want to truncate file */ @@ -961,6 +979,7 @@ gettimeofday(struct timeval *tv, struct timezone *) { SYSTEMTIME now; FILETIME tmp; + GetSystemTime(&now); if (tv == NULL) { @@ -977,8 +996,8 @@ gettimeofday(struct timeval *tv, struct timezone *) _100nsec |= tmp.dwLowDateTime; _100nsec -= WIN32_FILETIME_ADJUST; - tv->tv_sec =(long) (_100nsec / 10000000); - tv->tv_usec = (long) ((_100nsec % 10000000)/10); + tv->tv_sec = (long)(_100nsec / 10000000); + tv->tv_usec = (long)((_100nsec % 10000000)/10); return 0; } diff --git a/bacula/technotes-2.1 b/bacula/technotes-2.1 index 808fe337db..6beafd1fd5 100644 --- a/bacula/technotes-2.1 +++ b/bacula/technotes-2.1 @@ -1,7 +1,16 @@ Technical notes on version 2.1 General: +Release 2.1.22 beta Win32 binaries only: 24Jun07 +kes Implement Windows reparse points -- similar to directories, but + we do not descend into it. This is a first cut. They seem to + be backed up, but restore is not yet tested. +kes Remove restore_blocking in tls code when shutting a socket to leave + it in blocking mode. Hopefully this will fix the encryption bug + reported by Frank Sweetser. +kes When opening a file for backup, tell the OS that we are going to + read it sequentially -- optimization. kes Change variable names in authenticate_director() to not conflict with member names in bat. Caused great confusion with compiler, but no warnings. @@ -17,9 +26,9 @@ kes Add Swedish sv.po file 21Jun07 kes Don't print clock skew message in FD if less than 3 seconds diff. kes Add a bit of VSS info to status client. -kes Make a gross first cut of Vista VSS, using Win2003 code. +kes Implement a first cut of Vista VSS, using Win2003 code. -Release: 2.1.18 beta +Release: 2.1.20 beta 20Jun07 kes Fixed bug #886 (multidrive autochanger: SD doesn't use drive with loaded tape but uses first drive). -- 2.39.5