X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Ffindlib%2Fattribs.c;h=abd971997dd63a7ae25000b763933c970c0a81f2;hb=10cfd798ced2d27f61ead2de6fe9b1bcc8e3468d;hp=0d6e7c2f69a6efd83b3e65a8824e53785fdcbacd;hpb=bcfc3499e3ed90d43bef43e4a60edabecb4b236f;p=bacula%2Fbacula diff --git a/bacula/src/findlib/attribs.c b/bacula/src/findlib/attribs.c index 0d6e7c2f69..abd971997d 100644 --- a/bacula/src/findlib/attribs.c +++ b/bacula/src/findlib/attribs.c @@ -1,31 +1,22 @@ /* - Bacula® - The Network Backup Solution - - Copyright (C) 2002-2011 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. - This program is Free Software; you can redistribute it and/or - modify it under the terms of version three of the GNU Affero General Public - License as published by the Free Software Foundation and included - in the file LICENSE. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. - - Bacula® is a registered trademark of Kern Sibbald. - The licensor of Bacula is the Free Software Foundation Europe - (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, - Switzerland, email:ftf@fsfeurope.org. + Bacula(R) - The Network Backup Solution + + Copyright (C) 2000-2017 Kern Sibbald + + The original author of Bacula is Kern Sibbald, with contributions + from many others, a complete list can be found in the file AUTHORS. + + You may use this file and others of this release according to the + license defined in the LICENSE file, which includes the Affero General + Public License, v3.0 ("AGPLv3") and some additional permissions and + terms pursuant to its AGPLv3 Section 7. + + This notice must be preserved when any source code is + conveyed and/or propagated. + + Bacula(R) is a registered trademark of Kern Sibbald. */ -/** +/* * Encode and decode standard Unix attributes and * Extended attributes for Win32 and * other non-Unix systems, or Unix systems with ACLs, ... @@ -34,27 +25,35 @@ * */ +//#define _POSIX_C_SOURCE 200809L +//#define _BSD_SOURCE 1 + #include "bacula.h" #include "find.h" #include "ch.h" static uid_t my_uid = 1; -static gid_t my_gid = 1; +static gid_t my_gid = 1; static bool uid_set = false; - -#if defined(HAVE_WIN32) -/* Forward referenced subroutines */ +#ifdef HAVE_WIN32 +/* Forward referenced Windows subroutines */ static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd); -void unix_name_to_win32(POOLMEM **win32_name, char *name); +void unix_name_to_win32(POOLMEM **win32_name, const char *name); +void win_error(JCR *jcr, int type, const char *prefix, POOLMEM *ofile); void win_error(JCR *jcr, const char *prefix, POOLMEM *ofile); HANDLE bget_handle(BFILE *bfd); #endif /* HAVE_WIN32 */ -/* For old systems that don't have lchown() use chown() */ +/* + * For old systems that don't have lchown() or lchmod() + */ #ifndef HAVE_LCHOWN #define lchown chown #endif +#ifndef HAVE_LCHMOD +#define lchmod chmod +#endif /*=============================================================*/ /* */ @@ -62,7 +61,125 @@ HANDLE bget_handle(BFILE *bfd); /* */ /*=============================================================*/ -/** +/* + * To turn off use of fchown(), fchmod(), or futimes(), + * uncomment one or more of the following. + */ +//#undef HAVE_FCHOWN +//#undef HAVE_FCHMOD +//#undef HAVE_FUTIMES + +/* + * Print errors only if debug level defined or we are root. + * root should not get errors. Errors for users causes + * too much output. + */ +#define print_error(jcr) (chk_dbglvl(100) || (my_uid == 0 && (!jcr || jcr->job_uid == 0))) + +/* + * Restore the owner and permissions (mode) of a Directory. + * See attribs.c for the equivalent for files. + */ +void set_own_mod(ATTR *attr, char *path, uid_t owner, gid_t group, mode_t mode) +{ + if (lchown(path, owner, group) != 0 && print_error(attr->jcr) +#ifdef AFS + && errno != EPERM +#endif + ) { + berrno be; + Jmsg4(attr->jcr, M_WARNING, 0, _("Cannot change owner and/or group of %s: ERR=%s %d %d\n"), + path, be.bstrerror(), getuid(), attr->jcr->job_uid); + } + if (lchmod(path, mode) != 0 && print_error(attr->jcr)) { + berrno be; + Jmsg2(attr->jcr, M_WARNING, 0, _("Cannot change permissions of %s: ERR=%s\n"), + path, be.bstrerror()); + } +} + + +bool set_mod_own_time(JCR *jcr, BFILE *ofd, ATTR *attr) +{ + bool ok = true; + struct utimbuf ut; + + /* Do not try to set rights with f functions when using a plugin */ + if (is_bopen(ofd) && !ofd->cmd_plugin) { /* TODO: Look with opt_plugin */ + /* + * The #ifdefing is a bit ugly, but it is the only + * way we can ensure this works on older systems. + */ +#ifdef HAVE_FCHOWN + if (fchown(ofd->fid, attr->statp.st_uid, attr->statp.st_gid) < 0 && print_error(jcr)) { +#else + if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0 && print_error(jcr)) { +#endif + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"), + attr->ofname, be.bstrerror()); + ok = false; + } + +#ifdef HAVE_FCHMOD + if (fchmod(ofd->fid, attr->statp.st_mode) < 0 && print_error(jcr)) { +#else + if (lchmod(attr->ofname, attr->statp.st_mode) < 0 && print_error(jcr)) { +#endif + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("Unable to set file modes %s: ERR=%s\n"), + attr->ofname, be.bstrerror()); + ok = false; + } + +#ifdef HAVE_FUTIMES + struct timeval times[2]; + times[0].tv_sec = attr->statp.st_atime; + times[0].tv_usec = 0; + times[1].tv_sec = attr->statp.st_mtime; + times[1].tv_usec = 0; + if (futimes(ofd->fid, times) < 0 && print_error(jcr)) { +#else + ut.actime = attr->statp.st_atime; + ut.modtime = attr->statp.st_mtime; + //bclose(ofd); + if (utime(attr->ofname, &ut) < 0 && print_error(jcr)) { +#endif + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"), + attr->ofname, be.bstrerror()); + ok = false; + } + } else { + if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0 && print_error(jcr)) { + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"), + attr->ofname, be.bstrerror()); + ok = false; + } + if (lchmod(attr->ofname, attr->statp.st_mode) < 0 && print_error(jcr)) { + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("Unable to set file modes %s: ERR=%s\n"), + attr->ofname, be.bstrerror()); + ok = false; + } + /* + * Reset file times. + */ + ut.actime = attr->statp.st_atime; + ut.modtime = attr->statp.st_mtime; + + if (utime(attr->ofname, &ut) < 0 && print_error(jcr)) { + berrno be; + Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"), + attr->ofname, be.bstrerror()); + ok = false; + } + } + return ok; +} + +/* * Return the data stream that will be used */ int select_data_stream(FF_PKT *ff_pkt) @@ -75,15 +192,15 @@ int select_data_stream(FF_PKT *ff_pkt) return STREAM_FILE_DATA; } - /** + /* * Fix all incompatible options */ - /** No sparse option for encrypted data */ + /* No sparse option for encrypted data */ if (ff_pkt->flags & FO_ENCRYPT) { ff_pkt->flags &= ~FO_SPARSE; } - /** Note, no sparse option for win32_data */ + /* Note, no sparse option for win32_data */ if (!is_portable_backup(&ff_pkt->bfd)) { stream = STREAM_WIN32_DATA; ff_pkt->flags &= ~FO_SPARSE; @@ -96,18 +213,18 @@ int select_data_stream(FF_PKT *ff_pkt) stream = STREAM_SPARSE_DATA; } - /** Encryption is only supported for file data */ + /* Encryption is only supported for file data */ if (stream != STREAM_FILE_DATA && stream != STREAM_WIN32_DATA && stream != STREAM_MACOS_FORK_DATA) { ff_pkt->flags &= ~FO_ENCRYPT; } - /** Compression is not supported for Mac fork data */ + /* Compression is not supported for Mac fork data */ if (stream == STREAM_MACOS_FORK_DATA) { ff_pkt->flags &= ~FO_COMPRESS; } - /** + /* * Handle compression and encryption options */ #if defined(HAVE_LIBZ) || defined(HAVE_LZO) @@ -125,7 +242,7 @@ int select_data_stream(FF_PKT *ff_pkt) stream = STREAM_GZIP_DATA; break; default: - /** + /* * All stream types that do not support compression should clear out * FO_COMPRESS above, and this code block should be unreachable. */ @@ -147,7 +264,7 @@ int select_data_stream(FF_PKT *ff_pkt) stream = STREAM_COMPRESSED_DATA; break; default: - /** + /* * All stream types that do not support compression should clear out * FO_COMPRESS above, and this code block should be unreachable. */ @@ -192,7 +309,7 @@ int select_data_stream(FF_PKT *ff_pkt) } -/** +/* * Encode a stat structure into a base64 character string * All systems must create such a structure. * In addition, we tack on the LinkFI, which is non-zero in @@ -206,52 +323,51 @@ int select_data_stream(FF_PKT *ff_pkt) void encode_stat(char *buf, struct stat *statp, int stat_size, int32_t LinkFI, int data_stream) { char *p = buf; - /* * We read the stat packet so make sure the caller's conception * is the same as ours. They can be different if LARGEFILE is not * the same when compiling this library and the calling program. */ ASSERT(stat_size == (int)sizeof(struct stat)); - - /** + + /* * Encode a stat packet. I should have done this more intelligently * with a length so that it could be easily expanded. */ - p += to_base64((int64_t)statp->st_dev, p); + p += to_base64((int64_t)statp->st_dev, p); *p++ = ' '; /* separate fields with a space */ - p += to_base64((int64_t)statp->st_ino, p); + p += to_base64((int64_t)statp->st_ino, p); *p++ = ' '; - p += to_base64((int64_t)statp->st_mode, p); + p += to_base64((int64_t)statp->st_mode, p); *p++ = ' '; - p += to_base64((int64_t)statp->st_nlink, p); + p += to_base64((int64_t)statp->st_nlink, p); *p++ = ' '; - p += to_base64((int64_t)statp->st_uid, p); + p += to_base64((int64_t)statp->st_uid, p); *p++ = ' '; - p += to_base64((int64_t)statp->st_gid, p); + p += to_base64((int64_t)statp->st_gid, p); *p++ = ' '; - p += to_base64((int64_t)statp->st_rdev, p); + p += to_base64((int64_t)statp->st_rdev, p); *p++ = ' '; - p += to_base64((int64_t)statp->st_size, p); + p += to_base64((int64_t)statp->st_size, p); *p++ = ' '; #ifndef HAVE_MINGW - p += to_base64((int64_t)statp->st_blksize, p); + p += to_base64((int64_t)statp->st_blksize, p); *p++ = ' '; - p += to_base64((int64_t)statp->st_blocks, p); + p += to_base64((int64_t)statp->st_blocks, p); *p++ = ' '; #else - p += to_base64((int64_t)0, p); /* output place holder */ + p += to_base64((int64_t)0, p); /* output place holder */ *p++ = ' '; - p += to_base64((int64_t)0, p); /* output place holder */ + p += to_base64((int64_t)0, p); /* output place holder */ *p++ = ' '; #endif - p += to_base64((int64_t)statp->st_atime, p); + p += to_base64((int64_t)statp->st_atime, p); *p++ = ' '; - p += to_base64((int64_t)statp->st_mtime, p); + p += to_base64((int64_t)statp->st_mtime, p); *p++ = ' '; p += to_base64((int64_t)statp->st_ctime, p); *p++ = ' '; - p += to_base64((int64_t)LinkFI, p); + p += to_base64((int64_t)LinkFI, p); *p++ = ' '; #ifdef HAVE_CHFLAGS @@ -262,11 +378,14 @@ void encode_stat(char *buf, struct stat *statp, int stat_size, int32_t LinkFI, i #endif *p++ = ' '; p += to_base64((int64_t)data_stream, p); +#ifdef HAVE_MINGW + *p++ = ' '; + p += to_base64((int64_t)statp->st_fattrs, p); +#endif *p = 0; return; } - /* Do casting according to unknown type to keep compiler happy */ #ifdef HAVE_TYPEOF #define plug(st, val) st = (typeof st)val @@ -284,11 +403,15 @@ void encode_stat(char *buf, struct stat *statp, int stat_size, int32_t LinkFI, i #endif -/** Decode a stat packet from base64 characters */ +/* + * Decode a stat packet from base64 characters + * returns: data_stream + */ int decode_stat(char *buf, struct stat *statp, int stat_size, int32_t *LinkFI) { char *p = buf; int64_t val; + int data_stream; /* * We store into the stat packet so make sure the caller's conception @@ -373,10 +496,21 @@ int decode_stat(char *buf, struct stat *statp, int stat_size, int32_t *LinkFI) } else { val = 0; } - return (int)val; + data_stream = val; +#ifdef HAVE_MINGW + if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) { + p++; + p += from_base64(&val, p); + plug(statp->st_fattrs, val); + } else { + statp->st_fattrs = 0; + val = 0; + } +#endif + return data_stream; } -/** Decode a LinkFI field of encoded stat packet */ +/* Decode a LinkFI field of encoded stat packet */ int32_t decode_LinkFI(char *buf, struct stat *statp, int stat_size) { char *p = buf; @@ -424,7 +558,7 @@ int32_t decode_LinkFI(char *buf, struct stat *statp, int stat_size) return 0; } -/** +/* * Set file modes, permissions and times * * fname is the original filename @@ -435,18 +569,17 @@ int32_t decode_LinkFI(char *buf, struct stat *statp, int stat_size) */ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) { - struct utimbuf ut; mode_t old_mask; bool ok = true; boffset_t fsize; - - if (uid_set) { + + if (!uid_set) { my_uid = getuid(); my_gid = getgid(); uid_set = true; } -#if defined(HAVE_WIN32) +#ifdef HAVE_WIN32 if (attr->stream == STREAM_UNIX_ATTRIBUTES_EX && set_win32_attributes(jcr, attr, ofd)) { if (is_bopen(ofd)) { @@ -465,20 +598,18 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) return true; } - - /** + /* * If Windows stuff failed, e.g. attempt to restore Unix file * to Windows, simply fall through and we will do it the * universal way. */ -#endif +#endif /* HAVE_WIN32 */ old_mask = umask(0); if (is_bopen(ofd)) { char ec1[50], ec2[50]; fsize = blseek(ofd, 0, SEEK_END); - bclose(ofd); /* first close file */ - if (attr->type == FT_REG && fsize > 0 && attr->statp.st_size > 0 && + if (attr->type == FT_REG && fsize > 0 && attr->statp.st_size > 0 && fsize != (boffset_t)attr->statp.st_size) { Jmsg3(jcr, M_ERROR, 0, _("File size of restored file %s not correct. Original %s, restored %s.\n"), attr->ofname, edit_uint64(attr->statp.st_size, ec1), @@ -486,7 +617,7 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) } } - /** + /* * We do not restore sockets, so skip trying to restore their * attributes. */ @@ -494,54 +625,49 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) goto bail_out; } - ut.actime = attr->statp.st_atime; - ut.modtime = attr->statp.st_mtime; - /* ***FIXME**** optimize -- don't do if already correct */ - /** + /* * For link, change owner of link using lchown, but don't * try to do a chmod as that will update the file behind it. */ if (attr->type == FT_LNK) { - /** Change owner of link, not of real file */ - if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0 && my_uid == 0) { +#ifdef HAVE_LCHOWN + /* Change owner of link, not of real file */ + if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0 && print_error(jcr)) { berrno be; Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"), attr->ofname, be.bstrerror()); ok = false; } - } else { - if (chown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0 && my_uid == 0) { - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"), - attr->ofname, be.bstrerror()); - ok = false; - } - if (chmod(attr->ofname, attr->statp.st_mode) < 0 && my_uid == 0) { - berrno be; - Jmsg2(jcr, M_ERROR, 0, _("Unable to set file modes %s: ERR=%s\n"), - attr->ofname, be.bstrerror()); - ok = false; - } - - /** - * Reset file times. - */ - if (utime(attr->ofname, &ut) < 0 && my_uid == 0) { +#endif +#ifdef HAVE_LUTIMES + struct timeval times[2]; + times[0].tv_sec = attr->statp.st_atime; + times[0].tv_usec = 0; + times[1].tv_sec = attr->statp.st_mtime; + times[1].tv_usec = 0; + if (lutimes(attr->ofname, times) < 0 && print_error(jcr)) { berrno be; Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"), attr->ofname, be.bstrerror()); ok = false; } +#endif + } else { + /* + * At this point, we have a file that is not a LINK + */ + ok = set_mod_own_time(jcr, ofd, attr); + #ifdef HAVE_CHFLAGS - /** + /* * FreeBSD user flags * * Note, this should really be done before the utime() above, * but if the immutable bit is set, it will make the utimes() * fail. */ - if (chflags(attr->ofname, attr->statp.st_flags) < 0 && my_uid == 0) { + if (chflags(attr->ofname, attr->statp.st_flags) < 0 && print_error(jcr)) { berrno be; Jmsg2(jcr, M_ERROR, 0, _("Unable to set file flags %s: ERR=%s\n"), attr->ofname, be.bstrerror()); @@ -551,6 +677,9 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) } bail_out: + if (is_bopen(ofd)) { + bclose(ofd); + } pm_strcpy(attr->ofname, "*none*"); umask(old_mask); return ok; @@ -563,9 +692,9 @@ bail_out: /* */ /*=============================================================*/ -#if !defined(HAVE_WIN32) +#ifndef HAVE_WIN32 -/** +/* * It is possible to piggyback additional data e.g. ACLs on * the encode_stat() data by returning the extended attributes * here. They must be "self-contained" (i.e. you keep track @@ -577,7 +706,7 @@ bail_out: int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt) { #ifdef HAVE_DARWIN_OS - /** + /* * We save the Mac resource fork length so that on a * restore, we can be sure we put back the whole resource. */ @@ -608,7 +737,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt) /* */ /*=============================================================*/ -#if defined(HAVE_WIN32) +#ifdef HAVE_WIN32 int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt) { @@ -624,12 +753,12 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt) unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname); - /** try unicode version */ + /* try unicode version */ if (p_GetFileAttributesExW) { - POOLMEM* pwszBuf = get_pool_memory(PM_FNAME); + POOLMEM* pwszBuf = get_pool_memory(PM_FNAME); make_win32_path_UTF8_2_wchar(&pwszBuf, ff_pkt->fname); - BOOL b=p_GetFileAttributesExW((LPCWSTR)pwszBuf, GetFileExInfoStandard, + BOOL b=p_GetFileAttributesExW((LPCWSTR)pwszBuf, GetFileExInfoStandard, (LPVOID)&atts); free_pool_memory(pwszBuf); @@ -640,7 +769,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt) } else { if (!p_GetFileAttributesExA) - return STREAM_UNIX_ATTRIBUTES; + return STREAM_UNIX_ATTRIBUTES; if (!p_GetFileAttributesExA(ff_pkt->sys_fname, GetFileExInfoStandard, (LPVOID)&atts)) { @@ -670,7 +799,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt) return STREAM_UNIX_ATTRIBUTES_EX; } -/** Define attributes that are legal to set with SetFileAttributes() */ +/* Define attributes that are legal to set with SetFileAttributes() */ #define SET_ATTRS ( \ FILE_ATTRIBUTE_ARCHIVE| \ FILE_ATTRIBUTE_HIDDEN| \ @@ -681,8 +810,7 @@ int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt) FILE_ATTRIBUTE_SYSTEM| \ FILE_ATTRIBUTE_TEMPORARY) - -/** +/* * Set Extended File Attributes for Win32 * * fname is the original filename @@ -699,7 +827,7 @@ static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) ULARGE_INTEGER li; POOLMEM *win32_ofile; - /** if we have neither Win ansi nor wchar API, get out */ + /* if we have neither Win ansi nor wchar API, get out */ if (!(p_SetFileAttributesW || p_SetFileAttributesA)) { return false; } @@ -738,11 +866,11 @@ static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) p += from_base64(&val, p); plug(atts.nFileSizeLow, val); - /** Convert to Windows path format */ + /* Convert to Windows path format */ win32_ofile = get_pool_memory(PM_FNAME); unix_name_to_win32(&win32_ofile, attr->ofname); - /** At this point, we have reconstructed the WIN32_FILE_ATTRIBUTE_DATA pkt */ + /* At this point, we have reconstructed the WIN32_FILE_ATTRIBUTE_DATA pkt */ if (!is_bopen(ofd)) { Dmsg1(100, "File not open: %s\n", attr->ofname); @@ -755,26 +883,58 @@ static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) &atts.ftCreationTime, &atts.ftLastAccessTime, &atts.ftLastWriteTime)) { - win_error(jcr, "SetFileTime:", win32_ofile); + win_error(jcr, M_WARNING, "SetFileTime:", win32_ofile); + } + + /* + * Inform win32 api that the given file is a sparse file + */ + if (atts.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) { + DWORD bytesReturned; + + Dmsg1(100, "Set FILE_ATTRIBUTE_SPARSE_FILE on %s\n", attr->ofname); + if (!DeviceIoControl(bget_handle(ofd), FSCTL_SET_SPARSE, + NULL, 0, NULL, 0, &bytesReturned, NULL)) + { + /* Not sure we really want to have a Warning for such attribute */ + win_error(jcr, M_WARNING, "set SPARSE_FILE:", win32_ofile); + } + } + + /* + * Restore the file as compressed. + */ + if (atts.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) { + int fmt = COMPRESSION_FORMAT_DEFAULT; + DWORD bytesReturned; + + Dmsg1(100, "Set FILE_ATTRIBUTE_COMPRESSED on %s\n", attr->ofname); + if (!DeviceIoControl(bget_handle(ofd), FSCTL_SET_COMPRESSION, + &fmt, sizeof(fmt), NULL, 0, &bytesReturned, NULL)) + { + /* Not sure we really want to have a Warning for such attribute */ + win_error(jcr, M_WARNING, "set COMPRESSED:", win32_ofile); + } } + bclose(ofd); } Dmsg1(100, "SetFileAtts %s\n", attr->ofname); if (!(atts.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { if (p_SetFileAttributesW) { - POOLMEM* pwszBuf = get_pool_memory(PM_FNAME); + POOLMEM* pwszBuf = get_pool_memory(PM_FNAME); make_win32_path_UTF8_2_wchar(&pwszBuf, attr->ofname); BOOL b=p_SetFileAttributesW((LPCWSTR)pwszBuf, atts.dwFileAttributes & SET_ATTRS); free_pool_memory(pwszBuf); - - if (!b) - win_error(jcr, "SetFileAttributesW:", win32_ofile); + + if (!b) + win_error(jcr, M_WARNING, "SetFileAttributesW:", win32_ofile); } else { if (!p_SetFileAttributesA(win32_ofile, atts.dwFileAttributes & SET_ATTRS)) { - win_error(jcr, "SetFileAttributesA:", win32_ofile); + win_error(jcr, M_WARNING, "SetFileAttributesA:", win32_ofile); } } } @@ -782,7 +942,7 @@ static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd) return true; } -void win_error(JCR *jcr, const char *prefix, POOLMEM *win32_ofile) +void win_error(JCR *jcr, int type, const char *prefix, POOLMEM *win32_ofile) { DWORD lerror = GetLastError(); LPTSTR msg; @@ -796,10 +956,15 @@ void win_error(JCR *jcr, const char *prefix, POOLMEM *win32_ofile) NULL); Dmsg3(100, "Error in %s on file %s: ERR=%s\n", prefix, win32_ofile, msg); strip_trailing_junk(msg); - Jmsg3(jcr, M_ERROR, 0, _("Error in %s file %s: ERR=%s\n"), prefix, win32_ofile, msg); + Jmsg3(jcr, type, 0, _("Error in %s file %s: ERR=%s\n"), prefix, win32_ofile, msg); LocalFree(msg); } +void win_error(JCR *jcr, const char *prefix, POOLMEM *win32_ofile) +{ + win_error(jcr, M_ERROR, prefix, win32_ofile); +} + void win_error(JCR *jcr, const char *prefix, DWORD lerror) { LPTSTR msg; @@ -814,9 +979,8 @@ void win_error(JCR *jcr, const char *prefix, DWORD lerror) strip_trailing_junk(msg); if (jcr) { Jmsg2(jcr, M_ERROR, 0, _("Error in %s: ERR=%s\n"), prefix, msg); - } else { MessageBox(NULL, msg, prefix, MB_OK); } LocalFree(msg); } -#endif /* HAVE_WIN32 */ +#endif /* HAVE_WIN32 */