Exemplo n.º 1
0
Status DeleteDirectory(const OsPath& path)
{
	// note: we have to recursively empty the directory before it can
	// be deleted (required by Windows and POSIX rmdir()).

	CFileInfos files; DirectoryNames subdirectoryNames;
	RETURN_STATUS_IF_ERR(GetDirectoryEntries(path, &files, &subdirectoryNames));

	// delete files
	for(size_t i = 0; i < files.size(); i++)
	{
		const OsPath pathname = path / files[i].Name();
		errno = 0;
		if(wunlink(pathname) != 0)
			WARN_RETURN(StatusFromErrno());
	}

	// recurse over subdirectoryNames
	for(size_t i = 0; i < subdirectoryNames.size(); i++)
		RETURN_STATUS_IF_ERR(DeleteDirectory(path / subdirectoryNames[i]));

	errno = 0;
	if(wrmdir(path) != 0)
		WARN_RETURN(StatusFromErrno());

	return INFO::OK;
}
Exemplo n.º 2
0
static Status load_sys_cursor(const PIVFS& vfs, const VfsPath& pathname, int hx, int hy, sys_cursor* cursor)
{
#if !ALLOW_SYS_CURSOR
	UNUSED2(vfs);
	UNUSED2(pathname);
	UNUSED2(hx);
	UNUSED2(hy);
	UNUSED2(cursor);

	return ERR::FAIL;
#else
	shared_ptr<u8> file; size_t fileSize;
	RETURN_STATUS_IF_ERR(vfs->LoadFile(pathname, file, fileSize));

	Tex t;
	RETURN_STATUS_IF_ERR(t.decode(file, fileSize));

	// convert to required BGRA format.
	const size_t flags = (t.m_Flags | TEX_BGR) & ~TEX_DXT;
	RETURN_STATUS_IF_ERR(t.transform_to(flags));
	void* bgra_img = t.get_data();
	if(!bgra_img)
		WARN_RETURN(ERR::FAIL);

	RETURN_STATUS_IF_ERR(sys_cursor_create((int)t.m_Width, (int)t.m_Height, bgra_img, hx, hy, cursor));
	return INFO::OK;
#endif
}
Exemplo n.º 3
0
Status UnalignedWriter::Append(const u8* data, size_t size) const
{
	while(size != 0)
	{
		// optimization: write directly from the input buffer, if possible
		const size_t alignedSize = (size / BLOCK_SIZE) * BLOCK_SIZE;
		if(m_bytesUsed == 0 && IsAligned(data, maxSectorSize) && alignedSize != 0)
		{
			io::Operation op(*m_file.get(), (void*)data, alignedSize, m_alignedOfs);
			RETURN_STATUS_IF_ERR(io::Run(op));
			m_alignedOfs += (off_t)alignedSize;
			data += alignedSize;
			size -= alignedSize;
		}

		const size_t chunkSize = std::min(size, BLOCK_SIZE-m_bytesUsed);
		memcpy(m_alignedBuf.get()+m_bytesUsed, data, chunkSize);
		m_bytesUsed += chunkSize;
		data += chunkSize;
		size -= chunkSize;

		if(m_bytesUsed == BLOCK_SIZE)
			RETURN_STATUS_IF_ERR(WriteBlock());
	}

	return INFO::OK;
}
Exemplo n.º 4
0
Status OpenOggStream(const OsPath& pathname, OggStreamPtr& stream)
{
	PFile file(new File);
    RETURN_STATUS_IF_ERR(file->Open(pathname, L'r'));

	shared_ptr<OggStreamImpl<VorbisFileAdapter> > tmp(new OggStreamImpl<VorbisFileAdapter>(VorbisFileAdapter(file)));
	RETURN_STATUS_IF_ERR(tmp->Open());
	stream = tmp;
	return INFO::OK;
}
Exemplo n.º 5
0
Status OpenOggNonstream(const PIVFS& vfs, const VfsPath& pathname, OggStreamPtr& stream)
{
	shared_ptr<u8> contents;
	size_t size;
	RETURN_STATUS_IF_ERR(vfs->LoadFile(pathname, contents, size));

	shared_ptr<OggStreamImpl<VorbisBufferAdapter> > tmp(new OggStreamImpl<VorbisBufferAdapter>(VorbisBufferAdapter(contents, size)));
	RETURN_STATUS_IF_ERR(tmp->Open());
	stream = tmp;
	return INFO::OK;
}
Exemplo n.º 6
0
	Status Activate()
	{
		RETURN_STATUS_IF_ERR(MapRegisters(m_hpetRegisters));

		RETURN_STATUS_IF_ERR(VerifyCapabilities(m_frequency, m_counterBits));

		// start the counter (if not already running)
		Write64(CONFIG, Read64(CONFIG)|1);
		// note: to avoid interfering with any other users of the timer
		// (e.g. Vista QPC), we don't reset the counter value to 0.

		return INFO::OK;
	}
Exemplo n.º 7
0
Status da_append(DynArray* da, const void* data, size_t size)
{
	RETURN_STATUS_IF_ERR(da_reserve(da, size));
	memcpy(da->base+da->pos, data, size);
	da->pos += size;
	return INFO::OK;
}
Exemplo n.º 8
0
Status da_reserve(DynArray* da, size_t size)
{
	if(da->pos+size > da->cur_size_pa)
		RETURN_STATUS_IF_ERR(da_set_size(da, da->cur_size_pa+size));
	da->cur_size = std::max(da->cur_size, da->pos+size);
	return INFO::OK;
}
Exemplo n.º 9
0
Status CreateDirectories(const OsPath& path, mode_t mode, bool breakpoint)
{
	if(path.empty())
		return INFO::OK;

	struct stat s;
	if(wstat(path, &s) == 0)
	{
		if(!S_ISDIR(s.st_mode))	// encountered a file
			WARN_RETURN(ERR::FAIL);
		return INFO::OK;
	}

	// If we were passed a path ending with '/', strip the '/' now so that
	// we can consistently use Parent to find parent directory names
	if(path.IsDirectory())
		return CreateDirectories(path.Parent(), mode, breakpoint);

	RETURN_STATUS_IF_ERR(CreateDirectories(path.Parent(), mode));

	errno = 0;
	if(wmkdir(path, mode) != 0)
	{
		debug_printf("CreateDirectories: failed to mkdir %s (mode %d)\n", path.string8().c_str(), mode);
		if (breakpoint)
			WARN_RETURN(StatusFromErrno());
		else
			return StatusFromErrno();
	}

	return INFO::OK;
}
Exemplo n.º 10
0
static Handle reuse_existing_handle(uintptr_t key, H_Type type, size_t flags)
{
	if(flags & RES_NO_CACHE)
		return 0;

	// object of specified key and type doesn't exist yet
	Handle h = h_find(type, key);
	if(h <= 0)
		return 0;

	HDATA* hd;
	RETURN_STATUS_IF_ERR(h_data_tag_type(h, type, hd));	// h_find means this won't fail

	hd->refs += 1;

	// we are reactivating a closed but cached handle.
	// need to generate a new tag so that copies of the
	// previous handle can no longer access the resource.
	// (we don't need to reset the tag in h_free, because
	// use before this fails due to refs > 0 check in h_user_data).
	if(hd->refs == 1)
	{
		const Tag tag = gen_tag();
		h = handle(h_idx(h), tag);	// can't fail
		hd->h = h;
	}

	return h;
}
Exemplo n.º 11
0
	virtual Status GetFilePriority(const VfsPath& pathname, size_t* ppriority) const
	{
		ScopedLock s;
		VfsDirectory* directory; VfsFile* file;
		RETURN_STATUS_IF_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, &file));
		*ppriority = file->Priority();
		return INFO::OK;
	}
Exemplo n.º 12
0
// retrieve the internal reference count or a negative error code.
// background: since h_alloc has no way of indicating whether it
// allocated a new handle or reused an existing one, counting references
// within resource control blocks is impossible. since that is sometimes
// necessary (always wrapping objects in Handles is excessive), we
// provide access to the internal reference count.
intptr_t h_get_refcnt(Handle h)
{
	HDATA* hd;
	RETURN_STATUS_IF_ERR(h_data_tag(h, hd));

	ENSURE(hd->refs);	// if there are no refs, how did the caller manage to keep a Handle?!
	return hd->refs;
}
Exemplo n.º 13
0
Status UnalignedWriter::WriteBlock() const
{
	io::Operation op(*m_file.get(), m_alignedBuf.get(), BLOCK_SIZE, m_alignedOfs);
	RETURN_STATUS_IF_ERR(io::Run(op));
	m_alignedOfs += BLOCK_SIZE;
	m_bytesUsed = 0;
	return INFO::OK;
}
Exemplo n.º 14
0
	virtual Status Mount(const VfsPath& mountPoint, const OsPath& path, size_t flags /* = 0 */, size_t priority /* = 0 */)
	{
		ScopedLock s;
		if(!DirectoryExists(path))
		{
			if(flags & VFS_MOUNT_MUST_EXIST)
				return ERR::VFS_DIR_NOT_FOUND;	// NOWARN
			else
				RETURN_STATUS_IF_ERR(CreateDirectories(path, 0700));
		}

		VfsDirectory* directory;
		WARN_RETURN_STATUS_IF_ERR(vfs_Lookup(mountPoint, &m_rootDirectory, directory, 0, VFS_LOOKUP_ADD|VFS_LOOKUP_SKIP_POPULATE));

		PRealDirectory realDirectory(new RealDirectory(path, priority, flags));
		RETURN_STATUS_IF_ERR(vfs_Attach(directory, realDirectory));
		return INFO::OK;
	}
Exemplo n.º 15
0
	virtual Status GetVirtualPath(const OsPath& realPathname, VfsPath& pathname)
	{
		ScopedLock s;
		const OsPath realPath = realPathname.Parent()/"";
		VfsPath path;
		RETURN_STATUS_IF_ERR(FindRealPathR(realPath, m_rootDirectory, L"", path));
		pathname = path / realPathname.Filename();
		return INFO::OK;
	}
Exemplo n.º 16
0
// (moved into a separate function to simplify error handling)
static inline Status ActivateCounter(ICounter* counter)
{
	RETURN_STATUS_IF_ERR(counter->Activate());

	if(!counter->IsSafe())
		return ERR::WHRT_COUNTER_UNSAFE;	// NOWARN (happens often)

	return INFO::OK;
}
Exemplo n.º 17
0
Status GetDirectoryEntries(const OsPath& path, CFileInfos* files, DirectoryNames* subdirectoryNames)
{
	// open directory
	errno = 0;
	WDIR* pDir = wopendir(path);
	if(!pDir)
		return StatusFromErrno();	// NOWARN
	shared_ptr<WDIR> osDir(pDir, DirDeleter());

	for(;;)
	{
		errno = 0;
		struct wdirent* osEnt = wreaddir(osDir.get());
		if(!osEnt)
		{
			// no error, just no more entries to return
			if(!errno)
				return INFO::OK;
			WARN_RETURN(StatusFromErrno());
		}

		for(size_t i = 0; osEnt->d_name[i] != '\0'; i++)
			RETURN_STATUS_IF_ERR(Path::Validate(osEnt->d_name[i]));
		const OsPath name(osEnt->d_name);

		// get file information (mode, size, mtime)
		struct stat s;
#if OS_WIN
		// .. return wdirent directly (much faster than calling stat).
		RETURN_STATUS_IF_ERR(wreaddir_stat_np(osDir.get(), &s));
#else
		// .. call regular stat().
		errno = 0;
		const OsPath pathname = path / name;
		if(wstat(pathname, &s) != 0)
			WARN_RETURN(StatusFromErrno());
#endif

		if(files && S_ISREG(s.st_mode))
			files->push_back(CFileInfo(name, s.st_size, s.st_mtime));
		else if(subdirectoryNames && S_ISDIR(s.st_mode) && name != L"." && name != L"..")
			subdirectoryNames->push_back(name);
	}
}
Exemplo n.º 18
0
Arquivo: pool.cpp Projeto: 2asoft/0ad
Status pool_create(Pool* p, size_t max_size, size_t el_size)
{
	if(el_size == POOL_VARIABLE_ALLOCS)
		p->el_size = 0;
	else
		p->el_size = Align<allocationAlignment>(el_size);
	p->freelist = mem_freelist_Sentinel();
	RETURN_STATUS_IF_ERR(da_alloc(&p->da, max_size));
	return INFO::OK;
}
Exemplo n.º 19
0
	virtual Status RepopulateDirectory(const VfsPath& path)
	{
		ScopedLock s;

		VfsDirectory* directory;
		RETURN_STATUS_IF_ERR(vfs_Lookup(path, &m_rootDirectory, directory, 0));
		directory->RequestRepopulate();

		return INFO::OK;
	}
Exemplo n.º 20
0
// get HDATA for the given handle.
// only uses (and checks) the index field.
// used by h_force_close (which must work regardless of tag).
static inline Status h_data_no_tag(const Handle h, HDATA*& hd)
{
	ssize_t idx = (ssize_t)h_idx(h);
	RETURN_STATUS_IF_ERR(h_data_from_idx(idx, hd));
	// need to verify it's in range - h_data_from_idx can only verify that
	// it's < maximum allowable index.
	if(uintptr_t(hd) > uintptr_t(hpool.da.base)+hpool.da.pos)
		WARN_RETURN(ERR::H_IDX_UNUSED);
	return INFO::OK;
}
Exemplo n.º 21
0
	virtual Status RemoveFile(const VfsPath& pathname)
	{
		ScopedLock s;
		m_fileCache.Remove(pathname);

		VfsDirectory* directory; VfsFile* file;
		RETURN_STATUS_IF_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, &file));
		directory->RemoveFile(file->Name());

		return INFO::OK;
	}
Exemplo n.º 22
0
// any further params are passed to type's init routine
Handle h_alloc(H_Type type, const PIVFS& vfs, const VfsPath& pathname, size_t flags, ...)
{
	H_ScopedLock s;

	RETURN_STATUS_IF_ERR(type_validate(type));

	const uintptr_t key = fnv_hash(pathname.string().c_str(), pathname.string().length()*sizeof(pathname.string()[0]));

	// see if we can reuse an existing handle
	Handle h = reuse_existing_handle(key, type, flags);
	RETURN_STATUS_IF_ERR(h);
	// .. successfully reused the handle; refcount increased
	if(h > 0)
		return h;
	// .. need to allocate a new one:
	va_list args;
	va_start(args, flags);
	h = alloc_new_handle(type, vfs, pathname, key, flags, &args);
	va_end(args);
	return h;	// alloc_new_handle already does WARN_RETURN_STATUS_IF_ERR
}
Exemplo n.º 23
0
Status sys_cursor_create(int w, int h, void* bgra_img, int hx, int hy, sys_cursor* cursor)
{
	// alpha-blended cursors do not work on a 16-bit display
	// (they get drawn as a black square), so refuse to load the
	// cursor in that case
	int bpp = 0;
	RETURN_STATUS_IF_ERR(gfx::GetVideoMode(NULL, NULL, &bpp, NULL));
	if (bpp <= 16)
		return ERR::FAIL;

	return sys_cursor_create_common(w, h, bgra_img, NULL, hx, hy, cursor);
}
Exemplo n.º 24
0
static Status InitStructures()
{
#if OS_WIN
	wfirmware::Table table;
	RETURN_STATUS_IF_ERR(GetTable(table));
#else
	std::vector<u8> table;
	return ERR::NOT_SUPPORTED;
#endif

	// (instead of counting the total string size, just use the
	// SMBIOS size - typically 1-2 KB - as an upper bound.)
	stringStoragePos = stringStorage = (char*)calloc(table.size(), sizeof(char));	// freed in Cleanup
	if(!stringStorage)
		WARN_RETURN(ERR::NO_MEM);

	atexit(Cleanup);

	const Header* header = (const Header*)&table[0];
	const Header* const end = (const Header*)(&table[0] + table.size());
	for(;;)
	{
		if(header+1 > end)
		{
			debug_printf("SMBIOS: table not terminated\n");
			break;
		}
		if(header->id == 127)	// end
			break;
		if(header->length < sizeof(Header))
			return ERR::_3; // NOWARN (happens on some unknown BIOS, see http://trac.wildfiregames.com/ticket/2985)

		const Header* next;
		const Strings strings = ExtractStrings(header, (const char*)end, next);

		switch(header->id)
		{
#define STRUCTURE(name, id) case id: AddStructure(header, strings, structures.name##_); break;
			STRUCTURES
#undef STRUCTURE

		default:
			if(32 < header->id && header->id < 126)	// only mention non-proprietary structures of which we are not aware
				debug_printf("SMBIOS: unknown structure type %d\n", header->id);
			break;
		}

		header = next;
	}

	return INFO::OK;
}
Exemplo n.º 25
0
// get HDATA for the given handle.
// also verifies the type.
// used by most functions accessing handle data.
static Status h_data_tag_type(const Handle h, const H_Type type, HDATA*& hd)
{
	RETURN_STATUS_IF_ERR(h_data_tag(h, hd));

	// h_alloc makes sure type isn't 0, so no need to check that here.
	if(hd->type != type)
	{
		debug_printf(L"h_mgr: expected type %ls, got %ls\n", hd->type->name, type->name);
		WARN_RETURN(ERR::H_TYPE_MISMATCH);
	}

	return INFO::OK;
}
Exemplo n.º 26
0
// force the resource to be freed immediately, even if cached.
// tag is not checked - this allows the first Handle returned
// (whose tag will change after being 'freed', but remaining in memory)
// to later close the object.
// this is used when reinitializing the sound engine -
// at that point, all (cached) OpenAL resources must be freed.
Status h_force_free(Handle h, H_Type type)
{
	H_ScopedLock s;

	// require valid index; ignore tag; type checked below.
	HDATA* hd;
	RETURN_STATUS_IF_ERR(h_data_no_tag(h, hd));
	if(hd->type != type)
		WARN_RETURN(ERR::H_TYPE_MISMATCH);
	hd->keep_open = 0;
	hd->refs = 0;
	h_free_hd(hd);
	return INFO::OK;
}
Exemplo n.º 27
0
	virtual Status LoadFile(const VfsPath& pathname, shared_ptr<u8>& fileContents, size_t& size)
	{
		ScopedLock s;
		const bool isCacheHit = m_fileCache.Retrieve(pathname, fileContents, size);
		if(!isCacheHit)
		{
			VfsDirectory* directory; VfsFile* file;
			// per 2010-05-01 meeting, this shouldn't raise 'scary error
			// dialogs', which might fail to display the culprit pathname
			// instead, callers should log the error, including pathname.
			RETURN_STATUS_IF_ERR(vfs_Lookup(pathname, &m_rootDirectory, directory, &file));

			fileContents = DummySharedPtr((u8*)0);
			size = file->Size();
			if(size != 0)	// (the file cache can't handle zero-length allocations)
			{
				if(size < m_cacheSize/2)	// (avoid evicting lots of previous data)
					fileContents = m_fileCache.Reserve(size);
				if(fileContents)
				{
					RETURN_STATUS_IF_ERR(file->Loader()->Load(file->Name(), fileContents, file->Size()));
					m_fileCache.Add(pathname, fileContents, size);
				}
				else
				{
					RETURN_STATUS_IF_ERR(AllocateAligned(fileContents, size, maxSectorSize));
					RETURN_STATUS_IF_ERR(file->Loader()->Load(file->Name(), fileContents, file->Size()));
				}
			}
		}

		stats_io_user_request(size);
		stats_cache(isCacheHit? CR_HIT : CR_MISS, size);
		m_trace->NotifyLoad(pathname, size);

		return INFO::OK;
	}
Exemplo n.º 28
0
Status ForEachFile(const PIVFS& fs, const VfsPath& startPath, FileCallback cb, uintptr_t cbData, const wchar_t* pattern, size_t flags)
{
	// (declare here to avoid reallocations)
	CFileInfos files;
	DirectoryNames subdirectoryNames;

	// (a FIFO queue is more efficient than recursion because it uses less
	// stack space and avoids seeks due to breadth-first traversal.)
	std::queue<VfsPath> pendingDirectories;
	pendingDirectories.push(startPath/"");
	while(!pendingDirectories.empty())
	{
		const VfsPath& path = pendingDirectories.front();

		RETURN_STATUS_IF_ERR(fs->GetDirectoryEntries(path, &files, &subdirectoryNames));

		for(size_t i = 0; i < files.size(); i++)
		{
			const CFileInfo fileInfo = files[i];
			if(!match_wildcard(fileInfo.Name().string().c_str(), pattern))
				continue;

			const VfsPath pathname(path / fileInfo.Name());	// (CFileInfo only stores the name)
			RETURN_STATUS_IF_ERR(cb(pathname, fileInfo, cbData));
		}

		if(!(flags & DIR_RECURSIVE))
			break;

		for(size_t i = 0; i < subdirectoryNames.size(); i++)
			pendingDirectories.push(path / subdirectoryNames[i]/"");
		pendingDirectories.pop();
	}

	return INFO::OK;
}
Exemplo n.º 29
0
Status ReloadChangedFiles()
{
	std::vector<DirWatchNotification> notifications;
	RETURN_STATUS_IF_ERR(dir_watch_Poll(notifications));
	for(size_t i = 0; i < notifications.size(); i++)
	{
		if(!CanIgnore(notifications[i]))
		{
			VfsPath pathname;
			RETURN_STATUS_IF_ERR(g_VFS->GetVirtualPath(notifications[i].Pathname(), pathname));
			RETURN_STATUS_IF_ERR(g_VFS->Invalidate(pathname));

			// Tell each hotloadable system about this file change:

			RETURN_STATUS_IF_ERR(g_GUI->ReloadChangedFiles(pathname));

			for (size_t j = 0; j < g_ReloadFuncs.size(); ++j)
				g_ReloadFuncs[j].first(g_ReloadFuncs[j].second, pathname);

			RETURN_STATUS_IF_ERR(h_reload(g_VFS, pathname));
		}
	}
	return INFO::OK;
}
Exemplo n.º 30
0
	Status create(const PIVFS& vfs, const VfsPath& pathname, int hotspotx_, int hotspoty_)
	{
		ht = ogl_tex_load(vfs, pathname);
		RETURN_STATUS_IF_ERR(ht);

		size_t width, height;
		(void)ogl_tex_get_size(ht, &width, &height, 0);
		w = (GLint)width;
		h = (GLint)height;

		hotspotx = hotspotx_; hotspoty = hotspoty_;

		(void)ogl_tex_set_filter(ht, GL_NEAREST);
		(void)ogl_tex_upload(ht);
		return INFO::OK;
	}