예제 #1
0
파일: fusemain.cpp 프로젝트: Thinkscape/pfs
int impl_fuse_context::move_file(LPCWSTR file_name, LPCWSTR new_file_name,
			  BOOL replace_existing, PDOKAN_FILE_INFO dokan_file_info)
{
	if (!ops_.rename || !ops_.getattr) return -EINVAL;

	std::string name=unixify(wchar_to_utf8_cstr(file_name));
	std::string new_name=unixify(wchar_to_utf8_cstr(new_file_name));

	struct FUSE_STAT stbuf={0};
	if (ops_.getattr(new_name.c_str(),&stbuf)!=-ENOENT)
	{
		//Cannot delete directory
		if ((stbuf.st_mode&S_IFDIR)==0 && ops_.unlink)
        {
            if (replace_existing)
            {
                CHECKED(ops_.unlink(new_name.c_str()));
            }
            else
            {
                return -EEXIST;
            }
		}
	}

	return ops_.rename(name.c_str(),new_name.c_str());
}
예제 #2
0
int impl_fuse_context::move_file(LPCWSTR file_name, LPCWSTR new_file_name,
                                 BOOL replace_existing,
                                 PDOKAN_FILE_INFO dokan_file_info) {
  if (!ops_.rename || !ops_.getattr)
    return -EINVAL;

  std::string name = unixify(wchar_to_utf8_cstr(file_name));
  std::string new_name = unixify(wchar_to_utf8_cstr(new_file_name));

  struct FUSE_STAT stbuf = {0};
  if (ops_.getattr(new_name.c_str(), &stbuf) != -ENOENT) {
    if (!replace_existing)
      return -EEXIST;

    // Cannot delete directory
    if ((stbuf.st_mode & S_IFDIR) != 0)
      return -EISDIR;
    if (!ops_.unlink)
      return -EINVAL;
    CHECKED(ops_.unlink(new_name.c_str()));
  }

  // this can happen cause DeleteFile in Windows can return success even if
  // file is still in the file system
  if (ops_.getattr(new_name.c_str(), &stbuf) != -ENOENT) {
    return -EEXIST;
  }

  CHECKED(ops_.rename(name.c_str(), new_name.c_str()));
  file_locks.renamed_file(name, new_name);
  return 0;
}
예제 #3
0
int impl_fuse_context::set_file_time(PCWSTR file_name,
                                     const FILETIME *creation_time,
                                     const FILETIME *last_access_time,
                                     const FILETIME *last_write_time,
                                     PDOKAN_FILE_INFO dokan_file_info) {
  if (!ops_.utimens && !ops_.utime && !ops_.win_set_times)
    return -EINVAL;

  if (ops_.win_set_times) {
    std::string fname = unixify(wchar_to_utf8_cstr(file_name));
    CHECKED(check_and_resolve(&fname));

    impl_file_handle *hndl =
        reinterpret_cast<impl_file_handle *>(dokan_file_info->Context);
    if (!hndl)
      return ops_.win_set_times(fname.c_str(), NULL, creation_time,
                                last_access_time, last_write_time);

    if (hndl->is_dir())
      return -EACCES;

    fuse_file_info finfo(hndl->make_finfo());

    return ops_.win_set_times(fname.c_str(), &finfo, creation_time,
                              last_access_time, last_write_time);
  }

  if (!ops_.getattr)
    return -EINVAL;

  std::string fname = unixify(wchar_to_utf8_cstr(file_name));
  CHECKED(check_and_resolve(&fname));

  struct FUSE_STAT st = {0};
  CHECKED(ops_.getattr(fname.c_str(), &st));

  if (ops_.utimens) {
    struct timespec tv[2] = {0};
    // TODO: support nanosecond resolution
    // Access time
    CHECKED(helper_set_time_struct(last_access_time, st.st_atim.tv_sec,
                                   &(tv[0].tv_sec)));
    // Modification time
    CHECKED(helper_set_time_struct(last_write_time, st.st_mtim.tv_sec,
                                   &(tv[1].tv_sec)));

    return ops_.utimens(fname.c_str(), tv);
  } else {
    struct utimbuf ut = {0};
    // Access time
    CHECKED(helper_set_time_struct(last_access_time, st.st_atim.tv_sec,
                                   &(ut.actime)));
    // Modification time
    CHECKED(helper_set_time_struct(last_write_time, st.st_mtim.tv_sec,
                                   &(ut.modtime)));

    return ops_.utime(fname.c_str(), &ut);
  }
}
예제 #4
0
win_error impl_fuse_context::create_file(LPCWSTR file_name, DWORD access_mode, 
								   DWORD share_mode, DWORD creation_disposition, 
								   DWORD flags_and_attributes, 
								   PDOKAN_FILE_INFO dokan_file_info)
{
	std::string fname=unixify(wchar_to_utf8_cstr(file_name));
	dokan_file_info->Context=0;

	if (!ops_.getattr)
		return -EINVAL;

	struct FUSE_STAT stbuf={0};
	//Check if the target file/directory exists
	if (ops_.getattr(fname.c_str(),&stbuf)<0)
	{
		//Nope.		
		if (dokan_file_info->IsDirectory) 
			return -EINVAL; //We can't create directories using CreateFile
		return do_create_file(file_name, creation_disposition, share_mode, access_mode,
			dokan_file_info);
	} else
	{		
		if (S_ISLNK(stbuf.st_mode))
		{
			//Get link's target
			CHECKED(resolve_symlink(fname,&fname));
			CHECKED(ops_.getattr(fname.c_str(),&stbuf));
		}

		if ((stbuf.st_mode&S_IFDIR)==S_IFDIR)
		{
			//Existing directory
			//TODO: add access control
			dokan_file_info->IsDirectory=TRUE;
			return do_open_dir(file_name,dokan_file_info);
		} else
		{
			//Existing file
			//Check if we'll be able to truncate or delete the opened file
			//TODO: race condition here?
			if (creation_disposition==CREATE_ALWAYS)
			{
				if (!ops_.unlink) return -EINVAL;
				CHECKED(ops_.unlink(fname.c_str())); //Delete file
				//And create it!
				return do_create_file(file_name,creation_disposition, share_mode,
					access_mode,dokan_file_info);
			} else if (creation_disposition==TRUNCATE_EXISTING)
			{
				if (!ops_.truncate) return -EINVAL;
				CHECKED(ops_.truncate(fname.c_str(),0));
			} else if (creation_disposition==CREATE_NEW)
			{
				return win_error(ERROR_FILE_EXISTS, true);
			}

			return do_open_file(file_name, share_mode, access_mode, dokan_file_info);
		}
	}
}
예제 #5
0
int impl_fuse_context::do_create_file(LPCWSTR FileName, DWORD Disposition, DWORD share_mode, DWORD Flags,
									PDOKAN_FILE_INFO DokanFileInfo)
{
	std::string fname=unixify(wchar_to_utf8_cstr(FileName));

	//Create file?
	if (Disposition!=CREATE_NEW && Disposition!=CREATE_ALWAYS && Disposition!=OPEN_ALWAYS)		
		return -ENOENT; //No, we're trying to open an existing file!

	if (!ops_.create)
	{
		//Use mknod+open.
		if (!ops_.mknod || !ops_.open) return -EINVAL;
		CHECKED(ops_.mknod(fname.c_str(),filemask_,0));
		return do_open_file(FileName, share_mode, Flags, DokanFileInfo);
	}

	std::auto_ptr<impl_file_handle> file;
	CHECKED(file_locks.get_file(fname,false,Flags,share_mode,file));

	fuse_file_info finfo={0};
	finfo.flags=O_CREAT | O_EXCL | convert_flags(Flags); //TODO: these flags should be OK for new files?	
	
	CHECKED(ops_.create(fname.c_str(),filemask_,&finfo));

	DokanFileInfo->Context=reinterpret_cast<ULONG64>(file.release());
	return 0;
}
예제 #6
0
void Drive::Umount(HWND)
{
	// check mounted
	CheckMounted();
//	if (GetDriveType(mnt) == DRIVE_NO_ROOT_DIR)
//		mounted = false;
	if (!mounted)
		throw truntime_error(_T("Cannot unmount a not mounted drive"));

	// unmount
	fuse_unmount(wchar_to_utf8_cstr(mnt).c_str(), NULL);

	if (subProcess) {
		// attach console to allow sending ctrl-c
		AttachConsole(subProcess->pid);

		// disable ctrl-c to not exit this process
		SetConsoleCtrlHandler(HandlerRoutine, TRUE);

		if (!GenerateConsoleCtrlEvent(CTRL_C_EVENT, subProcess->pid)
		    && !GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, subProcess->pid))
			TerminateProcess(subProcess->hProcess, 0);

		// force exit
		if (WaitForSingleObject(subProcess->hProcess, 2000) == WAIT_TIMEOUT)
			TerminateProcess(subProcess->hProcess, 0);
			
		// close the console
		FreeConsole();
		SetConsoleCtrlHandler(HandlerRoutine, FALSE);
	}
	CheckMounted();
}
예제 #7
0
파일: fusemain.cpp 프로젝트: Thinkscape/pfs
int impl_fuse_context::set_file_time(PCWSTR file_name, const FILETIME* creation_time,
				  const FILETIME* last_access_time, const FILETIME* last_write_time,
				  PDOKAN_FILE_INFO dokan_file_info)
{
	if (!ops_.utimens && !ops_.utime) return -EINVAL;
	if (!ops_.getattr) return -EINVAL;

	std::string fname=unixify(wchar_to_utf8_cstr(file_name));
	CHECKED(check_and_resolve(&fname));

	struct FUSE_STAT st={0};
	CHECKED(ops_.getattr(fname.c_str(),&st));

	if (ops_.utimens)
	{
		struct timespec tv[2]={{0,},};
		//TODO: support nanosecond resolution
		//Access time
		CHECKED(helper_set_time_struct(last_access_time,st.st_atime,&(tv[0].tv_sec)));
		//Modification time
		CHECKED(helper_set_time_struct(last_write_time,st.st_mtime,&(tv[1].tv_sec)));

		return ops_.utimens(fname.c_str(),tv);
	} else
	{
		struct utimbuf ut={0};
		//Access time
		CHECKED(helper_set_time_struct(last_access_time,st.st_atime,&(ut.actime)));
		//Modification time
		CHECKED(helper_set_time_struct(last_write_time,st.st_mtime,&(ut.modtime)));

		return ops_.utime(fname.c_str(),&ut);
	}
}
예제 #8
0
int impl_fuse_context::get_file_information(
    LPCWSTR file_name, LPBY_HANDLE_FILE_INFORMATION handle_file_information,
    PDOKAN_FILE_INFO dokan_file_info) {
  std::string fname = unixify(wchar_to_utf8_cstr(file_name));

  if (!ops_.getattr)
    return -EINVAL;

  struct FUSE_STAT st = {0};
  CHECKED(ops_.getattr(fname.c_str(), &st));
  if (S_ISLNK(st.st_mode)) {
    std::string resolved;
    CHECKED(resolve_symlink(fname, &resolved));
    CHECKED(ops_.getattr(resolved.c_str(), &st));
  }

  handle_file_information->nNumberOfLinks = st.st_nlink;
  if ((st.st_mode & S_IFDIR) == S_IFDIR)
    dokan_file_info->IsDirectory = TRUE;
  convertStatlikeBuf(&st, fname, handle_file_information);

  uint32_t attrs = 0xFFFFFFFFu;
  if (ops_.win_get_attributes)
    attrs = ops_.win_get_attributes(fname.c_str());
  if (attrs != 0xFFFFFFFFu)
    handle_file_information->dwFileAttributes = attrs;

  return 0;
}
예제 #9
0
int impl_fuse_context::open_directory(LPCWSTR file_name, 
									  PDOKAN_FILE_INFO dokan_file_info)
{
	std::string fname=unixify(wchar_to_utf8_cstr(file_name));	

	if (ops_.opendir)
		return do_open_dir(file_name,dokan_file_info);

	//We don't have opendir(), so the most we can do is make sure
	//that the target is indeed a directory
	struct FUSE_STAT st={0};
	CHECKED(ops_.getattr(fname.c_str(),&st));
	if (S_ISLNK(st.st_mode))
	{
		std::string resolved;
		CHECKED(resolve_symlink(fname,&resolved));	
		CHECKED(ops_.getattr(resolved.c_str(),&st));
	}

	//Not a directory
	if ((st.st_mode&S_IFDIR)!=S_IFDIR)
		return -ENOTDIR;
	
	dokan_file_info->Context=(ULONG64)NULL; //Do not want to attach anything
	return 0; //Use readdir here?
}
예제 #10
0
static void
OpenOrCreate(HWND hwnd)
{
	static bool openAlreadyOpened = false;

	if (openAlreadyOpened)
		return;

	class Unique {
	public:
		Unique() { openAlreadyOpened = true; }
		~Unique() { openAlreadyOpened = false; }
	} unique;

	std::tstring dir = GetExistingDirectory(hwnd,
		_T("Select a folder which contains or will contain encrypted data."), _T("Select Crypt Folder"));
	if (dir.empty())
		return;

	// if directory is already configured add and try to mount
	boost::shared_ptr<EncFSConfig> config(new EncFSConfig);
	if (readConfig(slashTerminate(wchar_to_utf8_cstr(dir.c_str())), config) != Config_None) {
		char drive = SelectFreeDrive(hwnd);
		if (drive) {
			Drives::drive_t dr(Drives::Add(dir, drive));
			if (dr)
				dr->Mount(hwnd);
		}
		return;
	}

	// TODO check directory is empty, warning if continue
	// "You are initializing a crypted directory with a no-empty directory. Is this expected?"
	OptionsData data;
	data.rootDir = dir;
	if (DialogBoxParam(hInst, (LPCTSTR) IDD_OPTIONS, hwnd, (DLGPROC) OptionsDlgProc, (LPARAM) &data) != IDOK)
		return;

	// add configuration and add new drive
	createConfig(slashTerminate(wchar_to_utf8_cstr(dir.c_str())), data.paranoia, false, wchar_to_utf8_cstr(data.password).c_str(), true);

	Drives::drive_t dr(Drives::Add(dir, data.drive));
	if (dr)
		dr->Mount(hwnd);
}
예제 #11
0
int impl_fuse_context::do_delete_file(LPCWSTR file_name,
                                      PDOKAN_FILE_INFO dokan_file_info) {
  if (!ops_.unlink)
    return -EINVAL;

  // Note: we do not try to resolve symlink target
  std::string fname = unixify(wchar_to_utf8_cstr(file_name));
  return ops_.unlink(fname.c_str());
}
예제 #12
0
int impl_fuse_context::create_directory(LPCWSTR file_name,
                                        PDOKAN_FILE_INFO dokan_file_info) {
  std::string fname = unixify(wchar_to_utf8_cstr(file_name));

  if (!ops_.mkdir)
    return -EINVAL;

  return ops_.mkdir(fname.c_str(), dirmask_);
}
예제 #13
0
int impl_fuse_context::delete_file(LPCWSTR file_name,
                                   PDOKAN_FILE_INFO dokan_file_info) {
  std::string fname = unixify(wchar_to_utf8_cstr(file_name));

  if (!ops_.getattr)
    return -EINVAL;

  struct FUSE_STAT stbuf = {0};
  return ops_.getattr(fname.c_str(), &stbuf);
}
예제 #14
0
파일: fusemain.cpp 프로젝트: Thinkscape/pfs
int impl_fuse_context::do_open_dir(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo)
{
	if (ops_.opendir)
	{
		fuse_file_info finfo={0};
		std::string fname=unixify(wchar_to_utf8_cstr(FileName));
		CHECKED(ops_.opendir(fname.c_str(),&finfo));

		DokanFileInfo->Context=reinterpret_cast<ULONG64>(new impl_file_handle(fname,true,&finfo));
		return 0;
	}

	DokanFileInfo->Context=0;
	return 0;
}
예제 #15
0
int impl_fuse_context::walk_directory(void *buf, const char *name, 
									  const struct FUSE_STAT *stbuf, FUSE_OFF_T off)
{
	walk_data *wd=(walk_data*)buf;
	WIN32_FIND_DATAW find_data={0};	

	utf8_to_wchar_buf(name,find_data.cFileName,MAX_PATH);
	// fix name if wrong encoding
	if (!find_data.cFileName[0]) {
		struct FUSE_STAT stbuf={0};
		utf8_to_wchar_buf_old(name,find_data.cFileName,MAX_PATH);
		std::string new_name = wchar_to_utf8_cstr(find_data.cFileName);
		if (wd->ctx->ops_.getattr && wd->ctx->ops_.rename && new_name.length() && wd->ctx->ops_.getattr(new_name.c_str(),&stbuf) == -ENOENT)
			wd->ctx->ops_.rename(name, new_name.c_str());
	}
	memset(find_data.cAlternateFileName, 0, sizeof(find_data.cAlternateFileName));

	struct FUSE_STAT stat={0};

	if (stbuf!=NULL)
		stat=*stbuf;		
	else
	{
		//No stat buffer - use 'getattr'.
		//TODO: fill directory params here!!!
		if (strcmp(name,".")==0 || strcmp(name,"..")==0) //Special entries
			stat.st_mode|=S_IFDIR;
		else
			CHECKED(wd->ctx->ops_.getattr((wd->dirname+name).c_str(),&stat));
	}

	if (S_ISLNK(stat.st_mode))
	{
		std::string resolved;
		CHECKED(wd->ctx->resolve_symlink(wd->dirname+name,&resolved));		
		CHECKED(wd->ctx->ops_.getattr(resolved.c_str(),&stat));		
	}
	
	convertStatlikeBuf(&stat,name,&find_data);

	uint32_t attrs = 0xFFFFFFFFu;
	if (wd->ctx->ops_.win_get_attributes)
		attrs = wd->ctx->ops_.win_get_attributes((wd->dirname+name).c_str());
	if (attrs != 0xFFFFFFFFu)
		find_data.dwFileAttributes = attrs;
	
	return wd->delegate(&find_data,wd->DokanFileInfo);
}
예제 #16
0
파일: fusemain.cpp 프로젝트: Thinkscape/pfs
int impl_fuse_context::do_open_file(LPCWSTR FileName, DWORD Flags,
									PDOKAN_FILE_INFO DokanFileInfo)
{
	if (!ops_.open) return -EINVAL;
	std::string fname=unixify(wchar_to_utf8_cstr(FileName));
	CHECKED(check_and_resolve(&fname));

	fuse_file_info finfo={0};
	//if ((ShareMode & FILE_SHARE_READ) || (ShareMode & FILE_SHARE_DELETE))
	//TODO: add sharing support?
	finfo.flags=convert_flags(Flags);

	CHECKED(ops_.open(fname.c_str(),&finfo));
	DokanFileInfo->Context=reinterpret_cast<ULONG64>(new impl_file_handle(fname,false,&finfo));
	return 0;
}
예제 #17
0
int impl_fuse_context::set_file_attributes(LPCWSTR file_name,
                                           DWORD file_attributes,
                                           PDOKAN_FILE_INFO dokan_file_info) {
  // This method is unlikely to be implemented since we do not support
  // advanced properties
  // TODO: maybe use extended properties of underlying FS?

  // Just return 'success' since returning -EINVAL interferes with modification
  // time
  // setting from FAR Manager.
  if (ops_.win_set_attributes) {
    std::string fname = unixify(wchar_to_utf8_cstr(file_name));
    CHECKED(check_and_resolve(&fname));
    return ops_.win_set_attributes(fname.c_str(), file_attributes);
  }
  return 0;
}
예제 #18
0
int impl_fuse_context::set_end_of_file(LPCWSTR file_name, LONGLONG byte_offset,
                                       PDOKAN_FILE_INFO dokan_file_info) {
  FUSE_OFF_T off;
  CHECKED(cast_from_longlong(byte_offset, &off));
  std::string fname = unixify(wchar_to_utf8_cstr(file_name));
  CHECKED(check_and_resolve(&fname));

  impl_file_handle *hndl =
      reinterpret_cast<impl_file_handle *>(dokan_file_info->Context);
  if (hndl && ops_.ftruncate) {
    fuse_file_info finfo(hndl->make_finfo());
    return ops_.ftruncate(hndl->get_name().c_str(), off, &finfo);
  }

  if (!ops_.truncate)
    return -EINVAL;
  return ops_.truncate(fname.c_str(), off);
}
예제 #19
0
int impl_fuse_context::find_files(LPCWSTR file_name,
                                  PFillFindData fill_find_data,
                                  PDOKAN_FILE_INFO dokan_file_info) {
  if ((!ops_.readdir && !ops_.getdir) || !ops_.getattr)
    return -EINVAL;

  std::string fname = unixify(wchar_to_utf8_cstr(file_name));
  CHECKED(check_and_resolve(&fname));

  walk_data wd;
  wd.ctx = this;
  wd.dirname = fname;
  if (*fname.rbegin() != '/')
    wd.dirname.append("/");
  wd.delegate = fill_find_data;
  wd.DokanFileInfo = dokan_file_info;

  if (ops_.readdir) {
    impl_file_handle *hndl =
        reinterpret_cast<impl_file_handle *>(dokan_file_info->Context);
    if (hndl != NULL) {
      fuse_file_info finfo(hndl->make_finfo());
      return ops_.readdir(fname.c_str(), &wd, &walk_directory, 0, &finfo);
    } else
      return ops_.readdir(fname.c_str(), &wd, &walk_directory, 0, NULL);
  } else {
    CHECKED(
        ops_.getdir(fname.c_str(), (fuse_dirh_t)&wd, &walk_directory_getdir));
    // Convert returned data The getdir_data array will be filled during
    // getdir() call.
    // We emulate FUSE behavior and do not pass information directly to Dokan
    // in walk_directory_getdir callback. This can cause excessive network
    // traffic
    // in sshfs because it populates stat buffer cache AFTER calling our
    // callback.
    // See: cache.c file, function cache_dirfill() in SSHFS 2.2
    for (std::vector<std::string>::const_iterator f = wd.getdir_data.begin();
         f != wd.getdir_data.end(); ++f)
      CHECKED(walk_directory(&wd, f->c_str(), 0, 0));
  }

  return 0;
}
예제 #20
0
int impl_fuse_context::do_open_file(LPCWSTR FileName, DWORD share_mode, DWORD Flags,
									PDOKAN_FILE_INFO DokanFileInfo)
{
	if (!ops_.open) return -EINVAL;
	std::string fname=unixify(wchar_to_utf8_cstr(FileName));
	CHECKED(check_and_resolve(&fname));

	std::auto_ptr<impl_file_handle> file;
	CHECKED(file_locks.get_file(fname,false,Flags,share_mode,file));

	fuse_file_info finfo={0};
	finfo.flags=convert_flags(Flags);

	CHECKED(ops_.open(fname.c_str(),&finfo));

	file->set_finfo(finfo);
	DokanFileInfo->Context=reinterpret_cast<ULONG64>(file.release());
	return 0;
}
예제 #21
0
int impl_fuse_context::do_open_dir(LPCWSTR FileName, PDOKAN_FILE_INFO DokanFileInfo)
{
	if (ops_.opendir)
	{
		std::string fname=unixify(wchar_to_utf8_cstr(FileName));
		std::auto_ptr<impl_file_handle> file;
		// TODO access_mode
		CHECKED(file_locks.get_file(fname,true,0,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,file));

		fuse_file_info finfo={0};
		CHECKED(ops_.opendir(fname.c_str(),&finfo));

		file->set_finfo(finfo);
		DokanFileInfo->Context=reinterpret_cast<ULONG64>(file.release());
		return 0;
	}

	DokanFileInfo->Context=0;
	return 0;
}
예제 #22
0
int impl_fuse_context::do_create_file(LPCWSTR FileName, DWORD Disposition,
                                      DWORD share_mode, DWORD Flags,
                                      PDOKAN_FILE_INFO DokanFileInfo)
// Kernel mappsings:
// Disposition = CreateDisposition
// Flags = DesiredAccess
// share_mode = ShareAccess
{
  std::string fname = unixify(wchar_to_utf8_cstr(FileName));

  // Create file?
  if (Disposition != FILE_CREATE && Disposition != FILE_SUPERSEDE &&
      Disposition != FILE_OPEN_IF && Disposition != FILE_OVERWRITE_IF) {
    SetLastError(ERROR_FILE_NOT_FOUND);
    return -ENOENT; // No, we're trying to open an existing file!
  }

  if (!ops_.create) {
    // Use mknod+open.
    if (!ops_.mknod || !ops_.open)
      return -EINVAL;

    CHECKED(ops_.mknod(fname.c_str(), filemask_, 0));

    return do_open_file(FileName, share_mode, Flags, DokanFileInfo);
  }

  std::unique_ptr<impl_file_handle> file;
  CHECKED(file_locks.get_file(fname, false, Flags, share_mode, file));

  fuse_file_info finfo = {0};
  finfo.flags =
      O_CREAT | O_EXCL |
      convert_flags(Flags); // TODO: these flags should be OK for new files?

  CHECKED(ops_.create(fname.c_str(), filemask_, &finfo));

  file->set_finfo(finfo);
  DokanFileInfo->Context = reinterpret_cast<ULONG64>(file.release());
  return 0;
}
예제 #23
0
int impl_fuse_context::do_delete_directory(LPCWSTR file_name,
                                           PDOKAN_FILE_INFO dokan_file_info) {
  std::string fname = unixify(wchar_to_utf8_cstr(file_name));

  if (!ops_.rmdir || !ops_.getattr)
    return -EINVAL;

  // Make sure directory is NOT opened
  // TODO: potential race here - Unix filesystems typically allow
  // to delete open files and directories.
  impl_file_handle *hndl =
      reinterpret_cast<impl_file_handle *>(dokan_file_info->Context);
  if (hndl)
    return -EBUSY;

  // A special case: symlinks are deleted by unlink, not rmdir
  struct FUSE_STAT stbuf = {0};
  CHECKED(ops_.getattr(fname.c_str(), &stbuf));
  if (S_ISLNK(stbuf.st_mode) && ops_.unlink)
    return ops_.unlink(fname.c_str());

  // Ok, try to rmdir it.
  return ops_.rmdir(fname.c_str());
}
예제 #24
0
void Drive::Mount(HWND hwnd)
{
	// check drive empty or require a new drive
	while (GetDriveType(mnt) != DRIVE_NO_ROOT_DIR) {
		char drive = SelectFreeDrive(hwnd);
		if (!drive)
			return;
		_stprintf(mnt, _T("%c:\\"), drive);
		Save();
	}

	// check directory existence
	if (!isDirectory(wchar_to_utf8_cstr(dir.c_str()).c_str())) {
		if (YesNo(hwnd, _T("Directory does not exists. Remove from list?")))
			Drives::Delete(shared_from_this());
		return;
	}

	// TODO check configuration still exists ?? ... no can cause recursion problem

	// search if executable is present
	TCHAR executable[MAX_PATH];
	if (!SearchPath(NULL, _T("encfs.exe"), NULL, LENGTH(executable), executable, NULL))
		throw truntime_error(_T("Unable to find encfs.exe file"));

	// ask a password to mount
	TCHAR pass[128+2];
	if (!GetPassword(hwnd, pass, LENGTH(pass)-2))
		return;
	_tcscat(pass, _T("\r\n"));

	// mount using a sort of popen
	TCHAR cmd[2048];
	_sntprintf(cmd, LENGTH(cmd), _T("\"%s\" -S \"%s\" %c:"), executable, dir.c_str(), mnt[0]);
	boost::shared_ptr<SubProcessInformations> proc(new SubProcessInformations);
	proc->creationFlags = CREATE_NEW_PROCESS_GROUP|CREATE_NO_WINDOW;
	if (!CreateSubProcess(cmd, proc.get())) {
		DWORD err = GetLastError();
		memset(pass, 0, sizeof(pass));
		_sntprintf(cmd, LENGTH(cmd), _T("Error: %s (%u)"), proc->errorPart, (unsigned) err);
		throw truntime_error(cmd);
	}
	subProcess = proc;

	// send the password
	std::string pwd = wchar_to_utf8_cstr(pass);
	DWORD written;
	WriteFile(proc->hIn, pwd.c_str(), pwd.length(), &written, NULL);
	CloseHandle(proc->hIn);	// close input so sub process does not any more
	proc->hIn = NULL;
	memset(pass, 0, sizeof(pass));
	memset((char*) pwd.c_str(), 0, pwd.length());

	mounted = false;

	// wait for mount, read error and give feedback
	for (unsigned n = 0; n < 5*10; ++n) {
		// drive appeared
		if (GetDriveType(mnt) != DRIVE_NO_ROOT_DIR) {
			if (Drives::autoShow)
				Show(hwnd);
			break;
		}

		// process terminated
		DWORD readed;
		char output[2048];
		switch (WaitForSingleObject(subProcess->hProcess, 200)) {
		case WAIT_OBJECT_0:
		case WAIT_ABANDONED:
			if (ReadFile(proc->hOut, output, sizeof(output)-1, &readed, NULL)) {
				output[readed] = 0;
				utf8_to_wchar_buf(output, cmd, LENGTH(cmd));
			} else {
				_stprintf(cmd, _T("Unknown error mounting drive %c:"), mnt[0]);
			}
			subProcess.reset();
			throw truntime_error(cmd);
		}
	}
	if (subProcess)
		mounted = true;
	Save(); // save for resume
}