Ejemplo n.º 1
0
/* @brief Checks whether two *paths* are on the same mount point; they don't
 * have to refer to existing or accessible files/directories. */
static int has_same_mount_point(const efile_path_t *path_a, const efile_path_t *path_b) {
    WCHAR *mount_a, *mount_b;
    int result = 0;

    mount_a = enif_alloc(path_a->size);
    mount_b = enif_alloc(path_b->size);

    if(mount_a != NULL && mount_b != NULL) {
        int length_a, length_b;

        length_a = PATH_LENGTH(path_a);
        length_b = PATH_LENGTH(path_b);

        if(GetVolumePathNameW((WCHAR*)path_a->data, mount_a, length_a)) {
            ASSERT(wcslen(mount_a) <= length_a);

            if(GetVolumePathNameW((WCHAR*)path_b->data, mount_b, length_b)) {
                ASSERT(wcslen(mount_b) <= length_b);

                result = !_wcsicmp(mount_a, mount_b);
            }
        }
    }

    if(mount_b != NULL) {
        enif_free(mount_b);
    }

    if(mount_a != NULL) {
        enif_free(mount_a);
    }

    return result;
}
Ejemplo n.º 2
0
/*
 * @implemented
 */
BOOL
WINAPI
GetVolumePathNameA(IN LPCSTR lpszFileName,
                   IN LPSTR lpszVolumePathName,
                   IN DWORD cchBufferLength)
{
    PWCHAR FileNameW = NULL;
    WCHAR VolumePathName[MAX_PATH];
    BOOL Result;

    if (lpszFileName)
    {
        if (!(FileNameW = FilenameA2W(lpszFileName, FALSE)))
            return FALSE;
    }

    Result = GetVolumePathNameW(FileNameW, VolumePathName, cchBufferLength);

    if (Result)
        FilenameW2A_N(lpszVolumePathName, MAX_PATH, VolumePathName, -1);

    return Result;
}
Ejemplo n.º 3
0
HRESULT TRASH_EnumItems(const WCHAR *path, LPITEMIDLIST **pidls, int *count)
{
    WCHAR volume_path[MAX_PATH];
    char *unix_path, trash_path[MAX_PATH];
    FSCatalogInfo catalog_info;
    OSStatus status;
    FSRef ref;
    struct dirent *entry;
    DIR *dir;
    LPITEMIDLIST *ret;
    int i=0, ret_size=8;
    HRESULT hr;

    TRACE("(%s %p %p)\n", debugstr_w(path), pidls, count);

    if(!path) {
        FIXME("All trashes enumeration not supported\n");
        volume_path[0] = 'C';
        volume_path[1] = ':';
        volume_path[2] = 0;
    } else {
        if(!GetVolumePathNameW(path, volume_path, MAX_PATH))
            return E_FAIL;
    }

    if(!(unix_path = wine_get_unix_file_name(volume_path)))
        return E_OUTOFMEMORY;

    status = FSPathMakeRef((UInt8*)unix_path, &ref, NULL);
    heap_free(unix_path);
    if(status != noErr) return E_FAIL;
    status = FSGetCatalogInfo(&ref, kFSCatInfoVolume, &catalog_info, NULL, NULL, NULL);
    if(status != noErr) return E_FAIL;
    status = FSFindFolder(catalog_info.volume, kTrashFolderType, kCreateFolder, &ref);
    if(status != noErr) return E_FAIL;
    status = FSRefMakePath(&ref, (UInt8*)trash_path, MAX_PATH);
    if(status != noErr) return E_FAIL;

    if(!(dir = opendir(trash_path))) return E_FAIL;
    ret = heap_alloc(ret_size * sizeof(*ret));
    if(!ret) {
        closedir(dir);
        return E_OUTOFMEMORY;
    }
    while((entry = readdir(dir))) {
        WIN32_FIND_DATAW data;

        if(!lstrcmpA(entry->d_name, ".") || !lstrcmpA(entry->d_name, ".." )
                || !lstrcmpA(entry->d_name, ".DS_Store"))
            continue;

        if(i == ret_size) {
            LPITEMIDLIST *resized;
            ret_size *= 2;
            resized = heap_realloc(ret, ret_size * sizeof(*ret));
            if(!resized) hr = E_OUTOFMEMORY;
            else ret = resized;
        }

        if(SUCCEEDED(hr)) {
            hr = TRASH_GetDetails(trash_path, entry->d_name, &data);
            if(hr == S_FALSE) continue;
        }
        if(SUCCEEDED(hr))
            hr = TRASH_CreateSimplePIDL(entry->d_name, &data, ret+i);
        if(FAILED(hr)) {
            while(i>0) SHFree(ret+(--i));
            heap_free(ret);
            closedir(dir);
            return hr;
        }
        i++;
    }
    closedir(dir);

    *pidls = SHAlloc(sizeof(**pidls) * i);
    if(!*pidls) {
        while(i>0) SHFree(ret+(--i));
        heap_free(ret);
        return E_OUTOFMEMORY;
    }
    *count = i;
    for(i--; i>=0; i--) (*pidls)[i] = ret[i];
    heap_free(ret);
    return S_OK;
}
Ejemplo n.º 4
0
bool os_sync(const std::string & path)
{
	std::string prefixedbpath = os_file_prefix(path);

	if (next(prefixedbpath, 0, "\\\\?\\UNC"))
	{
		HANDLE hVol = CreateFileW(ConvertToWchar(prefixedbpath).c_str(),
			GENERIC_READ | GENERIC_WRITE,
			FILE_SHARE_WRITE | FILE_SHARE_READ,
			NULL,
			OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL,
			NULL);

		if (hVol == INVALID_HANDLE_VALUE)
		{
			return false;
		}

		BOOL b = FlushFileBuffers(hVol);

		CloseHandle(hVol);

		return b == TRUE;
	}

	std::wstring tvolume;
	tvolume.resize(prefixedbpath.size() + 100);
	DWORD cchBufferLength = static_cast<DWORD>(tvolume.size());
	BOOL b = GetVolumePathNameW(ConvertToWchar(prefixedbpath).c_str(), &tvolume[0], cchBufferLength);
	if (!b)
	{
		return false;
	}

	std::string volume = ConvertFromWchar(tvolume.c_str());

	if (volume.find("\\\\?\\") == 0
		&& volume.find("\\\\?\\GLOBALROOT") != 0)
	{
		volume.erase(0, 4);
	}

	if (!volume.empty()
		&& volume[volume.size() - 1] == os_file_sep()[0])
	{
		volume = volume.substr(0, volume.size() - 1);
	}

	HANDLE hVol = CreateFileW(ConvertToWchar("\\\\.\\"+volume).c_str(),
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_WRITE | FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (hVol == INVALID_HANDLE_VALUE)
	{
		return false;
	}

	b = FlushFileBuffers(hVol);

	CloseHandle(hVol);
	
	return b == TRUE;
}
void ChangeJournalWatcher::watchDir(const std::wstring &dir)
{
	WCHAR volume_path[MAX_PATH]; 
	BOOL ok = GetVolumePathNameW(dir.c_str(), volume_path, MAX_PATH);
	if(!ok)
	{
		Server->Log("GetVolumePathName(dir, volume_path, MAX_PATH) failed in ChangeJournalWatcher::watchDir", LL_ERROR);
		listener->On_ResetAll(dir);
		has_error=true;
		error_dirs.push_back(dir);
		return;
	}

	std::wstring vol=volume_path;

	if(vol.size()>0)
	{
		if(vol[vol.size()-1]=='\\')
		{
			vol.erase(vol.size()-1,1);
		}
	}

	std::map<std::wstring, SChangeJournal>::iterator it=wdirs.find(vol);
	if(it!=wdirs.end())
	{
		it->second.path.push_back(dir);
		return;
	}

	bool do_index=false;

	_i64 rid=hasRoot(vol);
	if(rid==-1)
	{
		listener->On_ResetAll(vol);
		do_index=true;
		rid=addRoot(vol);
		setIndexDone(vol, 0);
	}

	HANDLE hVolume=CreateFileW((L"\\\\.\\"+vol).c_str(), GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
	if(hVolume==INVALID_HANDLE_VALUE)
	{
		Server->Log(L"CreateFile of volume '"+vol+L"' failed. - watchDir", LL_ERROR);
		listener->On_ResetAll(vol);
		error_dirs.push_back(vol);
		CloseHandle(hVolume);
		has_error=true;
		return;
	}
	
	USN_JOURNAL_DATA data;
	DWORD r_bytes;
	BOOL b=DeviceIoControl(hVolume, FSCTL_QUERY_USN_JOURNAL, NULL, 0, &data, sizeof(USN_JOURNAL_DATA), &r_bytes, NULL);
	if(b==0)
	{
		DWORD err=GetLastError();
		if(err==ERROR_INVALID_FUNCTION)
		{
			Server->Log(L"Change Journals not supported for Volume '"+vol+L"'", LL_ERROR);
			listener->On_ResetAll(vol);
			error_dirs.push_back(vol);
			CloseHandle(hVolume);
			has_error=true;
			return;
		}
		else if(err==ERROR_JOURNAL_DELETE_IN_PROGRESS)
		{
			Server->Log(L"Change Journals for Volume '"+vol+L"' is being deleted", LL_ERROR);
			listener->On_ResetAll(vol);
			error_dirs.push_back(vol);
			CloseHandle(hVolume);
			has_error=true;
			return;
		}
		else if(err==ERROR_JOURNAL_NOT_ACTIVE)
		{
			CREATE_USN_JOURNAL_DATA dat;
			dat.AllocationDelta=10485760; //10 MB
			dat.MaximumSize=73400320; // 70 MB
			DWORD bret;
			BOOL r=DeviceIoControl(hVolume, FSCTL_CREATE_USN_JOURNAL, &dat, sizeof(CREATE_USN_JOURNAL_DATA), NULL, 0, &bret, NULL);
			if(r==0)
			{
				Server->Log(L"Error creating change journal for Volume '"+vol+L"'", LL_ERROR);
				listener->On_ResetAll(vol);
				error_dirs.push_back(vol);
				CloseHandle(hVolume);
				has_error=true;
				return;
			}
			b=DeviceIoControl(hVolume, FSCTL_QUERY_USN_JOURNAL, NULL, 0, &data, sizeof(USN_JOURNAL_DATA), &r_bytes, NULL);
			if(b==0)
			{
				Server->Log(L"Unknown error for Volume '"+vol+L"' after creation - watchDir", LL_ERROR);
				listener->On_ResetAll(vol);
				error_dirs.push_back(vol);
				CloseHandle(hVolume);
				has_error=true;
				return;
			}
		}
		else
		{
			Server->Log(L"Unknown error for Volume '"+vol+L"' - watchDir ec: "+convert((int)err), LL_ERROR);
			listener->On_ResetAll(vol);
			error_dirs.push_back(vol);
			CloseHandle(hVolume);
			has_error=true;
			return;
		}
	}

	SDeviceInfo info=getDeviceInfo(vol);

	if(info.has_info)
	{
		if(info.journal_id!=data.UsnJournalID)
		{
			Server->Log(L"Journal id for '"+vol+L"' wrong - reindexing", LL_WARNING);
			listener->On_ResetAll(vol);
			do_index=true;
			setIndexDone(vol, 0);
			info.last_record=data.NextUsn;

			q_update_journal_id->Bind((_i64)data.UsnJournalID);
			q_update_journal_id->Bind(vol);
			q_update_journal_id->Write();
			q_update_journal_id->Reset();
		}

		bool needs_reindex=false;

		if( do_index==false && (info.last_record<data.FirstUsn || info.last_record>data.NextUsn) )
		{
			Server->Log(L"Last record not readable at '"+vol+L"' - reindexing", LL_WARNING);
			needs_reindex=true;
		}

		if( do_index==false && data.NextUsn-info.last_record>usn_reindex_num )
		{
			Server->Log(L"There are "+convert(data.NextUsn-info.last_record)+L" new USN entries at '"+vol+L"' - reindexing", LL_WARNING);
			needs_reindex=true;
		}

		if(needs_reindex)
		{
			
			listener->On_ResetAll(vol);
			do_index=true;
			setIndexDone(vol, 0);
			info.last_record=data.NextUsn;
		}

		if(do_index==false && info.index_done==0)
		{
			Server->Log(L"Indexing was not finished at '"+vol+L"' - reindexing", LL_WARNING);
			do_index=true;
			setIndexDone(vol, 0);
			info.last_record=data.NextUsn;
		}
	}
	else
	{
		listener->On_ResetAll(vol);
		Server->Log(L"Info not found at '"+vol+L"' - reindexing", LL_WARNING);
		do_index=true;
	}

	SChangeJournal cj;
	cj.journal_id=data.UsnJournalID;
	if(!info.has_info)
		cj.last_record=data.NextUsn;
	else
		cj.last_record=info.last_record;

	cj.path.push_back(dir);
	cj.hVolume=hVolume;
	cj.rid=rid;
	cj.last_record_update=false;
	cj.vol_str=vol;

	if(!info.has_info)
	{
		q_add_journal->Bind((_i64)data.UsnJournalID);
		q_add_journal->Bind(vol);
		q_add_journal->Bind(cj.last_record);
		q_add_journal->Write();
		q_add_journal->Reset();

		setIndexDone(vol, 0);
	}

	wdirs.insert(std::pair<std::wstring, SChangeJournal>(vol, cj) );

	if(do_index)
	{
		reindex(rid, vol, &cj);
		Server->Log(L"Reindexing of '"+vol+L"' done.", LL_INFO);
	}
}