app-manager/localmedia.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Jul 16 11:07:18 2016 +0100 (2016-07-16)
changeset 61 31fb35727621
parent 12 1d18b9c34d26
permissions -rw-r--r--
Support parallel installations. The idea is that for CAD screener, we want
to be able to install this on the same machine as a standard AVOT setup
(most notably for John's laptop). To allow for the possibility of a second
application that might have the same requirements, we add the concept of
vendor-specific distributions. Thus we can have one distribution for CAD
screener and one for The Next Big Thing. It doesn't seem trivial to have
both CAD screener and AVOT under the same vendor tag so we'll have to have
AVOT under "City Occupational" and CAD screener under "City Occupational Ltd"
or some such kludge.

Most of this is done although we are very short of test cases (in particular
we don't test that it's actually possible to install CAD screener in parallel
with AVOT or to update either of them once installed, which is fundamental).

We also have a lot of baggage left over, including an intercept of razor_set.
The problem that this was introduced to debug has been fixed but it looks
like there are a number of memory leaks which it might be useful to help
track down so it has been left in place for now.

There is still a lot of confusion in plover between path-based and URI-based
API. We should review the API, decide what we want and have a general clear up.

There is also confusion as to the purpose of RAZOR_ROOT (and meaning; path or
URI). This is not used at all in librazor (although it is used in razor.exe).
Ideally we shouldn't use it in plover or plover-gtk either although again, we
might want to support it or an equivalent in (some of) the various executables.

Work that would still to nice to do for CAD screener:

- uninstall (ideally as an installed program that hooks into Add/Remove programs
but even re-running the installer would be acceptable).
- xz support (smaller packages).
- repomd.xml and xml:base (would be needed for an Internet installer).
- graphical installer.
     1 /*
     2  * Copyright (C) 2010  J. Ali Harlow <ali@juiblex.co.uk>
     3  *
     4  * This program is free software; you can redistribute it and/or modify
     5  * it under the terms of the GNU General Public License as published by
     6  * the Free Software Foundation; either version 2 of the License, or
     7  * (at your option) any later version.
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License along
    15  * with this program; if not, write to the Free Software Foundation, Inc.,
    16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    17  */
    18 
    19 #include "config.h"
    20 #include <stdlib.h>
    21 #include <string.h>
    22 #ifdef WIN32
    23 #include <windows.h>
    24 #endif
    25 #include <glib.h>
    26 #include <gio/gio.h>
    27 #include <gtk/gtk.h>
    28 #include <plover-gtk/packagestore.h>
    29 #include "app-manager.h"
    30 #include "localmedia.h"
    31 
    32 G_DEFINE_TYPE(PloverLocalMediaStore,plover_local_media_store,
    33   PLOVER_TYPE_PACKAGE_STORE);
    34 
    35 static void plover_local_media_store_dispose(GObject *obj)
    36 {
    37     PloverLocalMediaStore *store=PLOVER_LOCAL_MEDIA_STORE(obj);
    38     if (store->monitor)
    39     {
    40 	g_object_unref(store->monitor);
    41 	store->monitor=NULL;
    42     }
    43     if (G_OBJECT_CLASS(plover_local_media_store_parent_class)->dispose)
    44 	G_OBJECT_CLASS(plover_local_media_store_parent_class)->dispose(obj);
    45 }
    46 
    47 static void
    48   plover_local_media_store_class_init(PloverLocalMediaStoreClass *klass)
    49 {
    50     GObjectClass *oclass=G_OBJECT_CLASS(klass);
    51     oclass->dispose=plover_local_media_store_dispose;
    52 }
    53 
    54 GtkTreeModel *plover_local_media_store_new(void)
    55 {
    56     return g_object_new(PLOVER_TYPE_LOCAL_MEDIA_STORE,NULL);
    57 }
    58 
    59 static void local_media_scan_mount(PloverLocalMediaStore *store,GMount *mount)
    60 {
    61     GFile *root;
    62     gchar *path;
    63 #ifdef WIN32
    64     gunichar2 *path2;
    65     UINT type;
    66 #endif
    67     PloverPackageSet *set;
    68     root=g_mount_get_root(mount);
    69     path=g_file_get_path(root);
    70 #ifdef WIN32
    71     if (path)
    72     {
    73 	path2=g_utf8_to_utf16(path,-1,NULL,NULL,NULL);
    74 	if (path2)
    75 	{
    76 	    type=GetDriveTypeW(path2);
    77 	    g_free(path2);
    78 	}
    79 	else
    80 	    type=DRIVE_UNKNOWN;
    81 	if (type!=DRIVE_REMOVABLE && type!=DRIVE_CDROM)
    82 	{
    83 	    gchar *name=g_mount_get_name(mount);
    84 	    g_debug("Skipping non-local mount \"%s\"",name);
    85 	    g_free(name);
    86 	    g_free(path);
    87 	    path=NULL;
    88 	}
    89     }
    90 #endif
    91     if (path)
    92     {
    93 	set=plover_package_set_new_from_yum(path,relocations,NULL);
    94 	if (set)
    95 	{
    96 	    g_object_set_data(G_OBJECT(mount),"plover-local-media-set",set);
    97 	    plover_package_store_add_set(PLOVER_PACKAGE_STORE(store),set);
    98 	    g_object_ref(mount);
    99 	}
   100 	g_free(path);
   101     }
   102     g_object_unref(root);
   103 }
   104 
   105 static void local_media_mounted(GObject *source,GAsyncResult *res,gpointer data)
   106 {
   107     GVolume *volume=G_VOLUME(source);
   108     GMount *mount;
   109     PloverLocalMediaStore *store=PLOVER_LOCAL_MEDIA_STORE(data);
   110     if (g_volume_mount_finish(volume,res,NULL))
   111     {
   112 	mount=g_volume_get_mount(volume);
   113 	if (mount)
   114 	{
   115 	    local_media_scan_mount(store,mount);
   116 	    g_object_unref(mount);
   117 	}
   118     }
   119     g_object_unref(volume);
   120 }
   121 
   122 static void local_media_scan_drive(PloverLocalMediaStore *store,GDrive *drive)
   123 {
   124     GVolume *volume;
   125     GMount *mount;
   126     GList *volumes,*mounts,*link;
   127     if (!drive)
   128 	volumes=g_volume_monitor_get_volumes(store->monitor);
   129     else if (g_drive_has_media(drive))
   130 	volumes=g_drive_get_volumes(drive);
   131     else
   132 	volumes=NULL;
   133     for(link=volumes;link;link=link->next)
   134     {
   135 	volume=G_VOLUME(link->data);
   136 	mount=g_volume_get_mount(volume);
   137 	if (mount)
   138 	{
   139 	    local_media_scan_mount(store,mount);
   140 	    g_object_unref(mount);
   141 	}
   142 	else if (!store->implicit_scan && g_volume_can_mount(volume))
   143 	    g_volume_mount(volume,G_MOUNT_MOUNT_NONE,NULL,NULL,
   144 	      local_media_mounted,store);
   145 	g_object_unref(volume);
   146     }
   147     g_list_free(volumes);
   148     if (!drive)
   149     {
   150 	mounts=g_volume_monitor_get_mounts(store->monitor);
   151 	for(link=mounts;link;link=link->next)
   152 	{
   153 	    mount=G_MOUNT(link->data);
   154 	    local_media_scan_mount(store,mount);
   155 	    g_object_unref(mount);
   156 	}
   157 	g_list_free(mounts);
   158     }
   159 }
   160 
   161 static void local_media_polled(GObject *source,GAsyncResult *res,gpointer data)
   162 {
   163     GDrive *drive=G_DRIVE(source);
   164     PloverLocalMediaStore *store=PLOVER_LOCAL_MEDIA_STORE(data);
   165     if (g_drive_poll_for_media_finish(drive,res,NULL))
   166 	local_media_scan_drive(store,drive);
   167     g_object_unref(drive);
   168 }
   169 
   170 void plover_local_media_store_scan(PloverLocalMediaStore *store)
   171 {
   172     GSList *sets,*slink;
   173     GList *drives,*link;
   174     GDrive *drive;
   175     g_return_if_fail(PLOVER_IS_LOCAL_MEDIA_STORE(store));
   176     sets=
   177       g_slist_copy(plover_package_store_get_sets(PLOVER_PACKAGE_STORE(store)));
   178     for(slink=sets;slink;slink=slink->next)
   179 	plover_package_store_remove_set(PLOVER_PACKAGE_STORE(store),
   180 	  PLOVER_PACKAGE_SET(slink->data));
   181     g_slist_free(sets);
   182     drives=g_volume_monitor_get_connected_drives(store->monitor);
   183     for(link=drives;link;link=link->next)
   184     {
   185 	drive=G_DRIVE(link->data);
   186 	if (g_drive_is_media_removable(drive))
   187 	{
   188 	    if (!g_drive_is_media_check_automatic(drive) &&
   189 	      g_drive_can_poll_for_media(drive) ||
   190 	      !g_drive_has_media(drive) && !store->implicit_scan)
   191 	    {
   192 		g_object_ref(drive);
   193 		g_drive_poll_for_media(drive,NULL,local_media_polled,store);
   194 	    }
   195 	    else
   196 		local_media_scan_drive(store,drive);
   197 	}
   198 	g_object_unref(drive);
   199     }
   200     g_list_free(drives);
   201     local_media_scan_drive(store,NULL);
   202 }
   203 
   204 static void local_media_mount_added(GVolumeMonitor *volume_monitor,
   205   GMount *mount,PloverLocalMediaStore *store)
   206 {
   207     local_media_scan_mount(store,mount);
   208 }
   209 
   210 static void local_media_mount_removed(GVolumeMonitor *volume_monitor,
   211   GMount *mount,PloverLocalMediaStore *store)
   212 {
   213     PloverPackageSet *set=
   214       g_object_get_data(G_OBJECT(mount),"plover-local-media-set");
   215     if (set)
   216     {
   217 	plover_package_store_remove_set(PLOVER_PACKAGE_STORE(store),set);
   218 	g_object_set_data(G_OBJECT(mount),"plover-local-media-set",NULL);
   219 	g_object_unref(set);
   220 	g_object_unref(mount);
   221     }
   222 }
   223 
   224 static void local_media_mount_changed(GVolumeMonitor *volume_monitor,
   225   GMount *mount,PloverLocalMediaStore *store)
   226 {
   227     local_media_mount_removed(volume_monitor,mount,store);
   228     local_media_mount_added(volume_monitor,mount,store);
   229 }
   230 
   231 static void plover_local_media_store_init(PloverLocalMediaStore *store)
   232 {
   233     store->monitor=g_volume_monitor_get();
   234     store->implicit_scan=TRUE;
   235     plover_local_media_store_scan(store);
   236     store->implicit_scan=FALSE;
   237     g_signal_connect(store->monitor,"mount-added",
   238       G_CALLBACK(local_media_mount_added),store);
   239     g_signal_connect(store->monitor,"mount-changed",
   240       G_CALLBACK(local_media_mount_changed),store);
   241     g_signal_connect(store->monitor,"mount-removed",
   242       G_CALLBACK(local_media_mount_removed),store);
   243 }