Example #1
0
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;
}
Example #2
0
		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);
		}
Example #3
0
/**
 * 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;
}
Example #4
0
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;
}
Example #5
0
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);
}
Example #6
0
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;
	}
Example #8
0
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;
		}