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); } }
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); } }
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; }
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; }
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); }
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; }
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; }