#include "jcr.h"
#ifdef HAVE_CYGWIN
-#include <windows.h>
/* Forward referenced subroutines */
static
int set_win32_attributes(void *jcr, char *fname, char *ofile, char *lname,
int type, int stream, struct stat *statp,
- char *attribsEx, int *ofd);
+ char *attribsEx, BFILE *ofd);
void unix_name_to_win32(POOLMEM **win32_name, char *name);
-extern "C" HANDLE get_osfhandle(int fd);
void win_error(void *jcr, char *prefix, POOLMEM *ofile);
+HANDLE bget_handle(BFILE *bfd);
#endif
+/* For old systems that don't have lchown() use chown() */
+#ifndef HAVE_LCHOWN
+#define lchown chown
+#endif
/*=============================================================*/
/* */
/* Encode a stat structure into a base64 character string */
-void encode_stat(char *buf, struct stat *statp)
+void encode_stat(char *buf, struct stat *statp, uint32_t LinkFI)
{
char *p = buf;
/*
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);
+
+/* FreeBSD function */
+#ifdef HAVE_CHFLAGS
+ *p++ = ' ';
+ p += to_base64((int64_t)statp->st_flags, p);
+#endif
*p = 0;
return;
}
/* Decode a stat packet from base64 characters */
void
-decode_stat(char *buf, struct stat *statp)
+decode_stat(char *buf, struct stat *statp, uint32_t *LinkFI)
{
char *p = buf;
int64_t val;
p++;
p += from_base64(&val, p);
statp->st_ctime = val;
+ /* Optional FileIndex of hard linked file data */
+ if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) {
+ p++;
+ p += from_base64(&val, p);
+ *LinkFI = (uint32_t)val;
+ } else {
+ *LinkFI = 0;
+ }
+
+/* FreeBSD user flags */
+#ifdef HAVE_CHFLAGS
+ if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) {
+ p++;
+ p += from_base64(&val, p);
+ statp->st_flags = (uint32_t)val;
+ } else {
+ statp->st_flags = 0;
+ }
+#endif
}
/*
*/
int set_attributes(void *jcr, char *fname, char *ofile, char *lname,
int type, int stream, struct stat *statp,
- char *attribsEx, int *ofd)
+ char *attribsEx, BFILE *ofd)
{
struct utimbuf ut;
+ mode_t old_mask;
+ int stat = 1;
#ifdef HAVE_CYGWIN
if (set_win32_attributes(jcr, fname, ofile, lname, type, stream,
*/
#endif
- if (*ofd != -1) {
- close(*ofd); /* first close file */
- *ofd = -1;
+ old_mask = umask(0);
+ if (is_bopen(ofd)) {
+ bclose(ofd); /* first close file */
}
ut.actime = statp->st_atime;
ut.modtime = 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 (type == FT_LNK) {
+ /* Change owner of link, not of real file */
if (lchown(ofile, statp->st_uid, statp->st_gid) < 0) {
- Jmsg2(jcr, M_ERROR, 0, "Unable to set file owner %s: ERR=%s\n",
+ Jmsg2(jcr, M_WARNING, 0, "Unable to set file owner %s: ERR=%s\n",
ofile, strerror(errno));
- return 0;
+ stat = 0;
}
} else {
if (chown(ofile, statp->st_uid, statp->st_gid) < 0) {
- Jmsg2(jcr, M_ERROR, 0, "Unable to set file owner %s: ERR=%s\n",
+ Jmsg2(jcr, M_WARNING, 0, "Unable to set file owner %s: ERR=%s\n",
ofile, strerror(errno));
- return 0;
+ stat = 0;
+ }
+ if (chmod(ofile, statp->st_mode) < 0) {
+ Jmsg2(jcr, M_WARNING, 0, "Unable to set file modes %s: ERR=%s\n",
+ ofile, strerror(errno));
+ stat = 0;
}
- }
- if (chmod(ofile, statp->st_mode) < 0) {
- Jmsg2(jcr, M_ERROR, 0, "Unable to set file modes %s: ERR=%s\n",
- ofile, strerror(errno));
- return 0;
- }
- /*
- * Update file times.
- */
- if (utime(ofile, &ut) < 0) {
- Jmsg2(jcr, M_ERROR, 0, "Unable to set file times %s: ERR=%s\n",
- ofile, strerror(errno));
- return 0;
+ /* FreeBSD user flags */
+#ifdef HAVE_CHFLAGS
+ if (chflags(ofile, statp->st_flags) < 0) {
+ Jmsg2(jcr, M_WARNING, 0, "Unable to set file flags %s: ERR=%s\n",
+ ofile, strerror(errno));
+ stat = 0;
+ }
+#endif
+ /*
+ * Reset file times.
+ */
+ if (utime(ofile, &ut) < 0) {
+ Jmsg2(jcr, M_ERROR, 0, "Unable to set file times %s: ERR=%s\n",
+ ofile, strerror(errno));
+ stat = 0;
+ }
}
- return 1;
+ umask(old_mask);
+ return stat;
}
return STREAM_UNIX_ATTRIBUTES;
}
+void SetServicePrivileges(void *jcr)
+ { }
+
+
#endif
#ifdef HAVE_CYGWIN
+int NoGetFileAttributesEx = 0;
+
int encode_attribsEx(void *jcr, char *attribsEx, FF_PKT *ff_pkt)
{
char *p = attribsEx;
attribsEx[0] = 0; /* no extended attributes */
+ if (NoGetFileAttributesEx) {
+ return STREAM_UNIX_ATTRIBUTES;
+ }
+
unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname);
if (!GetFileAttributesEx(ff_pkt->sys_fname, GetFileExInfoStandard,
(LPVOID)&atts)) {
static
int set_win32_attributes(void *jcr, char *fname, char *ofile, char *lname,
int type, int stream, struct stat *statp,
- char *attribsEx, int *ofd)
+ char *attribsEx, BFILE *ofd)
{
char *p = attribsEx;
int64_t val;
WIN32_FILE_ATTRIBUTE_DATA atts;
ULARGE_INTEGER li;
- int fid, stat;
+ int stat;
POOLMEM *win32_ofile;
if (!p || !*p) { /* we should have attributes */
- Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", ofile, *ofd);
- if (*ofd != -1) {
- close(*ofd);
- *ofd = -1;
+ Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", ofile, ofd->fid);
+ if (is_bopen(ofd)) {
+ bclose(ofd);
}
return 0;
} else {
win32_ofile = get_pool_memory(PM_FNAME);
unix_name_to_win32(&win32_ofile, ofile);
- if (*ofd == -1) {
+ if (!is_bopen(ofd)) {
Dmsg1(100, "File not open: %s\n", ofile);
- fid = open(ofile, O_RDWR|O_BINARY); /* attempt to open the file */
- if (fid >= 0) {
- *ofd = fid;
- }
+ bopen(ofd, ofile, O_WRONLY|O_BINARY, 0); /* attempt to open the file */
}
- if (*ofd != -1) {
+ if (is_bopen(ofd)) {
Dmsg1(100, "SetFileTime %s\n", ofile);
- stat = SetFileTime(get_osfhandle(*ofd),
+ stat = SetFileTime(bget_handle(ofd),
&atts.ftCreationTime,
&atts.ftLastAccessTime,
&atts.ftLastWriteTime);
if (stat != 1) {
win_error(jcr, "SetFileTime:", win32_ofile);
}
- close(*ofd);
- *ofd = -1;
+ bclose(ofd);
}
Dmsg1(100, "SetFileAtts %s\n", ofile);
0,
NULL);
Dmsg3(100, "Error in %s on file %s: ERR=%s\n", prefix, win32_ofile, msg);
+ strip_trailing_junk(msg);
Jmsg3(jcr, M_INFO, 0, _("Error in %s file %s: ERR=%s\n"), prefix, win32_ofile, msg);
LocalFree(msg);
}
+void win_error(void *vjcr, char *prefix, DWORD lerror)
+{
+ JCR *jcr = (JCR *)vjcr;
+ LPTSTR msg;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ lerror,
+ 0,
+ (LPTSTR)&msg,
+ 0,
+ NULL);
+ strip_trailing_junk(msg);
+ Jmsg2(jcr, M_INFO, 0, _("Error in %s: ERR=%s\n"), prefix, msg);
+ LocalFree(msg);
+}
+
+
/* Cygwin API definition */
extern "C" void cygwin_conv_to_win32_path(const char *path, char *win32_path);
cygwin_conv_to_win32_path(name, *win32_name);
}
+/*
+ * Setup privileges we think we will need. We probably do not need
+ * the SE_SECURITY_NAME, but since nothing seems to be working,
+ * we get it hoping to fix the problems.
+ */
+void SetServicePrivileges(void *jcr)
+{
+ HANDLE hToken;
+ TOKEN_PRIVILEGES tkp, tkpPrevious;
+ DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES);
+ DWORD lerror;
+ // Get a token for this process.
+ if (!OpenProcessToken(GetCurrentProcess(),
+ TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
+ win_error(jcr, "OpenProcessToken", GetLastError());
+ /* Forge on anyway */
+ }
+
+#ifdef xxx
+ // Get the LUID for the security privilege.
+ if (!LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tkp.Privileges[0].Luid)) {
+ win_error(jcr, "LookupPrivilegeValue", GetLastError());
+ }
+
+ tkp.PrivilegeCount = 1;
+ tkp.Privileges[0].Attributes = 0;
+ /* Get the privilege */
+ AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES),
+ &tkpPrevious, &cbPrevious);
+ lerror = GetLastError();
+ if (lerror != ERROR_SUCCESS) {
+ win_error(jcr, "AdjustTokenPrivileges get SECURITY_NAME", lerror);
+ }
+
+ tkpPrevious.PrivilegeCount = 1;
+ tkpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
+
+ /* Set the security privilege for this process. */
+ AdjustTokenPrivileges(hToken, FALSE, &tkpPrevious, sizeof(TOKEN_PRIVILEGES),
+ (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL);
+ lerror = GetLastError();
+ if (lerror != ERROR_SUCCESS) {
+ win_error(jcr, "AdjustTokenPrivileges set SECURITY_NAME", lerror);
+ }
+#endif
+
+ // Get the LUID for the backup privilege.
+ if (!LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &tkp.Privileges[0].Luid)) {
+ win_error(jcr, "LookupPrivilegeValue", GetLastError());
+ }
+
+ tkp.PrivilegeCount = 1;
+ tkp.Privileges[0].Attributes = 0;
+ /* Get the current privilege */
+ AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES),
+ &tkpPrevious, &cbPrevious);
+ lerror = GetLastError();
+ if (lerror != ERROR_SUCCESS) {
+ win_error(jcr, "AdjustTokenPrivileges get BACKUP_NAME", lerror);
+ }
+
+ tkpPrevious.PrivilegeCount = 1;
+ tkpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
+
+ /* Set the backup privilege for this process. */
+ AdjustTokenPrivileges(hToken, FALSE, &tkpPrevious, sizeof(TOKEN_PRIVILEGES),
+ (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL);
+ lerror = GetLastError();
+ if (lerror != ERROR_SUCCESS) {
+ win_error(jcr, "AdjustTokenPrivileges set BACKUP_NAME", lerror);
+ }
+
+ // Get the LUID for the restore privilege.
+ if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tkp.Privileges[0].Luid)) {
+ win_error(jcr, "LookupPrivilegeValue", GetLastError());
+ }
+
+ tkp.PrivilegeCount = 1;
+ tkp.Privileges[0].Attributes = 0;
+ /* Get the privilege */
+ AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(TOKEN_PRIVILEGES),
+ &tkpPrevious, &cbPrevious);
+ lerror = GetLastError();
+ if (lerror != ERROR_SUCCESS) {
+ win_error(jcr, "AdjustTokenPrivileges get RESTORE_NAME", lerror);
+ }
+
+ tkpPrevious.PrivilegeCount = 1;
+ tkpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED);
+
+ /* Set the security privilege for this process. */
+ AdjustTokenPrivileges(hToken, FALSE, &tkpPrevious, sizeof(TOKEN_PRIVILEGES),
+ (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL);
+ lerror = GetLastError();
+ if (lerror != ERROR_SUCCESS) {
+ win_error(jcr, "AdjustTokenPrivileges set RESTORE_NAME", lerror);
+ }
+ CloseHandle(hToken);
+}
+
+// MessageBox(NULL, "Get restore priv failed: AdjustTokePrivileges", "restore", MB_OK);
+
#endif /* HAVE_CYGWIN */