int impl_fuse_context::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()); }
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_); }
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); }
char * xstrdup_name (void) { if (qualified(name_of_file + 1)) *log_line = '\0'; else { (void) getcwd(log_line, sizeof(log_line)); strcat(log_line, PATH_SEP_STRING); } strcat(log_line, (char *) name_of_file + 1); unixify(log_line); return xstrdup(log_line); }
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; }
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; }
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; }
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; }
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? }
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()); }
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 == FILE_OVERWRITE) { 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 == FILE_SUPERSEDE || creation_disposition == FILE_OVERWRITE_IF) { if (!ops_.truncate) return -EINVAL; CHECKED(ops_.truncate(fname.c_str(), 0)); } else if (creation_disposition == FILE_CREATE) { SetLastError(ERROR_FILE_EXISTS); return win_error(STATUS_OBJECT_NAME_COLLISION, true); } if (creation_disposition == FILE_OVERWRITE_IF || creation_disposition == FILE_OPEN_IF) { SetLastError(ERROR_ALREADY_EXISTS); } return do_open_file(file_name, share_mode, access_mode, dokan_file_info); } } }
boolean open_output (FILE ** f, const char * fopen_mode) { unsigned temp_length; name_of_file[name_length + 1] = '\0'; if (pseudo_tilde != 0 || pseudo_space != 0) retwiddle(name_of_file + 1); /* 8 + 3 file names on Windows NT 95/Feb/20 */ if (shorten_file_name) check_short_name(name_of_file + 1); if (prepend_path_if(name_of_file + 1, name_of_file + 1, ".dvi", dvi_directory) || prepend_path_if(name_of_file + 1, name_of_file + 1, ".log", log_directory) || prepend_path_if(name_of_file + 1, name_of_file + 1, ".aux", aux_directory) || prepend_path_if(name_of_file + 1, name_of_file + 1, ".fmt", fmt_directory) || prepend_path_if(name_of_file + 1, name_of_file + 1, ".pdf", pdf_directory)) { if (open_trace_flag) printf("After prepend %s\n", name_of_file + 1); } if (open_trace_flag) printf(" Open `%s' for output ", name_of_file + 1); *f = fopen((char *) name_of_file + 1, fopen_mode); if (*f == NULL) { string temp_dir = kpse_var_value("TEXMFOUTPUT"); if (temp_dir != NULL) { unsigned char temp_name[file_name_size]; xconcat3((char *) temp_name, temp_dir, PATH_SEP_STRING, (char *) name_of_file + 1); if (deslash) unixify((char *) temp_name); *f = fopen((char *) temp_name, fopen_mode); if (*f) strcpy((char *) name_of_file + 1, (char *) temp_name); } } #ifdef COMPACTFORMAT if (strstr((char *) name_of_file + 1, ".fmt") != NULL) gz_fmt_file = gzdopen(fileno(*f), "wb9"); #endif if (strstr((char *) name_of_file + 1, ".dvi") != NULL) dvi_file_name = xstrdup_name(); else if (strstr((char *) name_of_file + 1, ".pdf") != NULL) pdf_file_name = xstrdup_name(); else if (strstr((char *) name_of_file + 1, ".log") != NULL) log_file_name = xstrdup_name(); temp_length = strlen((char *) name_of_file + 1); name_of_file[temp_length + 1] = ' '; if (*f) name_length = temp_length; return (*f != NULL); }