*
*/
/*
- Copyright (C) 2002-2004 Kern Sibbald and John Walker
+ Copyright (C) 2002-2005 Kern Sibbald
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
#if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
+#include "../lib/winapi.h"
+
+
/* Forward referenced subroutines */
static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd);
void unix_name_to_win32(POOLMEM **win32_name, char *name);
/*=============================================================*/
/*
- * Return the data stream that will be used
+ * Return the data stream that will be used
*/
int select_data_stream(FF_PKT *ff_pkt)
{
}
-/*
- * Encode a stat structure into a base64 character string
+/*
+ * 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
* the case of a hard linked file that has no data. This
}
+/* Do casting according to unknown type to keep compiler happy */
+#if !HAVE_GCC & HAVE_SUN_OS
+#define plug(st, val) st = val /* brain damaged compiler */
+#else
+template <class T> void plug(T &st, uint64_t val)
+ { st = static_cast<T>(val); }
+#endif
+
/* Decode a stat packet from base64 characters */
-int decode_stat(char *buf, struct stat *statp, int32_t *LinkFI)
+int decode_stat(char *buf, struct stat *statp, int32_t *LinkFI)
{
char *p = buf;
int64_t val;
p += from_base64(&val, p);
- statp->st_dev = val;
- p++; /* skip space */
+ plug(statp->st_dev, val);
+ p++;
p += from_base64(&val, p);
- statp->st_ino = val;
+ plug(statp->st_ino, val);
p++;
p += from_base64(&val, p);
- statp->st_mode = val;
+ plug(statp->st_mode, val);
p++;
p += from_base64(&val, p);
- statp->st_nlink = val;
+ plug(statp->st_nlink, val);
p++;
p += from_base64(&val, p);
- statp->st_uid = val;
+ plug(statp->st_uid, val);
p++;
p += from_base64(&val, p);
- statp->st_gid = val;
+ plug(statp->st_gid, val);
p++;
p += from_base64(&val, p);
- statp->st_rdev = val;
+ plug(statp->st_rdev, val);
p++;
p += from_base64(&val, p);
- statp->st_size = val;
+ plug(statp->st_size, val);
p++;
#ifndef HAVE_MINGW
p += from_base64(&val, p);
- statp->st_blksize = val;
+ plug(statp->st_blksize, val);
p++;
p += from_base64(&val, p);
- statp->st_blocks = val;
+ plug(statp->st_blocks, val);
p++;
#else
p += from_base64(&val, p);
-// statp->st_blksize = val;
+// plug(statp->st_blksize, val);
p++;
p += from_base64(&val, p);
-// statp->st_blocks = val;
+// plug(statp->st_blocks, val);
p++;
#endif
p += from_base64(&val, p);
- statp->st_atime = val;
+ plug(statp->st_atime, val);
p++;
p += from_base64(&val, p);
- statp->st_mtime = val;
+ plug(statp->st_mtime, val);
p++;
p += from_base64(&val, p);
- statp->st_ctime = val;
+ plug(statp->st_ctime, val);
/* Optional FileIndex of hard linked file data */
if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) {
p++;
p += from_base64(&val, p);
#ifdef HAVE_CHFLAGS
- statp->st_flags = (uint32_t)val;
+ plug(statp->st_flags, val);
} else {
statp->st_flags = 0;
#endif
}
-
+
/* Look for data stream id */
if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) {
p++;
skip_nonspaces(&p); /* st_ino */
p++;
p += from_base64(&val, p);
- statp->st_mode = val; /* st_mode */
+ plug(statp->st_mode, val); /* st_mode */
p++;
skip_nonspaces(&p); /* st_nlink */
p++;
/*
* Set file modes, permissions and times
*
- * fname is the original filename
+ * fname is the original filename
* ofile is the output filename (may be in a different directory)
*
* Returns: true on success
*/
bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
{
- struct utimbuf ut;
+ struct utimbuf ut;
mode_t old_mask;
bool ok = true;
+ off_t fsize;
#if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
if (attr->stream == STREAM_UNIX_ATTRIBUTES_EX &&
set_win32_attributes(jcr, attr, ofd)) {
if (is_bopen(ofd)) {
- bclose(ofd);
+ bclose(ofd);
}
- pm_strcpy(&attr->ofname, "*none*");
+ pm_strcpy(attr->ofname, "*none*");
return true;
}
if (attr->data_stream == STREAM_WIN32_DATA ||
attr->data_stream == STREAM_WIN32_GZIP_DATA) {
if (is_bopen(ofd)) {
- bclose(ofd);
+ bclose(ofd);
}
- pm_strcpy(&attr->ofname, "*none*");
+ pm_strcpy(attr->ofname, "*none*");
return true;
}
/*
* If Windows stuff failed, e.g. attempt to restore Unix file
- * to Windows, simply fall through and we will do it the
+ * to Windows, simply fall through and we will do it the
* universal way.
*/
#endif
old_mask = umask(0);
if (is_bopen(ofd)) {
+ char ec1[50], ec2[50];
+ fsize = blseek(ofd, 0, SEEK_CUR);
bclose(ofd); /* first close file */
+ if (fsize > 0 && fsize != (off_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),
+ edit_uint64(fsize, ec2));
+ }
}
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) {
+ berrno be;
Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"),
- attr->ofname, strerror(errno));
+ attr->ofname, be.strerror());
ok = false;
}
} else {
if (chown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) {
+ berrno be;
Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"),
- attr->ofname, strerror(errno));
+ attr->ofname, be.strerror());
ok = false;
}
if (chmod(attr->ofname, attr->statp.st_mode) < 0) {
+ berrno be;
Jmsg2(jcr, M_ERROR, 0, _("Unable to set file modes %s: ERR=%s\n"),
- attr->ofname, strerror(errno));
+ attr->ofname, be.strerror());
ok = false;
}
* Reset file times.
*/
if (utime(attr->ofname, &ut) < 0) {
+ berrno be;
Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"),
- attr->ofname, strerror(errno));
+ attr->ofname, be.strerror());
ok = false;
}
#ifdef HAVE_CHFLAGS
* fail.
*/
if (chflags(attr->ofname, attr->statp.st_flags) < 0) {
+ berrno be;
Jmsg2(jcr, M_ERROR, 0, _("Unable to set file flags %s: ERR=%s\n"),
- attr->ofname, strerror(errno));
+ attr->ofname, be.strerror());
ok = false;
}
#endif
}
- pm_strcpy(&attr->ofname, "*none*");
+ pm_strcpy(attr->ofname, "*none*");
umask(old_mask);
return ok;
}
/*=============================================================*/
#if !defined(HAVE_CYGWIN) && !defined(HAVE_WIN32)
-
+
/*
* It is possible to piggyback additional data e.g. ACLs on
* the encode_stat() data by returning the extended attributes
*/
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.
+ */
+ char *p;
+ p = attribsEx;
+ if (ff_pkt->flags & FO_HFSPLUS) {
+ p += to_base64((uint64_t)(ff_pkt->hfsinfo.rsrclength), p);
+ }
+ *p = 0;
+#else
*attribsEx = 0; /* no extended attributes */
+#endif
return STREAM_UNIX_ATTRIBUTES;
}
attribsEx[0] = 0; /* no extended attributes */
- if (!p_GetFileAttributesEx) {
- return STREAM_UNIX_ATTRIBUTES;
+ // try unicode version
+ if (p_GetFileAttributesExW) {
+ unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname);
+
+ WCHAR szBuf[MAX_PATH_UNICODE];
+ UTF8_2_wchar(szBuf, ff_pkt->sys_fname, MAX_PATH_UNICODE);
+
+ if (!p_GetFileAttributesExW(szBuf, GetFileExInfoStandard,
+ (LPVOID)&atts)) {
+ win_error(jcr, "GetFileAttributesExW:", ff_pkt->sys_fname);
+ return STREAM_UNIX_ATTRIBUTES;
+ }
}
+ else {
+ if (!p_GetFileAttributesExA)
+ return STREAM_UNIX_ATTRIBUTES;
+
+ unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname);
- unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname);
- if (!p_GetFileAttributesEx(ff_pkt->sys_fname, GetFileExInfoStandard,
- (LPVOID)&atts)) {
- win_error(jcr, "GetFileAttributesEx:", ff_pkt->sys_fname);
- return STREAM_UNIX_ATTRIBUTES;
+ if (!p_GetFileAttributesExA(ff_pkt->sys_fname, GetFileExInfoStandard,
+ (LPVOID)&atts)) {
+ win_error(jcr, "GetFileAttributesExA:", ff_pkt->sys_fname);
+ return STREAM_UNIX_ATTRIBUTES;
+ }
}
p += to_base64((uint64_t)atts.dwFileAttributes, p);
/*
* Set Extended File Attributes for Win32
*
- * fname is the original filename
+ * fname is the original filename
* ofile is the output filename (may be in a different directory)
*
* Returns: true on success
ULARGE_INTEGER li;
POOLMEM *win32_ofile;
- if (!p_GetFileAttributesEx) {
+ // if we have neither ansi nor wchar version, we leave
+ if (!(p_SetFileAttributesW || p_SetFileAttributesA))
return false;
- }
if (!p || !*p) { /* we should have attributes */
Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", attr->ofname, ofd->fid);
}
p += from_base64(&val, p);
- atts.dwFileAttributes = val;
+ plug(atts.dwFileAttributes, val);
p++; /* skip space */
p += from_base64(&val, p);
li.QuadPart = val;
li.QuadPart = val;
atts.ftLastWriteTime.dwLowDateTime = li.LowPart;
atts.ftLastWriteTime.dwHighDateTime = li.HighPart;
- p++;
+ p++;
p += from_base64(&val, p);
- atts.nFileSizeHigh = val;
+ plug(atts.nFileSizeHigh, val);
p++;
p += from_base64(&val, p);
- atts.nFileSizeLow = val;
+ plug(atts.nFileSizeLow, val);
/* Convert to Windows path format */
win32_ofile = get_pool_memory(PM_FNAME);
}
Dmsg1(100, "SetFileAtts %s\n", attr->ofname);
- if (!(atts.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (!(atts.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ if (p_SetFileAttributesW) {
+ WCHAR szBuf[MAX_PATH_UNICODE];
+ UTF8_2_wchar(szBuf, win32_ofile, MAX_PATH_UNICODE);
+
+ if (!SetFileAttributesW(szBuf, atts.dwFileAttributes & SET_ATTRS)) {
+ win_error(jcr, "SetFileAttributesW:", win32_ofile);
+ }
+ }
+ else {
if (!SetFileAttributes(win32_ofile, atts.dwFileAttributes & SET_ATTRS)) {
- win_error(jcr, "SetFileAttributes:", win32_ofile);
+ win_error(jcr, "SetFileAttributesA:", win32_ofile);
+ }
}
}
free_pool_memory(win32_ofile);
/* Cygwin API definition */
-extern "C" void cygwin_conv_to_win32_path(const char *path, char *win32_path);
+extern "C" void cygwin_conv_to_win32_path(const char *path, char *win32_path, DWORD dwSize);
void unix_name_to_win32(POOLMEM **win32_name, char *name)
{
/* One extra byte should suffice, but we double it */
- *win32_name = check_pool_memory_size(*win32_name, 2*strlen(name)+1);
- cygwin_conv_to_win32_path(name, *win32_name);
+ /* add MAX_PATH bytes for VSS shadow copy name */
+ DWORD dwSize = 2*strlen(name)+MAX_PATH;
+ *win32_name = check_pool_memory_size(*win32_name, dwSize);
+ cygwin_conv_to_win32_path(name, *win32_name, dwSize);
}
#endif /* HAVE_CYGWIN */