[Spice-devel] [phodav PATCH 4/4] spice-webdavd: Automount shared folder on Windows

Marc-André Lureau marcandre.lureau at gmail.com
Thu Sep 17 03:23:43 PDT 2015


Hi

On Thu, Aug 27, 2015 at 6:25 PM, Lukas Venhoda <lvenhoda at redhat.com> wrote:
> Try to connect to shared folder automatically on Windows.
>
> On each loop of run_service(), spawn a thread, that waits for 5 seconds.
> If read_thread() returns, it means, that sharing is not yet connected,
> and the map_drive thread is cancelled, and joined back to main thread.
>
> If the map_drive thread is NOT cancelled, it enumerates free drive
> letters, and maps shared folder to highest possible (from Z: to A:).
>
> If all drive letters are already assigned, stop the service.

Could you explain in the commit message why you need the thread ?

How do you prevent from having multiple drive pointing to the spice folder?


> ---
> Changes since RFC:
>  - Calling WNetAddConnection2() blindly was slow and caause many threads to spawn.
>     - Now only call it once, when it is sure, that it will connect.
>  - Now connects to a * drive, instead of always Z:
>  - Thread is now spawned and joined every time run_service() is called.
> ---
>  Makefile.am           |  4 +++
>  spice/spice-webdavd.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 80 insertions(+)
>
> diff --git a/Makefile.am b/Makefile.am
> index 485417b..df9a73e 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -87,6 +87,10 @@ spice_webdavd_LDADD =                \
>         $(PIE_LDFLAGS)          \
>         $(NULL)
>
> +if OS_WIN32
> +spice_webdavd_LDADD += -lnetapi32 -lmpr
> +endif
> +
>  deps.txt:
>         $(AM_V_GEN)rpm -qa | grep $(host_os) | sort | unix2dos > $@
>
> diff --git a/spice/spice-webdavd.c b/spice/spice-webdavd.c
> index f9c5cf1..3940f1c 100644
> --- a/spice/spice-webdavd.c
> +++ b/spice/spice-webdavd.c
> @@ -737,11 +737,81 @@ open_mux_path (const char *path)
>    mux_queue = output_queue_new (G_OUTPUT_STREAM (mux_ostream));
>  }
>
> +#ifdef G_OS_WIN32
> +static gchar
> +get_free_drive_letter(void)
> +{
> +  const guint32 max_mask = 1 << 25;
> +  guint32 drives;
> +  guint32 mask;
> +  gint i;
> +
> +  drives = GetLogicalDrives ();
> +
> +  for (i = 0; i < 26; i++)
> +    {
> +      mask = max_mask >> i;
> +      if ((drives & mask) == 0)
> +        return 'Z' - i;
> +    }
> +
> +  return 0;
> +}
> +
> +static gpointer
> +map_drive(gpointer user_data)
> +{
> +  GCancellable * cancel_map = user_data;
> +  gchar drive_letter;
> +  gchar local_name[3];
> +  gchar remote_name[] = "http://localhost:9843/";
> +  NETRESOURCE net_resource;
> +  guint32 retval;
> +  gint i;
> +
> +  for (i = 0; i < 5; ++i)
> +    {
> +      if (g_cancellable_is_cancelled (cancel_map))
> +        return NULL;
> +      else
> +        g_usleep (G_USEC_PER_SEC);
> +    }

It looks like this would fail if the guest is started without client
connected (or not sharing folder).

> +
> +  if ((drive_letter = get_free_drive_letter ()) == 0)
> +      g_error ("all drive letters already assigned.");
> +
> +  local_name[0] = drive_letter;
> +  local_name[1] = ':';
> +  local_name[2] = 0;
> +
> +  net_resource.dwType = RESOURCETYPE_DISK;
> +  net_resource.lpLocalName = local_name;
> +  net_resource.lpRemoteName = remote_name;
> +  net_resource.lpProvider = NULL;
> +
> +  retval = WNetAddConnection2 (&net_resource, NULL, NULL, CONNECT_TEMPORARY);
> +
> +  if (retval == NO_ERROR)
> +    g_debug ("map_drive ok");
> +  else if (retval == ERROR_ALREADY_ASSIGNED)
> +    g_debug ("map_drive already asigned");
> +  else
> +    g_error ("map_drive error %d", retval);
> +
> +  return NULL;
> +}
> +#endif
> +
>  static void
>  run_service (void)
>  {
>    g_debug ("Run service");
>
> +#ifdef G_OS_WIN32
> +  GCancellable * cancel_map = g_cancellable_new ();
> +  GThread * map_drive_thread = g_thread_new ("map-drive-thread", map_drive, cancel_map);
> +#endif
> +
>    g_socket_service_start (socket_service);
>
>    cancel = g_cancellable_new ();
> @@ -775,6 +845,12 @@ run_service (void)
>    g_main_loop_run (loop);
>    g_main_loop_unref (loop);
>
> +#ifdef G_OS_WIN32
> +  g_cancellable_cancel (cancel_map);
> +  g_thread_join(map_drive_thread);
> +  g_print ("map-drive-thread joined\n");
> +#endif
> +
>    g_cancellable_cancel (cancel);
>
>    g_clear_object (&mux_istream);
> --
> 2.4.3
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel



-- 
Marc-André Lureau


More information about the Spice-devel mailing list