Ejemplo n.º 1
0
 def wait_for_connection(self, timeout=None, force_wait=False):
     self._connection_cond.acquire()
     try:
         if force_wait:
             self.connected = False
         if not self.connected:
             if not self._poll_thread:
                 target = self._poll_connection
                 self._poll_thread = threading.Thread(target=target)
                 self._poll_thread.daemon = True
                 self._poll_thread.start()
             self._connection_cond.wait(timeout)
     finally:
         self._connection_cond.release()
Ejemplo n.º 2
0
def _start_timeout_protect_thread():
    """Start the background thread used to protect dokan from timeouts.

    This function starts the background thread that monitors calls into the
    dokan API and resets their timeouts.  It's safe to call this more than
    once, only a single thread will be started.
    """
    global _TIMEOUT_PROTECT_THREAD
    with _TIMEOUT_PROTECT_LOCK:
        if _TIMEOUT_PROTECT_THREAD is None:
            target = _run_timeout_protect_thread
            _TIMEOUT_PROTECT_THREAD = threading.Thread(target=target)
            _TIMEOUT_PROTECT_THREAD.daemon = True
            _TIMEOUT_PROTECT_THREAD.start()
Ejemplo n.º 3
0
def _start_timeout_protect_thread():
    """Start the background thread used to protect dokan from timeouts.
 
    This function starts the background thread that monitors calls into the
    dokan API and resets their timeouts.  It's safe to call this more than
    once, only a single thread will be started.
    """
    global _TIMEOUT_PROTECT_THREAD
    with _TIMEOUT_PROTECT_LOCK:
        if _TIMEOUT_PROTECT_THREAD is None:
            def target():
                while True:
                    (when,info,finished) = _TIMEOUT_PROTECT_QUEUE.get()
                    if finished:
                        continue
                    now = time.time()
                    wait_time = max(0,_TIMEOUT_PROTECT_WAIT_TIME - now + when)
                    time.sleep(wait_time)
                    libdokan.DokanResetTimeout(_TIMEOUT_PROTECT_RESET_TIME,info)
                    _TIMEOUT_PROTECT_QUEUE.put((now+wait_time,info,finished))
            _TIMEOUT_PROTECT_THREAD = threading.Thread(target=target)
            _TIMEOUT_PROTECT_THREAD.daemon = True
            _TIMEOUT_PROTECT_THREAD.start()
Ejemplo n.º 4
0
                    else:
                        return None
            else:
                check_alive(mp)
                raise OSError("dokan mount process seems to be hung")

    #  Running the the foreground is the final endpoint for the mount
    #  operation, it's where we call DokanMain().
    if foreground:
        numthreads = kwds.pop("numthreads", 0)
        flags = kwds.pop("flags", 0)
        FSOperationsClass = kwds.pop("FSOperationsClass", FSOperations)
        opts = libdokan.DOKAN_OPTIONS(drive[:1], numthreads, flags)
        ops = FSOperationsClass(fs, **kwds)
        if ready_callback:
            check_thread = threading.Thread(target=check_ready)
            check_thread.daemon = True
            check_thread.start()
        opstruct = ops.get_ops_struct()
        res = libdokan.DokanMain(ctypes.byref(opts), ctypes.byref(opstruct))
        if res != DOKAN_SUCCESS:
            raise OSError("Dokan failed with error: %d" % (res, ))
        if unmount_callback:
            unmount_callback()
    #  Running the background, spawn a subprocess and wait for it
    #  to be ready before returning.
    else:
        mp = MountProcess(fs, drive, kwds)
        check_ready(mp)
        if unmount_callback:
            orig_unmount = mp.unmount
Ejemplo n.º 5
0
def mount(fs, path, foreground=False, ready_callback=None, unmount_callback=None, **kwds):
    """Mount the given FS at the given path, using Dokan.

    By default, this function spawns a new background process to manage the
    Dokan event loop.  The return value in this case is an instance of the
    'MountProcess' class, a subprocess.Popen subclass.

    If the keyword argument 'foreground' is given, we instead run the Dokan
    main loop in the current process.  In this case the function will block
    until the filesystem is unmounted, then return None.

    If the keyword argument 'ready_callback' is provided, it will be called
    when the filesystem has been mounted and is ready for use.  Any additional
    keyword arguments control the behavior of the final dokan mount point.
    Some interesting options include:

        * numthreads:  number of threads to use for handling Dokan requests
        * fsname:  name to display in explorer etc
        * flags:   DOKAN_OPTIONS bitmask
        * securityfolder:  folder path used to duplicate security rights on all folders 
        * FSOperationsClass:  custom FSOperations subclass to use

    """
    if libdokan is None:
        raise OSError("the dokan library is not available")
    _check_path_string(path)
    #  This function captures the logic of checking whether the Dokan mount
    #  is up and running.  Unfortunately I can't find a way to get this
    #  via a callback in the Dokan API.  Instead we just check for the path
    #  in a loop, polling the mount proc to make sure it hasn't died.

    def check_alive(mp):
        if mp and mp.poll() is not None:
            raise OSError("dokan mount process exited prematurely")

    def check_ready(mp=None):
        if ready_callback is not False:
            check_alive(mp)
            for _ in range(100):
                try:
                    os.stat(path)
                except EnvironmentError:
                    check_alive(mp)
                    time.sleep(0.05)
                else:
                    check_alive(mp)
                    if ready_callback:
                        return ready_callback()
                    else:
                        return None
            else:
                check_alive(mp)
                raise OSError("dokan mount process seems to be hung")
    #  Running the the foreground is the final endpoint for the mount
    #  operation, it's where we call DokanMain().
    if foreground:
        numthreads = kwds.pop("numthreads", 0)
        flags = kwds.pop("flags", 0)
        FSOperationsClass = kwds.pop("FSOperationsClass", FSOperations)
        opts = libdokan.DOKAN_OPTIONS(libdokan.DOKAN_MINIMUM_COMPATIBLE_VERSION, numthreads, flags, 0, path, "", 2000, 512, 512)
        ops = FSOperationsClass(fs, **kwds)
        if ready_callback:
            check_thread = threading.Thread(target=check_ready)
            check_thread.daemon = True
            check_thread.start()
        opstruct = ops.get_ops_struct()
        res = libdokan.DokanMain(ctypes.byref(opts), ctypes.byref(opstruct))
        if res != DOKAN_SUCCESS:
            raise OSError("Dokan failed with error: %d" % (res,))
        if unmount_callback:
            unmount_callback()
    #  Running the background, spawn a subprocess and wait for it
    #  to be ready before returning.
    else:
        mp = MountProcess(fs, path, kwds)
        check_ready(mp)
        if unmount_callback:
            orig_unmount = mp.unmount

            def new_unmount():
                orig_unmount()
                unmount_callback()
            mp.unmount = new_unmount
        return mp