Пример #1
0
int win32_utime(const char *fname, struct utimbuf *times)
{
	FILETIME acc;
	FILETIME mod;
	char tmpbuf[5000];

	conv_unix_to_win32_path(fname, tmpbuf, 5000);

	cvt_utime_to_ftime(times->actime, acc);
	cvt_utime_to_ftime(times->modtime, mod);

	HANDLE h=INVALID_HANDLE_VALUE;

	if(p_CreateFileW)
	{
		char* pwszBuf=sm_get_pool_memory(PM_FNAME);
		make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf);

		h=p_CreateFileW((LPCWSTR)pwszBuf,
				FILE_WRITE_ATTRIBUTES,
				FILE_SHARE_WRITE
				|FILE_SHARE_READ
				|FILE_SHARE_DELETE,
				NULL,
				OPEN_EXISTING,
				// required for directories
				FILE_FLAG_BACKUP_SEMANTICS,
				NULL);

		sm_free_pool_memory(pwszBuf);
	}
	else if(p_CreateFileA)
	{
		h=p_CreateFileA(tmpbuf,
				FILE_WRITE_ATTRIBUTES,
				FILE_SHARE_WRITE
				|FILE_SHARE_READ
				|FILE_SHARE_DELETE,
				NULL,
				OPEN_EXISTING,
				// required for directories
				FILE_FLAG_BACKUP_SEMANTICS,
				NULL);
	}

	if(h==INVALID_HANDLE_VALUE)
	{
		const char *err=errorString();
		fprintf(stderr, "Cannot open %s for utime(): ERR=%s\n",
			tmpbuf, err);
		LocalFree((void *)err);
		errno=b_errno_win32;
		return -1;
	}

	int rval=SetFileTime(h, NULL, &acc, &mod)?0:-1;
	CloseHandle(h);
	if(rval==-1) errno=b_errno_win32;
	return rval;
}
Пример #2
0
static int win32_chmod_new(const char *path, int64_t winattr)
{
	//if(winattr & FILE_ATTRIBUTE_ENCRYPTED)
	//	printf("\n   %s was encrypted!\n", path);
	DWORD attr=(DWORD)-1;

	if(p_GetFileAttributesW)
	{
		char *pwszBuf=sm_get_pool_memory(PM_FNAME);
		make_win32_path_UTF8_2_wchar(&pwszBuf, path);

		attr=p_GetFileAttributesW((LPCWSTR) pwszBuf);
		if(attr!=INVALID_FILE_ATTRIBUTES)
			attr=p_SetFileAttributesW((LPCWSTR)pwszBuf,
				winattr & SET_ATTRS);
		sm_free_pool_memory(pwszBuf);
	}
	else if(p_GetFileAttributesA)
	{
		attr=p_GetFileAttributesA(path);
		if(attr!=INVALID_FILE_ATTRIBUTES)
			winattr=p_SetFileAttributesA(path, attr & SET_ATTRS);
	}

	if(attr==(DWORD)-1)
	{
		const char *err=errorString();
		LocalFree((void *)err);
		errno=b_errno_win32;
		return -1;
	}
	return 0;
}
Пример #3
0
int win32_chdir(const char *dir)
{
	if(p_SetCurrentDirectoryW)
	{
		char *pwszBuf=sm_get_pool_memory(PM_FNAME);
		make_win32_path_UTF8_2_wchar(&pwszBuf, dir);

		BOOL b=p_SetCurrentDirectoryW((LPCWSTR)pwszBuf);

		sm_free_pool_memory(pwszBuf);

		if(!b)
		{
			errno=b_errno_win32;
			return -1;
		}
	}
	else if(p_SetCurrentDirectoryA)
	{
		if(!p_SetCurrentDirectoryA(dir))
		{
			errno=b_errno_win32;
			return -1;
		}
	}
	else
		return -1;

	return 0;
}
Пример #4
0
int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
{
   char *p = attribsEx;
   WIN32_FILE_ATTRIBUTE_DATA atts;
   ULARGE_INTEGER li;

   attribsEx[0] = 0;                  /* no extended attributes */

   if (jcr->cmd_plugin || ff_pkt->type == FT_DELETED) {
      return STREAM_UNIX_ATTRIBUTES;
   }

   unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname);

   /** try unicode version */
   if (p_GetFileAttributesExW)  {
      POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);   
      make_win32_path_UTF8_2_wchar(&pwszBuf, ff_pkt->fname);

      BOOL b=p_GetFileAttributesExW((LPCWSTR)pwszBuf, GetFileExInfoStandard, 
                                    (LPVOID)&atts);
      free_pool_memory(pwszBuf);

      if (!b) {
         win_error(jcr, "GetFileAttributesExW:", ff_pkt->sys_fname);
         return STREAM_UNIX_ATTRIBUTES;
      }
   }
   else {
      if (!p_GetFileAttributesExA)
         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);
   *p++ = ' ';                        /* separate fields with a space */
   li.LowPart = atts.ftCreationTime.dwLowDateTime;
   li.HighPart = atts.ftCreationTime.dwHighDateTime;
   p += to_base64((uint64_t)li.QuadPart, p);
   *p++ = ' ';
   li.LowPart = atts.ftLastAccessTime.dwLowDateTime;
   li.HighPart = atts.ftLastAccessTime.dwHighDateTime;
   p += to_base64((uint64_t)li.QuadPart, p);
   *p++ = ' ';
   li.LowPart = atts.ftLastWriteTime.dwLowDateTime;
   li.HighPart = atts.ftLastWriteTime.dwHighDateTime;
   p += to_base64((uint64_t)li.QuadPart, p);
   *p++ = ' ';
   p += to_base64((uint64_t)atts.nFileSizeHigh, p);
   *p++ = ' ';
   p += to_base64((uint64_t)atts.nFileSizeLow, p);
   *p = 0;
   return STREAM_UNIX_ATTRIBUTES_EX;
}
Пример #5
0
static int win32_chmod_old(const char *path, mode_t mode)
{
	DWORD attr=(DWORD)-1;

	if(p_GetFileAttributesW)
	{
		char *pwszBuf=sm_get_pool_memory(PM_FNAME);
		make_win32_path_UTF8_2_wchar(&pwszBuf, path);

		attr=p_GetFileAttributesW((LPCWSTR)pwszBuf);
		if(attr!=INVALID_FILE_ATTRIBUTES)
		{
			// Use Burp mappings defined in stat() above.
			if(!(mode & (S_IRUSR|S_IRGRP|S_IROTH)))
				attr |= FILE_ATTRIBUTE_READONLY;
			else
				attr &= ~FILE_ATTRIBUTE_READONLY;
			if(!(mode & S_IRWXO))
				attr |= FILE_ATTRIBUTE_SYSTEM;
			else
				attr &= ~FILE_ATTRIBUTE_SYSTEM;
			if(mode & S_ISVTX)
				attr |= FILE_ATTRIBUTE_HIDDEN;
			else
				attr &= ~FILE_ATTRIBUTE_HIDDEN;
			attr=p_SetFileAttributesW((LPCWSTR)pwszBuf, attr);
		}
		sm_free_pool_memory(pwszBuf);
	}
	else if (p_GetFileAttributesA)
	{
		if(!(mode & (S_IRUSR|S_IRGRP|S_IROTH)))
			attr |= FILE_ATTRIBUTE_READONLY;
		else
			attr &= ~FILE_ATTRIBUTE_READONLY;
		if(!(mode & S_IRWXO))
			attr |= FILE_ATTRIBUTE_SYSTEM;
		else
			attr &= ~FILE_ATTRIBUTE_SYSTEM;
		if(mode & S_ISVTX)
			attr |= FILE_ATTRIBUTE_HIDDEN;
		else
			attr &= ~FILE_ATTRIBUTE_HIDDEN;
		attr=p_GetFileAttributesA(path);
		if(attr!=INVALID_FILE_ATTRIBUTES)
			attr=p_SetFileAttributesA(path, attr);
	}

	if(attr==(DWORD)-1)
	{
		const char *err=errorString();
		LocalFree((void *)err);
		errno=b_errno_win32;
		return -1;
	}
	return 0;
}
Пример #6
0
static int stat2(const char *file, struct stat *sb, uint64_t *winattr)
{
	HANDLE h=INVALID_HANDLE_VALUE;
	int rval=0;
	char tmpbuf[5000];
	conv_unix_to_win32_path(file, tmpbuf, 5000);

	DWORD attr=(DWORD)-1;

	if(p_GetFileAttributesW)
	{
		char* pwszBuf=sm_get_pool_memory(PM_FNAME);
		make_win32_path_UTF8_2_wchar(&pwszBuf, tmpbuf);

		attr=p_GetFileAttributesW((LPCWSTR) pwszBuf);
		if(p_CreateFileW)
			h=CreateFileW((LPCWSTR)pwszBuf, GENERIC_READ,
				FILE_SHARE_READ,
				NULL, OPEN_EXISTING, 0, NULL);
		sm_free_pool_memory(pwszBuf);
	}
	else if(p_GetFileAttributesA)
	{
		attr=p_GetFileAttributesA(tmpbuf);
		h=CreateFileA(tmpbuf, GENERIC_READ,
			FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	}

	if(attr==(DWORD)-1)
	{
		const char *err=errorString();
		LocalFree((void *)err);
		if(h!=INVALID_HANDLE_VALUE) CloseHandle(h);
		errno=b_errno_win32;
		return -1;
	}

	if(h==INVALID_HANDLE_VALUE)
	{
		const char *err=errorString();
		LocalFree((void *)err);
		errno=b_errno_win32;
		return -1;
	}

	rval=do_fstat((intptr_t)h, sb, winattr);
	CloseHandle(h);

	if(attr & FILE_ATTRIBUTE_DIRECTORY && file[1]==':' && file[2])
		rval = statDir(file, sb, winattr);

	return rval;
}
Пример #7
0
int win32_mkdir(const char *dir)
{
	if(p_wmkdir)
	{
		char *pwszBuf=sm_get_pool_memory(PM_FNAME);
		make_win32_path_UTF8_2_wchar(&pwszBuf, dir);

		int n=p_wmkdir((LPCWSTR)pwszBuf);
		sm_free_pool_memory(pwszBuf);
		return n;
	}
	return _mkdir(dir);
}
Пример #8
0
char *make_win32_path_UTF8_2_wchar_w(const char *pszUTF)
{
	int size=0;
	char *ret=NULL;
	char *tmp=sm_get_pool_memory(PM_FNAME);

	size=make_win32_path_UTF8_2_wchar(&tmp, pszUTF);
	if(size>0)
	{
		ret=(char *)malloc(2*strlen(pszUTF)+MAX_PATH);
		//ret=(char *)malloc((size+1)*sizeof(WCHAR));
        	wcscpy((LPWSTR)ret, (LPWSTR)tmp);
	}
	sm_free_pool_memory(tmp);
	return ret;
}
Пример #9
0
/**
 * Set Extended File Attributes for Win32
 *
 *  fname is the original filename
 *  ofile is the output filename (may be in a different directory)
 *
 * Returns:  true  on success
 *           false on failure
 */
static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
{
   char *p = attr->attrEx;
   int64_t val;
   WIN32_FILE_ATTRIBUTE_DATA atts;
   ULARGE_INTEGER li;
   POOLMEM *win32_ofile;

   /** if we have neither Win ansi nor wchar API, get out */
   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);
      if (is_bopen(ofd)) {
         bclose(ofd);
      }
      return false;
   } else {
      Dmsg2(100, "Attribs %s = %s\n", attr->ofname, attr->attrEx);
   }

   p += from_base64(&val, p);
   plug(atts.dwFileAttributes, val);
   p++;                               /* skip space */
   p += from_base64(&val, p);
   li.QuadPart = val;
   atts.ftCreationTime.dwLowDateTime = li.LowPart;
   atts.ftCreationTime.dwHighDateTime = li.HighPart;
   p++;                               /* skip space */
   p += from_base64(&val, p);
   li.QuadPart = val;
   atts.ftLastAccessTime.dwLowDateTime = li.LowPart;
   atts.ftLastAccessTime.dwHighDateTime = li.HighPart;
   p++;                               /* skip space */
   p += from_base64(&val, p);
   li.QuadPart = val;
   atts.ftLastWriteTime.dwLowDateTime = li.LowPart;
   atts.ftLastWriteTime.dwHighDateTime = li.HighPart;
   p++;
   p += from_base64(&val, p);
   plug(atts.nFileSizeHigh, val);
   p++;
   p += from_base64(&val, p);
   plug(atts.nFileSizeLow, val);

   /** 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 */

   if (!is_bopen(ofd)) {
      Dmsg1(100, "File not open: %s\n", attr->ofname);
      bopen(ofd, attr->ofname, O_WRONLY|O_BINARY, 0);   /* attempt to open the file */
   }

   if (is_bopen(ofd)) {
      Dmsg1(100, "SetFileTime %s\n", attr->ofname);
      if (!SetFileTime(bget_handle(ofd),
                         &atts.ftCreationTime,
                         &atts.ftLastAccessTime,
                         &atts.ftLastWriteTime)) {
         win_error(jcr, "SetFileTime:", 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);   
         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); 
      }
      else {
         if (!p_SetFileAttributesA(win32_ofile, atts.dwFileAttributes & SET_ATTRS)) {
            win_error(jcr, "SetFileAttributesA:", win32_ofile);
         }
      }
   }
   free_pool_memory(win32_ofile);
   return true;
}
Пример #10
0
static int do_stat(const char *file, struct stat *sb, uint64_t *winattr)
{
	WIN32_FILE_ATTRIBUTE_DATA data;
	errno=0;

	memset(sb, 0, sizeof(*sb));
	memset(winattr, 0, sizeof(*winattr));

	if(p_GetFileAttributesExW)
	{
		// Dynamically allocate enough space for UCS2 filename.
		char *pwszBuf=sm_get_pool_memory(PM_FNAME);
		make_win32_path_UTF8_2_wchar(&pwszBuf, file);

		BOOL b=p_GetFileAttributesExW((LPCWSTR)pwszBuf,
			GetFileExInfoStandard, &data);
		sm_free_pool_memory(pwszBuf);

		if(!b) return stat2(file, sb, winattr);

	}
	else if(p_GetFileAttributesExA)
	{
		if(!p_GetFileAttributesExA(file, GetFileExInfoStandard, &data))
			return stat2(file, sb, winattr);
	}
	else
		return stat2(file, sb, winattr);

	*winattr=(int64_t)data.dwFileAttributes;

	/* Graham says: all the following stuff seems rather complicated.
	   It is probably not all needed anymore, since I have added *winattr
	   above, which bacula did not do.
	   One reason for keeping it is that some of the values get converted to
	   unix-style permissions that show up in the long list functionality.
	   I think I would prefer to remove it all though.
	 */
	sb->st_mode = 0777; // Start with everything.
	if(data.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
		sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH);
	if(data.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
		sb->st_mode &= ~S_IRWXO; // Remove everything for other.
	if(data.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
		sb->st_mode |= S_ISVTX; // use sticky bit -> hidden.
	if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		sb->st_mode |= S_IFDIR;
	else
		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;
	sb->st_size|=data.nFileSizeLow;
	sb->st_blksize=4096;
	sb->st_blocks=(uint32_t)(sb->st_size + 4095)/4096;
	sb->st_atime=cvt_ftime_to_utime(data.ftLastAccessTime);
	sb->st_mtime=cvt_ftime_to_utime(data.ftLastWriteTime);
	sb->st_ctime=cvt_ftime_to_utime(data.ftCreationTime);

	/* If we are not at the root, then to distinguish a reparse 
	   point from a mount point, we must call FindFirstFile() to
	   get the WIN32_FIND_DATA, which has the bit that indicates
	   that this directory is a mount point -- aren't Win32 APIs
	   wonderful? (sarcasm).  The code exists in the statDir
	   subroutine.  */
	if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
	  && file[1]==':' && file[2])
		statDir(file, sb, winattr);
	return 0;
}
Пример #11
0
static int statDir(const char *file, struct stat *sb, uint64_t *winattr)
{
	WIN32_FIND_DATAW info_w; // window's file info
	WIN32_FIND_DATAA info_a; // window's file info

	// cache some common vars to make code more transparent
	DWORD *pdwFileAttributes;
	DWORD *pnFileSizeHigh;
	DWORD *pnFileSizeLow;
	DWORD *pdwReserved0;
	FILETIME *pftLastAccessTime;
	FILETIME *pftLastWriteTime;
	FILETIME *pftCreationTime;

	/* Oh, cool, another exception: Microsoft doesn't let us do 
	   FindFile operations on a Drive, so simply fake root attibutes. */
	if(file[1]==':' && !file[2])
	{
		time_t now=time(NULL);
		sb->st_mode=S_IFDIR;
		sb->st_mode|=S_IREAD|S_IEXEC|S_IWRITE;
		sb->st_ctime=now;
		sb->st_mtime=now;
		sb->st_atime=now;
		sb->st_rdev=0;
		return 0;
	}

	HANDLE h=INVALID_HANDLE_VALUE;

	// use unicode
	if(p_FindFirstFileW)
	{
		char *pwszBuf=sm_get_pool_memory(PM_FNAME);
		make_win32_path_UTF8_2_wchar(&pwszBuf, file);

		h=p_FindFirstFileW((LPCWSTR)pwszBuf, &info_w);
		sm_free_pool_memory(pwszBuf);

		pdwFileAttributes=&info_w.dwFileAttributes;
		pdwReserved0     =&info_w.dwReserved0;
		pnFileSizeHigh   =&info_w.nFileSizeHigh;
		pnFileSizeLow    =&info_w.nFileSizeLow;
		pftLastAccessTime=&info_w.ftLastAccessTime;
		pftLastWriteTime =&info_w.ftLastWriteTime;
		pftCreationTime  =&info_w.ftCreationTime;
		// use ASCII
	}
	else if (p_FindFirstFileA)
	{
		h=p_FindFirstFileA(file, &info_a);

		pdwFileAttributes=&info_a.dwFileAttributes;
		pdwReserved0     =&info_a.dwReserved0;
		pnFileSizeHigh   =&info_a.nFileSizeHigh;
		pnFileSizeLow    =&info_a.nFileSizeLow;
		pftLastAccessTime=&info_a.ftLastAccessTime;
		pftLastWriteTime =&info_a.ftLastWriteTime;
		pftCreationTime  =&info_a.ftCreationTime;
	}

	if(h==INVALID_HANDLE_VALUE)
	{
		const char *err = errorString();
		/* Note, in creating leading paths, it is normal that
		   the file does not exist. */
		LocalFree((void *)err);
		errno=b_errno_win32;
		return -1;
	}
	else
		FindClose(h);

	*winattr=(int64_t)*pdwFileAttributes;

	/* Graham says: all the following stuff seems rather complicated.
	   It is probably not all needed anymore, since I have added *winattr
	   above, which bacula did not do.
	   One reason for keeping it is that some of the values get converted
	   to unix-style permissions that show up in the long list
	   functionality.
	   I think I would prefer to remove it all at some point. */

	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;

	/* Store reparse/mount point info in st_rdev.  Note a
	   Win32 reparse point (junction point) is like a link
	   though it can have many properties (directory link,
	   soft link, hard link, HSM, ...
	   A mount point is a reparse point where another volume
	   is mounted, so it is like a Unix mount point (change of
	   filesystem).  */
	if(*pdwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
		sb->st_rdev=WIN32_MOUNT_POINT;
	else
		sb->st_rdev=0;

	if((*pdwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
	  && (*pdwReserved0 & IO_REPARSE_TAG_MOUNT_POINT))
	{
		sb->st_rdev=WIN32_MOUNT_POINT;
		/* Now to find out if the directory is a mount point or
		   a reparse point, we must do a song and a dance.
		   Explicitly open the file to read the reparse point, then
		   call DeviceIoControl to find out if it points to a Volume
		   or to a directory. */
		h=INVALID_HANDLE_VALUE;
		if(p_GetFileAttributesW)
		{
			char *pwszBuf=sm_get_pool_memory(PM_FNAME);
			make_win32_path_UTF8_2_wchar(&pwszBuf, file);
			if(p_CreateFileW)
			{
				h=CreateFileW((LPCWSTR)pwszBuf, GENERIC_READ,
					FILE_SHARE_READ, NULL, OPEN_EXISTING,
					FILE_FLAG_BACKUP_SEMANTICS
					| FILE_FLAG_OPEN_REPARSE_POINT,
					NULL);
			}
			sm_free_pool_memory(pwszBuf);
		}
		else if(p_GetFileAttributesA)
		{
			h=CreateFileA(file, GENERIC_READ,
				FILE_SHARE_READ, NULL, OPEN_EXISTING,
				FILE_FLAG_BACKUP_SEMANTICS
				| FILE_FLAG_OPEN_REPARSE_POINT,
				NULL);
		}
		if(h!=INVALID_HANDLE_VALUE)
		{
			char dummy[1000];
			REPARSE_DATA_BUFFER *rdb=(REPARSE_DATA_BUFFER *)dummy;
			rdb->ReparseTag=IO_REPARSE_TAG_MOUNT_POINT;
			DWORD bytes;
			bool ok;
			ok=DeviceIoControl(h, FSCTL_GET_REPARSE_POINT,
				NULL, 0, // in buffer, bytes
				(LPVOID)rdb,
				(DWORD)sizeof(dummy), // out buffer, btyes
				(LPDWORD)&bytes, (LPOVERLAPPED)0);
			if(ok)
			{
				char *utf8=sm_get_pool_memory(PM_NAME);
				wchar_2_UTF8(utf8, (wchar_t *)
				  rdb->SymbolicLinkReparseBuffer.PathBuffer);
				if(!strncasecmp(utf8, "\\??\\volume{", 11))
					sb->st_rdev=WIN32_MOUNT_POINT;
				else // Points to a directory so we ignore it. 
					sb->st_rdev=WIN32_JUNCTION_POINT;
				sm_free_pool_memory(utf8);
			}
			CloseHandle(h);
		}
	}
	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);

	return 0;
}
Пример #12
0
int win32_unlink(const char *filename)
{
	int nRetCode;
	if(p_wunlink)
	{
		char* pwszBuf=sm_get_pool_memory(PM_FNAME);
		make_win32_path_UTF8_2_wchar(&pwszBuf, filename);

		nRetCode=_wunlink((LPCWSTR) pwszBuf);

		/* Special case if file is readonly,
		   we retry but unset attribute before. */
		if(nRetCode==-1
		  && errno==EACCES
		  && p_SetFileAttributesW
		  && p_GetFileAttributesW)
		{
			DWORD dwAttr=p_GetFileAttributesW((LPCWSTR)pwszBuf);
			if(dwAttr!=INVALID_FILE_ATTRIBUTES)
			{
				if(p_SetFileAttributesW((LPCWSTR)pwszBuf,
				  dwAttr & ~FILE_ATTRIBUTE_READONLY))
				{
					nRetCode=_wunlink((LPCWSTR) pwszBuf);
					// Reset to original if it didn't help.
					if(nRetCode==-1)
						p_SetFileAttributesW(
						  (LPCWSTR)pwszBuf, dwAttr);
				}
			}
		}
		sm_free_pool_memory(pwszBuf);
	}
	else
	{
		nRetCode=_unlink(filename);

		/* special case if file is readonly,
		   we retry but unset attribute before. */
		if(nRetCode==-1
		  && errno==EACCES
		  && p_SetFileAttributesA
		  && p_GetFileAttributesA)
		{
			DWORD dwAttr=p_GetFileAttributesA(filename);
			if(dwAttr!=INVALID_FILE_ATTRIBUTES)
			{
				if(p_SetFileAttributesA(filename,
				  dwAttr & ~FILE_ATTRIBUTE_READONLY))
				{
					nRetCode=_unlink(filename);
					// Reset to original if it didn't help.
					if(nRetCode==-1)
						p_SetFileAttributesA(
						  filename, dwAttr);
				}
			}
		}
	}
	return nRetCode;
}
Пример #13
0
DIR * opendir(const char *path)
{
	ssize_t len=0;
	char *tspec=NULL;

	// Enough space for VSS!
	int max_len=strlen(path)+MAX_PATH;
	_dir *rval=NULL;
	if(!path)
	{
		errno=ENOENT;
		return NULL;
	}

	if(!(rval=(_dir *)malloc(sizeof(_dir)))) return NULL;
	memset(rval, 0, sizeof (_dir));
	if(!(tspec=(char *)malloc(max_len)))
	{
		free(rval);
		return NULL;
	}

	conv_unix_to_win32_path(path, tspec, max_len);

	len=strlen(tspec);
	// Add backslash only if there is none yet (think of c:\).
	if(tspec[len-1] != '\\' && len+1<max_len)
	{
		tspec[len++]='\\';
		tspec[len]='\0';
	}
	if(len+1<max_len)
	{
		tspec[len++]='*';
		tspec[len]='\0';
	}

	rval->spec=tspec;

	// Convert to wchar_t.
	if(p_FindFirstFileW)
	{
		char *pwcBuf=sm_get_pool_memory(PM_FNAME);
		make_win32_path_UTF8_2_wchar(&pwcBuf, rval->spec);

		rval->dirh=p_FindFirstFileW((LPCWSTR)pwcBuf, &rval->data_w);

		sm_free_pool_memory(pwcBuf);

		if(rval->dirh!=INVALID_HANDLE_VALUE) rval->valid_w=1;
	}
	else if (p_FindFirstFileA)
	{
		rval->dirh=p_FindFirstFileA(rval->spec, &rval->data_a);

		if (rval->dirh!=INVALID_HANDLE_VALUE) rval->valid_a = 1;
	}
	else
		goto err;

	rval->offset=0;
	if(rval->dirh==INVALID_HANDLE_VALUE) goto err;

	if(rval->valid_w) { }

	if(rval->valid_a) { }

	return (DIR *)rval;

err:
	free((void *)rval->spec);
	free(rval);
	errno=b_errno_win32;
	return NULL;
}
Пример #14
0
Файл: bfile.c Проект: AlD/bareos
static inline int bopen_nonencrypted(BFILE *bfd, const char *fname, int flags, mode_t mode)
{
   POOLMEM *win32_fname;
   POOLMEM *win32_fname_wchar;
   DWORD dwaccess, dwflags, dwshare;

   /*
    * Convert to Windows path format
    */
   win32_fname = get_pool_memory(PM_FNAME);
   win32_fname_wchar = get_pool_memory(PM_FNAME);

   unix_name_to_win32(&win32_fname, (char *)fname);

   if (bfd->cmd_plugin && plugin_bopen) {
      int rtnstat;
      Dmsg1(50, "call plugin_bopen fname=%s\n", fname);
      rtnstat = plugin_bopen(bfd, fname, flags, mode);
      Dmsg1(50, "return from plugin_bopen status=%d\n", rtnstat);
      if (rtnstat >= 0) {
         if (flags & O_CREAT || flags & O_WRONLY) {   /* Open existing for write */
            Dmsg1(50, "plugin_open for write OK file=%s.\n", fname);
            bfd->mode = BF_WRITE;
         } else {
            Dmsg1(50, "plugin_open for read OK file=%s.\n", fname);
            bfd->mode = BF_READ;
         }
      } else {
         bfd->mode = BF_CLOSED;
         Dmsg1(000, "==== plugin_bopen returned bad status=%d\n", rtnstat);
      }
      free_pool_memory(win32_fname_wchar);
      free_pool_memory(win32_fname);
      return bfd->mode == BF_CLOSED ? -1 : 1;
   }
   Dmsg0(50, "=== NO plugin\n");

   if (!(p_CreateFileA || p_CreateFileW)) {
      Dmsg0(50, "No CreateFileA and no CreateFileW!!!!!\n");
      return 0;
   }

   if (p_CreateFileW && p_MultiByteToWideChar) {
      make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
   }

   if (flags & O_CREAT) {             /* Create */
      if (bfd->use_backup_api) {
         dwaccess = GENERIC_WRITE | FILE_ALL_ACCESS | WRITE_OWNER | WRITE_DAC | ACCESS_SYSTEM_SECURITY;
         dwflags = FILE_FLAG_BACKUP_SEMANTICS;
      } else {
         dwaccess = GENERIC_WRITE;
         dwflags = 0;
      }

      /*
       * Unicode open for create write
       */
      if (p_CreateFileW && p_MultiByteToWideChar) {
         Dmsg1(100, "Create CreateFileW=%s\n", win32_fname);
         bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
                                  dwaccess,      /* Requested access */
                                  0,             /* Shared mode */
                                  NULL,          /* SecurityAttributes */
                                  CREATE_ALWAYS, /* CreationDisposition */
                                  dwflags,       /* Flags and attributes */
                                  NULL);         /* TemplateFile */
      } else {
         /*
          * ASCII open
          */
         Dmsg1(100, "Create CreateFileA=%s\n", win32_fname);
         bfd->fh = p_CreateFileA(win32_fname,
                                 dwaccess,      /* Requested access */
                                 0,             /* Shared mode */
                                 NULL,          /* SecurityAttributes */
                                 CREATE_ALWAYS, /* CreationDisposition */
                                 dwflags,       /* Flags and attributes */
                                 NULL);         /* TemplateFile */
      }

      bfd->mode = BF_WRITE;
   } else if (flags & O_WRONLY) {
      /*
       * Open existing for write
       */
      if (bfd->use_backup_api) {
         dwaccess = GENERIC_WRITE | WRITE_OWNER | WRITE_DAC;
         if (flags & O_NOFOLLOW) {
            dwflags = FILE_FLAG_BACKUP_SEMANTICS;
         } else {
            dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
         }
      } else {
         dwaccess = GENERIC_WRITE;
         dwflags = 0;
      }

      if (p_CreateFileW && p_MultiByteToWideChar) {
         /*
          * unicode open for open existing write
          */
         Dmsg1(100, "Write only CreateFileW=%s\n", win32_fname);
         bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
                                 dwaccess,      /* Requested access */
                                 0,             /* Shared mode */
                                 NULL,          /* SecurityAttributes */
                                 OPEN_EXISTING, /* CreationDisposition */
                                 dwflags,       /* Flags and attributes */
                                 NULL);         /* TemplateFile */
      } else {
         /*
          * ASCII open
          */
         Dmsg1(100, "Write only CreateFileA=%s\n", win32_fname);
         bfd->fh = p_CreateFileA(win32_fname,
                                 dwaccess,      /* Requested access */
                                 0,             /* Shared mode */
                                 NULL,          /* SecurityAttributes */
                                 OPEN_EXISTING, /* CreationDisposition */
                                 dwflags,       /* Flags and attributes */
                                 NULL);         /* TemplateFile */

      }

      bfd->mode = BF_WRITE;
   } else {
      /*
       * Open existing for read
       */
      if (bfd->use_backup_api) {
         dwaccess = GENERIC_READ | READ_CONTROL | ACCESS_SYSTEM_SECURITY;
         if (flags & O_NOFOLLOW) {
            dwflags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_SEQUENTIAL_SCAN;
         } else {
            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;
         dwflags = 0;
         dwshare = FILE_SHARE_READ | FILE_SHARE_WRITE;
      }

      if (p_CreateFileW && p_MultiByteToWideChar) {
         /*
          * Unicode open for open existing read
          */
         Dmsg1(100, "Read CreateFileW=%s\n", win32_fname);
         bfd->fh = p_CreateFileW((LPCWSTR)win32_fname_wchar,
                                 dwaccess,      /* Requested access */
                                 dwshare,       /* Share modes */
                                 NULL,          /* SecurityAttributes */
                                 OPEN_EXISTING, /* CreationDisposition */
                                 dwflags,       /* Flags and attributes */
                                 NULL);         /* TemplateFile */
      } else {
         /*
          * ASCII open for open existing read
          */
         Dmsg1(100, "Read CreateFileA=%s\n", win32_fname);
         bfd->fh = p_CreateFileA(win32_fname,
                                 dwaccess,      /* Requested access */
                                 dwshare,       /* Share modes */
                                 NULL,          /* SecurityAttributes */
                                 OPEN_EXISTING, /* CreationDisposition */
                                 dwflags,       /* Flags and attributes */
                                 NULL);         /* TemplateFile */
      }

      bfd->mode = BF_READ;
   }

   if (bfd->fh == INVALID_HANDLE_VALUE) {
      bfd->lerror = GetLastError();
      bfd->berrno = b_errno_win32;
      errno = b_errno_win32;
      bfd->mode = BF_CLOSED;
   }

   bfd->errmsg = NULL;
   bfd->lpContext = NULL;
   bfd->win32DecompContext.bIsInData = false;
   bfd->win32DecompContext.liNextHeader = 0;
   free_pool_memory(win32_fname_wchar);
   free_pool_memory(win32_fname);

   bfd->encrypted = false;

   return bfd->mode == BF_CLOSED ? -1 : 1;
}
Пример #15
0
Файл: bfile.c Проект: AlD/bareos
static inline int bopen_encrypted(BFILE *bfd, const char *fname, int flags, mode_t mode)
{
   bool is_dir;
   ULONG ulFlags = 0;
   POOLMEM *win32_fname;
   POOLMEM *win32_fname_wchar;

   if (!p_OpenEncryptedFileRawA && !p_OpenEncryptedFileRawW) {
      Dmsg0(50, "No p_OpenEncryptedFileRawA and no p_OpenEncryptedFileRawW!!!!!\n");
      return 0;
   }

   is_dir = S_ISDIR(mode);

   /*
    * Convert to Windows path format
    */
   win32_fname = get_pool_memory(PM_FNAME);
   win32_fname_wchar = get_pool_memory(PM_FNAME);

   unix_name_to_win32(&win32_fname, (char *)fname);

   if (p_OpenEncryptedFileRawW && p_MultiByteToWideChar) {
      make_win32_path_UTF8_2_wchar(&win32_fname_wchar, fname);
   }

   /*
    * See if we open the file for create or read-write.
    */
   if ((flags & O_CREAT) || (flags & O_WRONLY)) {
      if (is_dir) {
         ulFlags |= CREATE_FOR_IMPORT | OVERWRITE_HIDDEN | CREATE_FOR_DIR;
      } else {
         ulFlags |= CREATE_FOR_IMPORT | OVERWRITE_HIDDEN;
      }
      bfd->mode = BF_WRITE;
   } else {
      ulFlags = CREATE_FOR_EXPORT;
      bfd->mode = BF_READ;
   }

   if (p_OpenEncryptedFileRawW && p_MultiByteToWideChar) {
      /*
       * Unicode open.
       */
      Dmsg1(100, "OpenEncryptedFileRawW=%s\n", win32_fname);
      if (p_OpenEncryptedFileRawW((LPCWSTR)win32_fname_wchar,
                                  ulFlags,
                                  &(bfd->pvContext))) {
         bfd->mode = BF_CLOSED;
      }
   } else {
      /*
       * ASCII open.
       */
      Dmsg1(100, "OpenEncryptedFileRawA=%s\n", win32_fname);
      if (p_OpenEncryptedFileRawA(win32_fname_wchar,
                                  ulFlags,
                                  &(bfd->pvContext))) {
         bfd->mode=BF_CLOSED;
      }
   }

   free_pool_memory(win32_fname_wchar);
   free_pool_memory(win32_fname);

   bfd->encrypted = true;

   return bfd->mode == BF_CLOSED ? -1 : 1;
}
Пример #16
0
/*
 * Restore all file attributes like owner, mode and file times.
 */
static inline bool restore_file_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
{
    bool ok = true;
    bool suppress_errors;
#if defined(HAVE_FCHOWN) || defined(HAVE_FCHMOD) || defined(HAVE_FUTIMES) || defined(FUTIMENS)
    bool file_is_open;

    /*
     * Save if we are working on an open file.
     */
    file_is_open = is_bopen(ofd);
#endif

    /*
     * See if we want to print errors.
     */
    suppress_errors = (debug_level >= 100 || my_uid != 0);

    /*
     * Restore owner and group.
     */
#ifdef HAVE_FCHOWN
    if (file_is_open) {
        if (fchown(ofd->fid, attr->statp.st_uid, attr->statp.st_gid) < 0 && !suppress_errors) {
            berrno be;

            Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"), attr->ofname, be.bstrerror());
            ok = false;
        }
    } else {
#else
    {
#endif
        if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0 && !suppress_errors) {
            berrno be;

            Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"), attr->ofname, be.bstrerror());
            ok = false;
        }
    }

    /*
     * Restore filemode.
     */
#ifdef HAVE_FCHMOD
    if (file_is_open) {
        if (fchmod(ofd->fid, attr->statp.st_mode) < 0 && !suppress_errors) {
            berrno be;

            Jmsg2(jcr, M_ERROR, 0, _("Unable to set file modes %s: ERR=%s\n"), attr->ofname, be.bstrerror());
            ok = false;
        }
    } else {
#else
    {
#endif
#if defined(HAVE_WIN32)
        if (win32_chmod(attr->ofname, attr->statp.st_mode, attr->statp.st_rdev) < 0 && !suppress_errors) {
#else
        if (lchmod(attr->ofname, attr->statp.st_mode) < 0 && !suppress_errors) {
#endif
            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 defined(HAVE_FUTIMES)
    if (file_is_open) {
        struct timeval restore_times[2];

        restore_times[0].tv_sec = attr->statp.st_atime;
        restore_times[0].tv_usec = 0;
        restore_times[1].tv_sec = attr->statp.st_mtime;
        restore_times[1].tv_usec = 0;

        if (futimes(ofd->fid, restore_times) < 0 && !suppress_errors) {
            berrno be;

            Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"), attr->ofname, be.bstrerror());
            ok = false;
        }
    } else {
#elif defined(HAVE_FUTIMENS)
    if (file_is_open) {
        struct timespec restore_times[2];

        restore_times[0].tv_sec = attr->statp.st_atime;
        restore_times[0].tv_nsec = 0;
        restore_times[1].tv_sec = attr->statp.st_mtime;
        restore_times[1].tv_nsec = 0;

        if (futimens(ofd->fid, restore_times) < 0 && !suppress_errors) {
            berrno be;

            Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"), attr->ofname, be.bstrerror());
            ok = false;
        }
    } else {
#else
    {
#endif
#if defined(HAVE_LUTIMES)
        struct timeval restore_times[2];

        restore_times[0].tv_sec = attr->statp.st_atime;
        restore_times[0].tv_usec = 0;
        restore_times[1].tv_sec = attr->statp.st_mtime;
        restore_times[1].tv_usec = 0;

        if (lutimes(attr->ofname, restore_times) < 0 && !suppress_errors) {
            berrno be;

            Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"), attr->ofname, be.bstrerror());
            ok = false;
        }
#elif defined(HAVE_UTIMES)
        struct timeval restore_times[2];

        restore_times[0].tv_sec = attr->statp.st_atime;
        restore_times[0].tv_usec = 0;
        restore_times[1].tv_sec = attr->statp.st_mtime;
        restore_times[1].tv_usec = 0;

        if (utimes(attr->ofname, restore_times) < 0 && !suppress_errors) {
            berrno be;

            Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"), attr->ofname, be.bstrerror());
            ok = false;
        }
#else
        struct utimbuf restore_times;

        restore_times.actime = attr->statp.st_atime;
        restore_times.modtime = attr->statp.st_mtime;

        if (utime(attr->ofname, &restore_times) < 0 && !suppress_errors) {
            berrno be;

            Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"), attr->ofname, be.bstrerror());
            ok = false;
        }
#endif /* HAVE_LUTIMES */
    }

    return ok;
}

/**
 * Set file modes, permissions and times
 *
 *  fname is the original filename
 *  ofile is the output filename (may be in a different directory)
 *
 * Returns:  true  on success
 *           false on failure
 */
bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
{
    mode_t old_mask;
    bool ok = true;
    bool suppress_errors;

    if (uid_set) {
        my_uid = getuid();
        my_gid = getgid();
        uid_set = true;
    }

    /*
     * See if we want to print errors.
     */
    suppress_errors = (debug_level >= 100 || my_uid != 0);

#if defined(HAVE_WIN32)
    if (attr->stream == STREAM_UNIX_ATTRIBUTES_EX &&
            set_win32_attributes(jcr, attr, ofd)) {
        if (is_bopen(ofd)) {
            bclose(ofd);
        }
        pm_strcpy(attr->ofname, "*None*");
        return true;
    }

    if (attr->data_stream == STREAM_WIN32_DATA ||
            attr->data_stream == STREAM_WIN32_GZIP_DATA ||
            attr->data_stream == STREAM_WIN32_COMPRESSED_DATA) {
        if (is_bopen(ofd)) {
            bclose(ofd);
        }
        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 universal way.
     */
#endif

    old_mask = umask(0);
    if (is_bopen(ofd)) {
        boffset_t fsize;
        char ec1[50], ec2[50];

        fsize = blseek(ofd, 0, SEEK_END);
        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), edit_uint64(fsize, ec2));
        }
    } else {
        struct stat st;
        char ec1[50], ec2[50];

        if (lstat(attr->ofname, &st) == 0) {
            if (attr->type == FT_REG &&
                    st.st_size > 0 &&
                    attr->statp.st_size > 0 &&
                    st.st_size != 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(st.st_size, ec2));
            }
        }
    }

    /**
     * We do not restore sockets, so skip trying to restore their attributes.
     */
    if (attr->type == FT_SPEC && S_ISSOCK(attr->statp.st_mode)) {
        goto bail_out;
    }

    /* ***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 && !suppress_errors) {
            berrno be;

            Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"), attr->ofname, be.bstrerror());
            ok = false;
        }

#ifdef HAVE_LCHMOD
        if (lchmod(attr->ofname, attr->statp.st_mode) < 0 && !suppress_errors) {
            berrno be;

            Jmsg2(jcr, M_ERROR, 0, _("Unable to set file modes %s: ERR=%s\n"), attr->ofname, be.bstrerror());
            ok = false;
        }
#endif
    } else {
        if (!ofd->cmd_plugin) {
            ok = restore_file_attributes(jcr, attr, ofd);

#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 && !suppress_errors) {
                berrno be;
                Jmsg2(jcr, M_ERROR, 0, _("Unable to set file flags %s: ERR=%s\n"), attr->ofname, be.bstrerror());
                ok = false;
            }
#endif
        }
    }

bail_out:
    if (is_bopen(ofd)) {
        bclose(ofd);
    }

    pm_strcpy(attr->ofname, "*None*");
    umask(old_mask);

    return ok;
}

#if !defined(HAVE_WIN32)
/*=============================================================*/
/*                                                             */
/*                 * * *  U n i x * * * *                      */
/*                                                             */
/*=============================================================*/

/**
 * 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
 *   of your own length), and they must be in ASCII string
 *   format. Using this feature is not recommended.
 * The code below shows how to return nothing.  See the Win32
 *   code below for returning something in the 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;

    *attribsEx = 0;                 /* no extended attributes (yet) */
    if (jcr->cmd_plugin || ff_pkt->type == FT_DELETED) {
        return STREAM_UNIX_ATTRIBUTES;
    }
    p = attribsEx;
    if (bit_is_set(FO_HFSPLUS, ff_pkt->flags)) {
        p += to_base64((uint64_t)(ff_pkt->hfsinfo.rsrclength), p);
    }
    *p = 0;
#else
    *attribsEx = 0;                    /* no extended attributes */
#endif
    return STREAM_UNIX_ATTRIBUTES;
}
#else
/*=============================================================*/
/*                                                             */
/*                 * * *  W i n 3 2 * * * *                    */
/*                                                             */
/*=============================================================*/
int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
{
    char *p = attribsEx;
    WIN32_FILE_ATTRIBUTE_DATA atts;
    ULARGE_INTEGER li;

    attribsEx[0] = 0;                  /* no extended attributes */

    if (jcr->cmd_plugin || ff_pkt->type == FT_DELETED) {
        return STREAM_UNIX_ATTRIBUTES;
    }

    unix_name_to_win32(ff_pkt->sys_fname, ff_pkt->fname);
    if (p_GetFileAttributesExW)  {
        /**
         * Try unicode version
         */
        POOLMEM* pwszBuf = get_pool_memory(PM_FNAME);
        make_win32_path_UTF8_2_wchar(pwszBuf, ff_pkt->fname);

        BOOL b=p_GetFileAttributesExW((LPCWSTR)pwszBuf, GetFileExInfoStandard,
                                      (LPVOID)&atts);
        free_pool_memory(pwszBuf);

        if (!b) {
            win_error(jcr, "GetFileAttributesExW:", ff_pkt->sys_fname);
            return STREAM_UNIX_ATTRIBUTES;
        }
    } else {
        if (!p_GetFileAttributesExA)
            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;
        }
    }

    /*
     * Instead of using the current dwFileAttributes use the
     * ff_pkt->statp.st_rdev which contains the actual fileattributes we
     * want to save for this file.
     */
    atts.dwFileAttributes = ff_pkt->statp.st_rdev;

    p += to_base64((uint64_t)atts.dwFileAttributes, p);
    *p++ = ' ';                        /* separate fields with a space */
    li.LowPart = atts.ftCreationTime.dwLowDateTime;
    li.HighPart = atts.ftCreationTime.dwHighDateTime;
    p += to_base64((uint64_t)li.QuadPart, p);
    *p++ = ' ';
    li.LowPart = atts.ftLastAccessTime.dwLowDateTime;
    li.HighPart = atts.ftLastAccessTime.dwHighDateTime;
    p += to_base64((uint64_t)li.QuadPart, p);
    *p++ = ' ';
    li.LowPart = atts.ftLastWriteTime.dwLowDateTime;
    li.HighPart = atts.ftLastWriteTime.dwHighDateTime;
    p += to_base64((uint64_t)li.QuadPart, p);
    *p++ = ' ';
    p += to_base64((uint64_t)atts.nFileSizeHigh, p);
    *p++ = ' ';
    p += to_base64((uint64_t)atts.nFileSizeLow, p);
    *p = 0;

    return STREAM_UNIX_ATTRIBUTES_EX;
}