DIR *opendir(const char *name) { /* Open a directory */ DIR *pDir = NULL; size_t lName; unsigned attr; char *pszWildCards = "\\*.*"; char *pszCopy; DEBUG_ENTER(("opendir(\"%s\");\n", name)); lName = strlen(name); if (lName == 0) { opendir_noent: errno = ENOENT; opendir_failed: if (!_sys_errlist[ENOTDIR][0]) _sys_errlist[ENOTDIR] = "Not a directory"; /* Workaround for the missing entry in MSVC list */ if (pDir) free(pDir); DEBUG_LEAVE(("return NULL; // errno=%d - %s\n", errno, strerror(errno))); return NULL; } pDir = (DIR *)malloc(sizeof(DIR) + lName + 5); /* + 5 for wildcards suffix */ if (!pDir) goto opendir_failed; /* Work on a copy of the directory name */ pszCopy = (char *)(pDir + 1); strcpy(pszCopy, name); /* First change: Except for the root, Remove the trailing \s, which confuses get_file_attributes() */ while ((lName > 1) && (name[lName-1] == '\\') && (name[lName-2] != ':')) pszCopy[--lName] = '\0'; if (get_file_attributes(pszCopy, &attr)) goto opendir_noent; if (!(attr & _A_SUBDIR)) { errno = ENOTDIR; goto opendir_failed; } if (name[lName-1] == '\\') pszWildCards += 1; /* Avoid duplicating the \ */ strcpy(pszCopy+lName, pszWildCards); pDir->first = 1; DEBUG_LEAVE(("return 0x%p;\n", pDir)); return pDir; }
void add_files_impl(file_storage& fs, std::string const& p , std::string const& l, boost::function<bool(std::string)> pred, boost::uint32_t flags) { std::string f = combine_path(p, l); if (!pred(f)) return; error_code ec; file_status s; stat_file(f, &s, ec, (flags & create_torrent::symlinks) ? dont_follow_links : 0); if (ec) return; // recurse into directories bool recurse = (s.mode & file_status::directory) != 0; // if the file is not a link or we're following links, and it's a directory // only then should we recurse #ifndef TORRENT_WINDOWS if ((s.mode & file_status::link) && (flags & create_torrent::symlinks)) recurse = false; #endif if (recurse) { fs.add_path(parent_path(combine_path(l, "x")), s.mode & 0777); for (directory i(f, ec); !i.done(); i.next(ec)) { std::string leaf = i.file(); if (ignore_subdir(leaf)) continue; add_files_impl(fs, p, combine_path(l, leaf), pred, flags); } } else if (s.mode & (file_status::regular_file | file_status::link)) { // #error use the fields from s int file_flags = get_file_attributes(f, (flags & create_torrent::symlinks) ? dont_follow_links : 0); // mask all bits to check if the file is a symlink if ((file_flags & file_storage::attribute_symlink) && (flags & create_torrent::symlinks)) { std::string sym_path = get_symlink_path(f); fs.add_file(l, 0, file_flags, s.mtime, sym_path, s.mode & 0777); } else { fs.add_file(l, s.file_size, file_flags, s.mtime, "", s.mode & 0777); } } if (fs.num_files() == 0) fs.set_name(l); }
/** * Gets all meta data for a file and returns a filled meta_data_t * * structure. * @param file_event is the structure that contains directory and fileinfo * structures. directory is the directory we are iterating over. It * is used here to build the filename name. fileinfo is a glib * structure that contains all meta data and more for a file. * @param filter is a structure containing all structures needed to filter * files as database, regex_exclude_list and contains a boolean * that is set to TRUE if the file has been filtered out and FALSE * otherwise. * @param opt are the selected options for the program. * @returns a newly allocated and filled meta_data_t * structure. */ static meta_data_t *get_meta_data_from_fileinfo(file_event_t *file_event, filter_file_t *filter, options_t *opt) { meta_data_t *meta = NULL; gchar *directory = NULL; GFileInfo *fileinfo = NULL; if (file_event != NULL) { directory = file_event->directory; fileinfo = file_event->fileinfo; } if (directory != NULL && fileinfo != NULL && filter != NULL && filter->database != NULL) { /* filling meta data for the file represented by fileinfo */ meta = new_meta_data_t(); meta->file_type = g_file_info_get_file_type(fileinfo); meta->name = g_build_path(G_DIR_SEPARATOR_S, directory, g_file_info_get_name(fileinfo), NULL); if (exclude_file(filter->regex_exclude_list, meta->name) == FALSE) { /* fills meta_data_t *meta structure */ get_file_attributes(meta, fileinfo); meta->blocksize = calculate_file_blocksize(opt, meta->size); /* We need to determine if the file has already been saved by looking into the local database * This is usefull only when carving directories at the begining of the process as when called * by m_fanotify we already know that the file was written and that something changed. */ meta->in_cache = is_file_in_cache(filter->database, meta); filter->excluded = FALSE; } else { filter->excluded = TRUE; } } return meta; }
static int zipfile_write_check (zfile *zf, int task, int *attr) { FILE *fp = NULL; char *fmode = "w"; int err = 0; /* Note: if task != ZIP_DO_NEW, then a NULL value for zfiles means that zf->fname is non-existent or empty, but if task == ZIP_DO_NEW we don't do an initial read of zf->fname, so zfiles will be NULL regardless; its value is uninformative. */ if (task == ZIP_DO_NEW) { /* overwriting: don't destroy the original archive until we're fairly confident we have a good replacement */ if (gretl_file_test(zf->fname, G_FILE_TEST_EXISTS)) { fmode = "r+"; } } else if (zfiles != NULL || zf->zstart != 0) { fmode = "r+"; } trace(2, "testing fopen on '%s', mode %s\n", zf->fname, fmode); fp = fopen(zf->fname, fmode); if (fp == NULL) { err = ziperr(ZE_CREAT, zf->fname); } else { fclose(fp); } *attr = get_file_attributes(zf->fname); if (task != ZIP_DO_NEW && zfiles == NULL && zf->zstart == 0) { trace(2, "removing old file '%s'\n", zf->fname); gretl_remove(zf->fname); } return err; }
int access(const char *filename, int mode) { char extension[_MAX_FNAME]; DWORD attribs; size_t extlen; const char *extptr; const char *begin, *end; int isx, hasext, trypathext = 0; /* once: get default PATHEXT or use empty exts */ if (!*exts) { DWORD rc; /* not initialized */ rc = GetEnvironmentVariable("PATHEXT", exts, sizeof(exts)); if ((rc == 0) || (rc >= sizeof(exts))) *exts = 0; } if (!filename) { errno = ENOENT; return (-1); } /* search for the extension starting at the end */ extptr = filename + strlen(filename) - 1; hasext = 0; while (extptr > filename && !ISPATHSEP(*extptr)) { if (*extptr == '.' && *(extptr - 1) != ':' && !ISPATHSEP(*(extptr - 1))) { hasext++; break; } extptr--; } if (hasext) attribs = get_file_attributes(filename, extptr, hasext, mode, &isx); else attribs = get_file_attributes(filename, "", hasext, mode, &isx); /* if mode != X_OK or file exists or filename already has an extension ignore PATHEXT */ if ((mode != X_OK) || (attribs != (DWORD)-1) || hasext) { begin = "."; end = ""; } else { /* dir/file name not found and no extension */ begin = exts; end = exts; trypathext = 1; } while (*begin) { if (trypathext) { extlen = pgetext(&begin, &end, extension, sizeof(extension)); if (!*begin) break; if (extlen) attribs = get_file_attributes(filename, extension, hasext, mode, &isx); else attribs = (DWORD)(-1); } if (attribs != (DWORD)(-1)) { /* file or directory found */ if (mode & X_OK) { if (attribs & FILE_ATTRIBUTE_DIRECTORY) break; /* appending pathext may find a directory ! */ if (trypathext || isx) return (0); break; } else if ((mode & W_OK) && (attribs & FILE_ATTRIBUTE_READONLY)) { break; } /* R_OK is always OK */ return (0); } begin = pgetnext(&begin, &end); } if (attribs == (DWORD)(-1)) errno = ENOENT; else errno = EACCES; return (-1); }
static NTSTATUS query_dir_item(fcb* fcb, ccb* ccb, void* buf, LONG* len, PIRP Irp, dir_entry* de, root* r) { PIO_STACK_LOCATION IrpSp; LONG needed; UINT64 inode; INODE_ITEM ii; NTSTATUS Status; ULONG atts = 0, ealen = 0; file_ref* fileref = ccb->fileref; IrpSp = IoGetCurrentIrpStackLocation(Irp); if (de->key.obj_type == TYPE_ROOT_ITEM) { // subvol LIST_ENTRY* le; r = NULL; le = fcb->Vcb->roots.Flink; while (le != &fcb->Vcb->roots) { root* subvol = CONTAINING_RECORD(le, root, list_entry); if (subvol->id == de->key.obj_id) { r = subvol; break; } le = le->Flink; } if (r && r->parent != fcb->subvol->id) r = NULL; inode = SUBVOL_ROOT_INODE; } else { inode = de->key.obj_id; } if (IrpSp->Parameters.QueryDirectory.FileInformationClass != FileNamesInformation) { // FIXME - object ID and reparse point classes too? switch (de->dir_entry_type) { case DirEntryType_File: { if (!r) { LARGE_INTEGER time; ii = fcb->Vcb->dummy_fcb->inode_item; atts = fcb->Vcb->dummy_fcb->atts; ealen = fcb->Vcb->dummy_fcb->ealen; KeQuerySystemTime(&time); win_time_to_unix(time, &ii.otime); ii.st_atime = ii.st_mtime = ii.st_ctime = ii.otime; } else { BOOL found = FALSE; if (de->dc && de->dc->fileref && de->dc->fileref->fcb) { ii = de->dc->fileref->fcb->inode_item; atts = de->dc->fileref->fcb->atts; ealen = de->dc->fileref->fcb->ealen; found = TRUE; } if (!found) { KEY searchkey; traverse_ptr tp; searchkey.obj_id = inode; searchkey.obj_type = TYPE_INODE_ITEM; searchkey.offset = 0xffffffffffffffff; Status = find_item(fcb->Vcb, r, &tp, &searchkey, FALSE, Irp); if (!NT_SUCCESS(Status)) { ERR("error - find_item returned %08x\n", Status); return Status; } if (tp.item->key.obj_id != searchkey.obj_id || tp.item->key.obj_type != searchkey.obj_type) { ERR("could not find inode item for inode %llx in root %llx\n", inode, r->id); return STATUS_INTERNAL_ERROR; } RtlZeroMemory(&ii, sizeof(INODE_ITEM)); if (tp.item->size > 0) RtlCopyMemory(&ii, tp.item->data, min(sizeof(INODE_ITEM), tp.item->size)); if (IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileFullDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation) { BOOL dotfile = de->name.Length > sizeof(WCHAR) && de->name.Buffer[0] == '.'; atts = get_file_attributes(fcb->Vcb, r, inode, de->type, dotfile, FALSE, Irp); } if (IrpSp->Parameters.QueryDirectory.FileInformationClass == FileBothDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileFullDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdBothDirectoryInformation || IrpSp->Parameters.QueryDirectory.FileInformationClass == FileIdFullDirectoryInformation) { ealen = get_ea_len(fcb->Vcb, r, inode, Irp); } } } break; } case DirEntryType_Self: ii = fcb->inode_item; r = fcb->subvol; inode = fcb->inode; atts = fcb->atts; ealen = fcb->ealen; break; case DirEntryType_Parent: if (fileref && fileref->parent) { ii = fileref->parent->fcb->inode_item; r = fileref->parent->fcb->subvol; inode = fileref->parent->fcb->inode; atts = fileref->parent->fcb->atts; ealen = fileref->parent->fcb->ealen; } else { ERR("no fileref\n"); return STATUS_INTERNAL_ERROR; } break; } if (atts == 0) atts = FILE_ATTRIBUTE_NORMAL; } switch (IrpSp->Parameters.QueryDirectory.FileInformationClass) { case FileBothDirectoryInformation: { FILE_BOTH_DIR_INFORMATION* fbdi = buf; TRACE("FileBothDirectoryInformation\n"); needed = sizeof(FILE_BOTH_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %u > %u\n", needed, *len); return STATUS_BUFFER_OVERFLOW; } fbdi->NextEntryOffset = 0; fbdi->FileIndex = 0; fbdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime); fbdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime); fbdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime); fbdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime); fbdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size; if (de->type == BTRFS_TYPE_SYMLINK) fbdi->AllocationSize.QuadPart = 0; else if (atts & FILE_ATTRIBUTE_SPARSE_FILE) fbdi->AllocationSize.QuadPart = ii.st_blocks; else fbdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size); fbdi->FileAttributes = atts; fbdi->FileNameLength = de->name.Length; fbdi->EaSize = (r && atts & FILE_ATTRIBUTE_REPARSE_POINT) ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp) : ealen; fbdi->ShortNameLength = 0; RtlCopyMemory(fbdi->FileName, de->name.Buffer, de->name.Length); *len -= needed; return STATUS_SUCCESS; } case FileDirectoryInformation: { FILE_DIRECTORY_INFORMATION* fdi = buf; TRACE("FileDirectoryInformation\n"); needed = sizeof(FILE_DIRECTORY_INFORMATION) - sizeof(WCHAR) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %u > %u\n", needed, *len); return STATUS_BUFFER_OVERFLOW; } fdi->NextEntryOffset = 0; fdi->FileIndex = 0; fdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime); fdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime); fdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime); fdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime); fdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size; if (de->type == BTRFS_TYPE_SYMLINK) fdi->AllocationSize.QuadPart = 0; else if (atts & FILE_ATTRIBUTE_SPARSE_FILE) fdi->AllocationSize.QuadPart = ii.st_blocks; else fdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size); fdi->FileAttributes = atts; fdi->FileNameLength = de->name.Length; RtlCopyMemory(fdi->FileName, de->name.Buffer, de->name.Length); *len -= needed; return STATUS_SUCCESS; } case FileFullDirectoryInformation: { FILE_FULL_DIR_INFORMATION* ffdi = buf; TRACE("FileFullDirectoryInformation\n"); needed = sizeof(FILE_FULL_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %u > %u\n", needed, *len); return STATUS_BUFFER_OVERFLOW; } ffdi->NextEntryOffset = 0; ffdi->FileIndex = 0; ffdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime); ffdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime); ffdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime); ffdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime); ffdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size; if (de->type == BTRFS_TYPE_SYMLINK) ffdi->AllocationSize.QuadPart = 0; else if (atts & FILE_ATTRIBUTE_SPARSE_FILE) ffdi->AllocationSize.QuadPart = ii.st_blocks; else ffdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size); ffdi->FileAttributes = atts; ffdi->FileNameLength = de->name.Length; ffdi->EaSize = (r && atts & FILE_ATTRIBUTE_REPARSE_POINT) ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp) : ealen; RtlCopyMemory(ffdi->FileName, de->name.Buffer, de->name.Length); *len -= needed; return STATUS_SUCCESS; } case FileIdBothDirectoryInformation: { FILE_ID_BOTH_DIR_INFORMATION* fibdi = buf; TRACE("FileIdBothDirectoryInformation\n"); needed = sizeof(FILE_ID_BOTH_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %u > %u\n", needed, *len); return STATUS_BUFFER_OVERFLOW; } fibdi->NextEntryOffset = 0; fibdi->FileIndex = 0; fibdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime); fibdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime); fibdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime); fibdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime); fibdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size; if (de->type == BTRFS_TYPE_SYMLINK) fibdi->AllocationSize.QuadPart = 0; else if (atts & FILE_ATTRIBUTE_SPARSE_FILE) fibdi->AllocationSize.QuadPart = ii.st_blocks; else fibdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size); fibdi->FileAttributes = atts; fibdi->FileNameLength = de->name.Length; fibdi->EaSize = (r && atts & FILE_ATTRIBUTE_REPARSE_POINT) ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp) : ealen; fibdi->ShortNameLength = 0; fibdi->FileId.QuadPart = r ? make_file_id(r, inode) : make_file_id(fcb->Vcb->dummy_fcb->subvol, fcb->Vcb->dummy_fcb->inode); RtlCopyMemory(fibdi->FileName, de->name.Buffer, de->name.Length); *len -= needed; return STATUS_SUCCESS; } case FileIdFullDirectoryInformation: { FILE_ID_FULL_DIR_INFORMATION* fifdi = buf; TRACE("FileIdFullDirectoryInformation\n"); needed = sizeof(FILE_ID_FULL_DIR_INFORMATION) - sizeof(WCHAR) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %u > %u\n", needed, *len); return STATUS_BUFFER_OVERFLOW; } fifdi->NextEntryOffset = 0; fifdi->FileIndex = 0; fifdi->CreationTime.QuadPart = unix_time_to_win(&ii.otime); fifdi->LastAccessTime.QuadPart = unix_time_to_win(&ii.st_atime); fifdi->LastWriteTime.QuadPart = unix_time_to_win(&ii.st_mtime); fifdi->ChangeTime.QuadPart = unix_time_to_win(&ii.st_ctime); fifdi->EndOfFile.QuadPart = de->type == BTRFS_TYPE_SYMLINK ? 0 : ii.st_size; if (de->type == BTRFS_TYPE_SYMLINK) fifdi->AllocationSize.QuadPart = 0; else if (atts & FILE_ATTRIBUTE_SPARSE_FILE) fifdi->AllocationSize.QuadPart = ii.st_blocks; else fifdi->AllocationSize.QuadPart = sector_align(ii.st_size, fcb->Vcb->superblock.sector_size); fifdi->FileAttributes = atts; fifdi->FileNameLength = de->name.Length; fifdi->EaSize = (r && atts & FILE_ATTRIBUTE_REPARSE_POINT) ? get_reparse_tag(fcb->Vcb, r, inode, de->type, atts, ccb->lxss, Irp) : ealen; fifdi->FileId.QuadPart = r ? make_file_id(r, inode) : make_file_id(fcb->Vcb->dummy_fcb->subvol, fcb->Vcb->dummy_fcb->inode); RtlCopyMemory(fifdi->FileName, de->name.Buffer, de->name.Length); *len -= needed; return STATUS_SUCCESS; } case FileNamesInformation: { FILE_NAMES_INFORMATION* fni = buf; TRACE("FileNamesInformation\n"); needed = sizeof(FILE_NAMES_INFORMATION) - sizeof(WCHAR) + de->name.Length; if (needed > *len) { TRACE("buffer overflow - %u > %u\n", needed, *len); return STATUS_BUFFER_OVERFLOW; } fni->NextEntryOffset = 0; fni->FileIndex = 0; fni->FileNameLength = de->name.Length; RtlCopyMemory(fni->FileName, de->name.Buffer, de->name.Length); *len -= needed; return STATUS_SUCCESS; } case FileObjectIdInformation: FIXME("STUB: FileObjectIdInformation\n"); return STATUS_NOT_IMPLEMENTED; case FileQuotaInformation: FIXME("STUB: FileQuotaInformation\n"); return STATUS_NOT_IMPLEMENTED; case FileReparsePointInformation: FIXME("STUB: FileReparsePointInformation\n"); return STATUS_NOT_IMPLEMENTED; default: WARN("Unknown FileInformationClass %u\n", IrpSp->Parameters.QueryDirectory.FileInformationClass); return STATUS_NOT_IMPLEMENTED; } return STATUS_NO_MORE_FILES; }
// 'top_level' is extracting the file for a single-file torrent. The // distinction is that the filename is found in "name" rather than // "path" // root_dir is the name of the torrent, unless this is a single file // torrent, in which case it's empty. bool extract_single_file(bdecode_node const& dict, file_storage& files , std::string const& root_dir, ptrdiff_t info_ptr_diff, bool top_level , int& pad_file_cnt, error_code& ec) { if (dict.type() != bdecode_node::dict_t) return false; boost::uint32_t file_flags = get_file_attributes(dict); // symlinks have an implied "size" of zero. i.e. they use up 0 bytes of // the torrent payload space boost::int64_t const file_size = (file_flags & file_storage::flag_symlink) ? 0 : dict.dict_find_int_value("length", -1); if (file_size < 0 ) { ec = errors::torrent_invalid_length; return false; } boost::int64_t const mtime = dict.dict_find_int_value("mtime", 0); std::string path = root_dir; std::string path_element; char const* filename = NULL; int filename_len = 0; if (top_level) { // prefer the name.utf-8 because if it exists, it is more likely to be // correctly encoded bdecode_node p = dict.dict_find_string("name.utf-8"); if (!p) p = dict.dict_find_string("name"); if (!p || p.string_length() == 0) { ec = errors::torrent_missing_name; return false; } filename = p.string_ptr() + info_ptr_diff; filename_len = p.string_length(); while (filename_len > 0 && filename[0] == TORRENT_SEPARATOR) { filename += 1; filename_len -= 1; } sanitize_append_path_element(path, p.string_ptr(), p.string_length()); } else { bdecode_node p = dict.dict_find_list("path.utf-8"); if (!p) p = dict.dict_find_list("path"); if (p && p.list_size() > 0) { std::size_t const orig_path_len = path.size(); int const preallocate = path.size() + path_length(p, ec); if (ec) return false; path.reserve(preallocate); for (int i = 0, end(p.list_size()); i < end; ++i) { bdecode_node e = p.list_at(i); if (i == end - 1) { filename = e.string_ptr() + info_ptr_diff; filename_len = e.string_length(); } while (filename_len > 0 && filename[0] == TORRENT_SEPARATOR) { filename += 1; filename_len -= 1; } sanitize_append_path_element(path, e.string_ptr(), e.string_length()); } // if all path elements were sanitized away, we need to use another // name instead if (path.size() == orig_path_len) { path += TORRENT_SEPARATOR; path += "_"; } } else if (file_flags & file_storage::flag_pad_file) { // pad files don't need a path element, we'll just store them // under the .pad directory char cnt[10]; snprintf(cnt, sizeof(cnt), "%d", pad_file_cnt); path = combine_path(".pad", cnt); ++pad_file_cnt; } else { ec = errors::torrent_missing_name; return false; } } // bitcomet pad file if (path.find("_____padding_file_") != std::string::npos) file_flags = file_storage::flag_pad_file; bdecode_node fh = dict.dict_find_string("sha1"); char const* filehash = NULL; if (fh && fh.string_length() == 20) filehash = fh.string_ptr() + info_ptr_diff; std::string symlink_path; if (file_flags & file_storage::flag_symlink) { if (bdecode_node s_p = dict.dict_find_list("symlink path")) { int const preallocate = path_length(s_p, ec); if (ec) return false; symlink_path.reserve(preallocate); for (int i = 0, end(s_p.list_size()); i < end; ++i) { bdecode_node const& n = s_p.list_at(i); sanitize_append_path_element(symlink_path, n.string_ptr() , n.string_length()); } } } else { file_flags &= ~file_storage::flag_symlink; } if (filename_len > path.length() || path.compare(path.size() - filename_len, filename_len, filename , filename_len) != 0) { // if the filename was sanitized and differ, clear it to just use path filename = NULL; filename_len = 0; } files.add_file_borrow(filename, filename_len, path, file_size, file_flags, filehash , mtime, symlink_path); return true; }
void convert_values( extended_info **ei ) { extended_info *l_ei = *ei; column_info *t_ci = g_ci; int buf_count = 0; wchar_t *format = NULL; for ( unsigned long i = 0; i < g_column_count; ++i ) { // Stop processing and exit the thread. if ( g_kill_scan == true ) { break; } if ( t_ci != NULL ) { // Create a shared extended info structure to share the Windows Property names across entries. if ( t_ci->sei == NULL ) { t_ci->sei = ( shared_extended_info * )malloc( sizeof( shared_extended_info ) ); t_ci->sei->count = 0; t_ci->sei->windows_property = ( wchar_t * )malloc( sizeof( char ) * ( t_ci->Name_byte_length + sizeof( wchar_t ) ) ); memcpy_s( t_ci->sei->windows_property, sizeof( char ) * ( t_ci->Name_byte_length + sizeof( wchar_t ) ), t_ci->Name, t_ci->Name_byte_length ); t_ci->sei->windows_property[ t_ci->Name_byte_length / sizeof( wchar_t ) ] = 0; // Sanity. } ++( t_ci->sei->count ); extended_info *t_ei = ( extended_info * )malloc( sizeof( extended_info ) ); t_ei->sei = t_ci->sei; t_ei->property_value = NULL; t_ei->next = NULL; // See if the property value was retrieved. if ( g_rc_array[ i ].cbActual != 0 && g_rc_array[ i ].cbActual <= t_ci->max_size ) { switch ( t_ci->column_type ) { case JET_coltypBit: { // Handles Type(s): VT_BOOL if ( t_ci->Type == VT_BOOL ) // bool (true == -1, false == 0) { buf_count = ( t_ci->data[ 0 ] != 0 ? 4 : 5 ); // "true" or "false" t_ei->property_value = ( wchar_t * )malloc( sizeof( wchar_t ) * ( buf_count + 1 ) ); wcscpy_s( t_ei->property_value, buf_count + 1, ( t_ci->data[ 0 ] != 0 ? L"true" : L"false" ) ); break; } // For anything else, fall through to JET_coltypUnsignedByte } case JET_coltypUnsignedByte: { // Handles Type(s): VT_I1, VT_UI1, anything else from JET_coltypBit format = ( t_ci->Type == VT_I1 ? L"%d" : L"%lu" ); buf_count = _scwprintf( format, t_ci->data[ 0 ] ); if ( buf_count > 0 ) { t_ei->property_value = ( wchar_t * )malloc( sizeof( wchar_t ) * ( buf_count + 1 ) ); swprintf_s( t_ei->property_value, buf_count + 1, format, t_ci->data[ 0 ] ); } } break; case JET_coltypShort: case JET_coltypUnsignedShort: { // Handles Type(s): VT_UI2 unsigned short val = 0; memcpy_s( &val, sizeof( unsigned short ), t_ci->data, sizeof( unsigned short ) ); format = ( t_ci->column_type == JET_coltypShort ? L"%d" : L"%lu" ); buf_count = _scwprintf( format, val ); if ( buf_count > 0 ) { t_ei->property_value = ( wchar_t * )malloc( sizeof( wchar_t ) * ( buf_count + 1 ) ); swprintf_s( t_ei->property_value, buf_count + 1, format, val ); } } break; case JET_coltypLong: case JET_coltypUnsignedLong: { // Handles Type(s): VT_I4, VT_UI4 unsigned long val = 0; memcpy_s( &val, sizeof( unsigned long ), t_ci->data, sizeof( unsigned long ) ); if ( t_ci->Name_byte_length == 42 && wcscmp( t_ci->Name, L"System_FileAttributes" ) == 0 ) { t_ei->property_value = get_file_attributes( val ); } else if ( ( t_ci->Name_byte_length == 34 && wcscmp( t_ci->Name, L"System_SFGAOFlags" ) == 0 ) || ( t_ci->Name_byte_length == 56 && wcscmp( t_ci->Name, L"System_Link_TargetSFGAOFlags" ) == 0 ) ) { t_ei->property_value = get_sfgao( val ); } else { format = ( t_ci->column_type == JET_coltypLong ? L"%d" : L"%lu" ); buf_count = _scwprintf( format, val ); if ( buf_count > 0 ) { t_ei->property_value = ( wchar_t * )malloc( sizeof( wchar_t ) * ( buf_count + 1 ) ); swprintf_s( t_ei->property_value, buf_count + 1, format, val ); } } } break; case JET_coltypIEEEDouble: { // Handles Type(s): VT_R8 double val = 0.0f; memcpy_s( &val, sizeof( double ), t_ci->data, sizeof( double ) ); buf_count = _scwprintf( L"%f", val ); if ( buf_count > 0 ) { t_ei->property_value = ( wchar_t * )malloc( sizeof( wchar_t ) * ( buf_count + 1 ) ); swprintf_s( t_ei->property_value, buf_count + 1, L"%f", val ); } } break; case JET_coltypCurrency: case JET_coltypBinary: // May be compressed. We'll fall through to JET_coltypLongBinary to handle uncompressing it. case JET_coltypLongLong: { // Handles Type(s): VT_FILETIME, VT_UI8, VT_LPWSTR unsigned long long val = 0; memcpy_s( &val, sizeof( unsigned long long ), t_ci->data, sizeof( unsigned long long ) ); if ( g_use_big_endian == true ) { val = ntohll( val ); } if ( t_ci->Type == VT_FILETIME ) // FILETIME { SYSTEMTIME st; FILETIME ft; ft.dwLowDateTime = ( DWORD )val; ft.dwHighDateTime = ( DWORD )( val >> 32 ); FileTimeToSystemTime( &ft, &st ); buf_count = _scwprintf( L"%d/%d/%d (%02d:%02d:%02d.%d) [UTC]", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds ); if ( buf_count > 0 ) { t_ei->property_value = ( wchar_t * )malloc( sizeof( wchar_t ) * ( buf_count + 1 ) ); swprintf_s( t_ei->property_value, buf_count + 1, L"%d/%d/%d (%02d:%02d:%02d.%d) [UTC]", st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds ); } break; } else { if ( t_ci->Name_byte_length == 22 && wcscmp( t_ci->Name, L"System_Size" ) == 0 ) { buf_count = _scwprintf( L"%llu", val ); if ( buf_count > 0 ) { t_ei->property_value = ( wchar_t * )malloc( sizeof( wchar_t ) * ( buf_count + 6 + 1 ) ); swprintf_s( t_ei->property_value, buf_count + 6 + 1, L"%llu bytes", val ); } break; } else if ( t_ci->Name_byte_length == 46 && wcscmp( t_ci->Name, L"System_ThumbnailCacheId" ) == 0 ) { t_ei->property_value = ( wchar_t * )malloc( sizeof( wchar_t ) * 17 ); swprintf_s( t_ei->property_value, 17, L"%016llx", val ); break; } else if ( t_ci->Name_byte_length == 30 && wcscmp( t_ci->Name, L"InvertedOnlyMD5" ) == 0 ) { // Output hex values. unsigned long property_value_offset = 0; buf_count = ( ( g_rc_array[ i ].cbActual * 2 ) + 1 ); t_ei->property_value = ( wchar_t * )malloc( sizeof( wchar_t ) * buf_count ); for ( unsigned long h = 0; h < g_rc_array[ i ].cbActual; ++h ) { property_value_offset += swprintf_s( t_ei->property_value + property_value_offset, buf_count - property_value_offset, L"%02x", t_ci->data[ h ] ); } break; } else { if ( t_ci->JetCompress == false ) { // Handle 8 byte values. For everything else, fall through. if ( g_rc_array[ i ].cbActual == sizeof( unsigned long long ) ) { format = ( t_ci->column_type == JET_coltypLongLong ? L"%lld" : L"%llu" ); buf_count = _scwprintf( format, val ); if ( buf_count > 0 ) { t_ei->property_value = ( wchar_t * )malloc( sizeof( wchar_t ) * ( buf_count + 1 ) ); swprintf_s( t_ei->property_value, buf_count + 1, format, val ); } break; } } // Fall through to JET_coltypLongBinary. } } } case JET_coltypText: case JET_coltypLongBinary: case JET_coltypLongText: case JET_coltypGUID: { // Handles Type(s): VT_NULL, VT_LPWSTR, ( VT_VECTOR | VT_LPWSTR ), VT_BLOB, anything else from JET_coltypBinary if ( t_ci->column_type == JET_coltypGUID ) { if ( g_rc_array[ i ].cbActual == 16 ) { // Output GUID formatted value. unsigned long val_1 = 0; unsigned short val_2 = 0, val_3 = 0; memcpy_s( &val_1, sizeof( unsigned long ), t_ci->data, sizeof( unsigned long ) ); memcpy_s( &val_2, sizeof( unsigned short ), t_ci->data + sizeof( unsigned long ), sizeof( unsigned short ) ); memcpy_s( &val_3, sizeof( unsigned short ), t_ci->data + sizeof( unsigned long ) + sizeof( unsigned short ), sizeof( unsigned short ) ); buf_count = ( ( g_rc_array[ i ].cbActual * 2 ) + 6 + 1 ); t_ei->property_value = ( wchar_t * )malloc( sizeof( wchar_t ) * buf_count ); unsigned long property_value_offset = swprintf_s( t_ei->property_value, buf_count, L"{%04x-%02x-%02x-", val_1, val_2, val_3 ); for ( unsigned long h = sizeof( unsigned long ) + ( sizeof( unsigned short ) * 2 ); h < g_rc_array[ i ].cbActual; ++h ) { if ( h == 10 ) { t_ei->property_value[ property_value_offset ] = L'-'; ++property_value_offset; } property_value_offset += swprintf_s( t_ei->property_value + property_value_offset, buf_count - property_value_offset, L"%02x", t_ci->data[ h ] ); } t_ei->property_value[ buf_count - 2 ] = L'}'; t_ei->property_value[ buf_count - 1 ] = 0; // Sanity. break; } // Fall through to default. } else { // On Vista, if Type == ( VT_VECTOR | VT_LPWSTR ), then the first 2 bytes (little-endian) = array count? if ( t_ci->JetCompress == true ) { // Make a copy first because we may need to reuse t_ci->data and don't want it modified. unsigned char *data_copy = ( unsigned char * )malloc( sizeof( unsigned char ) * g_rc_array[ i ].cbActual ); memcpy_s( data_copy, sizeof( unsigned char ) * g_rc_array[ i ].cbActual, t_ci->data, g_rc_array[ i ].cbActual ); t_ei->property_value = uncompress_value( data_copy, g_rc_array[ i ].cbActual ); free( data_copy ); break; } else { if ( t_ci->Name_byte_length == 32 && wcscmp( t_ci->Name, L"InvertedOnlyPids" ) == 0 ) { // Output hex values. unsigned long property_value_offset = 0; buf_count = ( ( g_rc_array[ i ].cbActual * 2 ) + 1 ); t_ei->property_value = ( wchar_t * )malloc( sizeof( wchar_t ) * buf_count ); for ( unsigned long h = 0; h < g_rc_array[ i ].cbActual; ++h ) { property_value_offset += swprintf_s( t_ei->property_value + property_value_offset, buf_count - property_value_offset, L"%02x", t_ci->data[ h ] ); } break; } // Fall through to default. } } } default: { // This is usually wchar strings. t_ei->property_value = ( wchar_t * )malloc( sizeof( char ) * ( g_rc_array[ i ].cbActual + sizeof( wchar_t ) ) ); // Include the NULL terminator. memcpy_s( t_ei->property_value, sizeof( char ) * ( g_rc_array[ i ].cbActual + sizeof( wchar_t ) ), t_ci->data, g_rc_array[ i ].cbActual ); unsigned long property_value_size = g_rc_array[ i ].cbActual / sizeof( wchar_t ); t_ei->property_value[ property_value_size ] = 0; // Sanity. // See if we have any string arrays. if ( wcslen( t_ei->property_value ) < property_value_size ) { // Replace the NULL character at the end of each string (except the last) with a ';' separator. wchar_t *t_val = t_ei->property_value; while ( t_val < ( t_ei->property_value + property_value_size ) ) { if ( *t_val == 0 ) { *t_val = L';'; } ++t_val; } } } break; } } if ( l_ei != NULL ) { l_ei->next = t_ei; } else { *ei = t_ei; } l_ei = t_ei; // Go to the next Windows property. t_ci = t_ci->next; }