[Spice-devel] [phodav PATCH 1/3 v7] spice-webdavd-windows: Automount shared folder

Victor Toso lists at victortoso.com
Fri Jun 24 15:46:25 UTC 2016


Hi,

On Thu, Jun 23, 2016 at 06:05:51PM +0200, Lukas Venhoda wrote:
> Ping for pushing

Pushed the first two patches. Last one has g_mutex_init/clear pending

Best,

> 
> On Thu, May 26, 2016 at 1:01 PM, Victor Toso <lists at victortoso.com> wrote:
> 
> > Hi,
> >
> > On Wed, May 25, 2016 at 03:51:42PM +0200, Lukáš Venhoda wrote:
> > > From: Lukas Venhoda <lvenhoda at redhat.com>
> > >
> > > Try to connect to shared folder automatically on Windows.
> > >
> > > On each loop of run_service(), run a GTask, that waits for half a second.
> > > If read_thread() returns, it means, that sharing is not yet connected,
> > > and the map_drive task is cancelled.
> > >
> > > If the map_drive task is NOT cancelled, it enumerates free drive letters,
> > > and maps Spice Folder to highest possible (from Z: to A:).
> > >
> > > If all drive letters are already assigned, show a critical error, but
> > > don't stop the service. The folder can still be accessed trough other
> > > means.
> >
> > Acked-by: Victor Toso <victortoso at redhat.com>
> >
> > > ---
> > > Changes since v6:
> > >  - Fixed build
> > >
> > > Changes since v5:
> > >  - fixed indentation
> > >  - fixed * indentaion
> > >  - removed return from void functions
> > >
> > > Changes since v4:
> > >  - Changed cancel_map to MapDriveData structure
> > >  - Added error checking for GetLogicalDrives()
> > >  - Moved defines and variables around
> > >  - Renamed some functions and variables
> > >  - Better debug messages
> > >
> > > Changes since v3:
> > >  - Added init_netresource and clear_netresource functions
> > >     - Should clean up the map_drive function
> > >     - Better handeling of adress to map/unmap
> > >        - Not hardcoded port
> > >  - Syntax cleanup
> > >  - Changed criticals to warnings
> > >  - Better TODO
> > >
> > > Changes since v2:
> > >  - Changed for loop to gpoll
> > >  - split map_drive into 2 functions
> > >  - added enum for return values of map_drive
> > >  - added TODO for renaming the drive
> > >  - added explanation for the 0.5 delay into commit log
> > >
> > > Changes since v1:
> > >  - Changed GThread to a GTask
> > >  - Only wait half a second, instead of 5
> > >
> > > 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 | 140
> > ++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  2 files changed, 144 insertions(+)
> > >
> > > diff --git a/Makefile.am b/Makefile.am
> > > index 6127f93..d8e2d53 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..9783459 100644
> > > --- a/spice/spice-webdavd.c
> > > +++ b/spice/spice-webdavd.c
> > > @@ -737,11 +737,146 @@ open_mux_path (const char *path)
> > >    mux_queue = output_queue_new (G_OUTPUT_STREAM (mux_ostream));
> > >  }
> > >
> > > +#ifdef G_OS_WIN32
> > > +#define MAX_SHARED_FOLDER_NAME_SIZE 64
> > > +#define MAX_DRIVE_LETTER_SIZE 3
> > > +typedef enum _MapDriveEnum
> > > +{
> > > +  MAP_DRIVE_OK,
> > > +  MAP_DRIVE_TRY_AGAIN,
> > > +  MAP_DRIVE_ERROR
> > > +} MapDriveEnum;
> > > +
> > > +typedef struct _MapDriveData
> > > +{
> > > +  GCancellable *cancel_map;
> > > +} MapDriveData;
> > > +
> > > +static gchar
> > > +get_free_drive_letter(void)
> > > +{
> > > +  const guint32 max_mask = 1 << 25;
> > > +  guint32 drives;
> > > +  gint i;
> > > +
> > > +  drives = GetLogicalDrives ();
> > > +  if (drives == 0)
> > > +    {
> > > +      g_warning ("%s", g_win32_error_message (GetLastError ()));
> > > +      return 0;
> > > +    }
> > > +
> > > +  for (i = 0; i < 26; i++)
> > > +    {
> > > +      guint32 mask = max_mask >> i;
> > > +      if ((drives & mask) == 0)
> > > +        return 'z' - i;
> > > +    }
> > > +
> > > +  return 0;
> > > +}
> > > +
> > > +/* User is required to call netresource_free, when no longer needed. */
> > > +static void
> > > +netresource_init(NETRESOURCE *net_resource, const gchar drive_letter)
> > > +{
> > > +  net_resource->dwType = RESOURCETYPE_DISK;
> > > +  net_resource->lpLocalName = g_strdup_printf("%c:", drive_letter);
> > > +  net_resource->lpRemoteName = g_strdup_printf("http://localhost:%d/",
> > port);
> > > +  net_resource->lpProvider = NULL;
> > > +}
> > > +
> > > +static void
> > > +netresource_free(NETRESOURCE *net_resource)
> > > +{
> > > +  g_free(net_resource->lpLocalName);
> > > +  g_free(net_resource->lpRemoteName);
> > > +}
> > > +
> > > +static MapDriveEnum
> > > +map_drive(const gchar drive_letter)
> > > +{
> > > +  NETRESOURCE net_resource;
> > > +  guint32 errn;
> > > +
> > > +  netresource_init(&net_resource, drive_letter);
> > > +  errn = WNetAddConnection2 (&net_resource, NULL, NULL,
> > CONNECT_TEMPORARY);
> > > +  netresource_free(&net_resource);
> > > +
> > > +  if (errn == NO_ERROR)
> > > +    {
> > > +      g_debug ("Shared folder mapped to %c succesfully", drive_letter);
> > > +      return MAP_DRIVE_OK;
> > > +    }
> > > +  else if (errn == ERROR_ALREADY_ASSIGNED)
> > > +    {
> > > +      g_debug ("Drive letter %c is already assigned", drive_letter);
> > > +      return MAP_DRIVE_TRY_AGAIN;
> > > +    }
> > > +
> > > +  g_warning ("map_drive error %d", errn);
> > > +  return MAP_DRIVE_ERROR;
> > > +}
> > > +
> > > +static void
> > > +map_drive_cb(GTask *task,
> > > +             gpointer source_object,
> > > +             gpointer task_data,
> > > +             GCancellable *cancellable)
> > > +{
> > > +  const guint32 delay = 500; //half a second
> > > +  MapDriveData *map_drive_data = task_data;
> > > +  gchar drive_letter;
> > > +  GPollFD cancel_pollfd;
> > > +  guint32 ret = 0;
> > > +
> > > +  if (!g_cancellable_make_pollfd (map_drive_data->cancel_map,
> > &cancel_pollfd))
> > > +    {
> > > +      g_critical ("GPollFD failed to create.");
> > > +      return;
> > > +    }
> > > +
> > > +  ret = g_poll (&cancel_pollfd, 1, delay);
> > > +  g_cancellable_release_fd (map_drive_data->cancel_map);
> > > +
> > > +  if (ret != 0)
> > > +    {
> > > +      return;
> > > +    }
> > > +
> > > +  while (TRUE)
> > > +    {
> > > +      drive_letter = get_free_drive_letter ();
> > > +      if (drive_letter == 0)
> > > +        {
> > > +          g_warning ("all drive letters already assigned.");
> > > +          break;
> > > +        }
> > > +
> > > +      if (map_drive (drive_letter) != MAP_DRIVE_TRY_AGAIN)
> > > +        {
> > > +          break;
> > > +        }
> > > +      //TODO: After mapping, rename network drive from \\localhost at PORT
> > \DavWWWRoot
> > > +      //      to something like SPICE Shared Folder
> > > +    }
> > > +}
> > > +#endif
> > > +
> > >  static void
> > >  run_service (void)
> > >  {
> > >    g_debug ("Run service");
> > >
> > > +#ifdef G_OS_WIN32
> > > +  MapDriveData map_drive_data;
> > > +  map_drive_data.cancel_map = g_cancellable_new ();
> > > +  GTask *map_drive_task = g_task_new (NULL, NULL, NULL, NULL);
> > > +  g_task_set_task_data (map_drive_task, &map_drive_data, NULL);
> > > +  g_task_run_in_thread (map_drive_task, map_drive_cb);
> > > +  g_object_unref (map_drive_task);
> > > +#endif
> > > +
> > >    g_socket_service_start (socket_service);
> > >
> > >    cancel = g_cancellable_new ();
> > > @@ -775,6 +910,11 @@ run_service (void)
> > >    g_main_loop_run (loop);
> > >    g_main_loop_unref (loop);
> > >
> > > +#ifdef G_OS_WIN32
> > > +  g_cancellable_cancel (map_drive_data.cancel_map);
> > > +  g_object_unref (map_drive_data.cancel_map);
> > > +#endif
> > > +
> > >    g_cancellable_cancel (cancel);
> > >
> > >    g_clear_object (&mux_istream);
> > > --
> > > 2.5.5
> > >
> > > _______________________________________________
> > > Spice-devel mailing list
> > > Spice-devel at lists.freedesktop.org
> > > https://lists.freedesktop.org/mailman/listinfo/spice-devel
> >
> 
> 
> 
> -- 
> Lukas Venhoda


More information about the Spice-devel mailing list