Ticket #2952: exo-0.3.101-hal_fixes-1.patch

File exo-0.3.101-hal_fixes-1.patch, 17.4 KB (added by willimm, 15 years ago)

Kills the two HAL bugs with one stone, allowing the user to specify the HAL options, and stopping HAL from throwing cryptic messages when you press the eject button on a CD/DVD drive.

  • exo-mount/exo-mount-hal.c

    Submitted By: William Immendorf (will.immendorf@gmail.com)
    Date: 2009-09-19
    Initial Package Version: 0.3.101
    Upstream Status: unknown
    Origin: Both http://bugzilla.xfce.org/show_bug.cgi?id=2891 (first bug) and http://bugzilla.xfce.org/show_bug.cgi?id=2968. (second bug)
    Descirption: This kills the two HAL birds (or bugs) with one stone (or patch). This fixes two issues:
     1. You can't speficy the mount options for hal, as they are hardcoded in exo-mount. This is troubling, espicaly if you live in a non-English speaking contry 
    (in which you had to spefiy the iocharset option to hal), or if you are STILL using LFS 6.3 (which uses Linux 2.6.22.*), 
    and have that slow-vfat issue that can be solved (other than GETTING A NEW VERSION!) by adding the usefree option.
     2. HAL bombards you with cryptic messages every time you press the eject button on a CD/DVD drive.
    My patch fixes both, and it helps kill all the HAL releated bugs on the mouse. (my term for XFCE, who's mascot is a mouse.)
    
    diff -Naur exo-0.3.101-old/exo-mount/exo-mount-hal.c exo-0.3.101/exo-mount/exo-mount-hal.c
    old new  
    4040
    4141#include <exo-mount/exo-mount-hal.h>
    4242
    43 
     43#define CONFIG_FILE_GLOBAL     DATADIR "/xfce4/mount.rules"
    4444
    4545static gboolean exo_mount_hal_init            (GError   **error);
    4646static void     exo_mount_hal_propagate_error (GError   **error,
     
    6464  LibHalVolumeUsage fsusage;
    6565};
    6666
     67typedef struct _ExoVolumeOptions
     68{
     69    char** mount_options;
     70    char*  fstype_override;
     71} ExoVolumeOptions;
    6772
    6873
    6974static LibHalContext  *hal_context = NULL;
    7075static DBusConnection *dbus_connection = NULL;
    7176
    72 
     77static gboolean exo_volume_hal_get_options( const char* fs, ExoVolumeOptions* ret );
    7378
    7479static gboolean
    7580exo_mount_hal_init (GError **error)
     
    145150}
    146151
    147152
     153static gboolean
     154string_in_list(gchar * const *haystack, const gchar *needle)
     155{
     156  gint n;
     157
     158  if (!haystack)
     159      return FALSE;
     160
     161  for (n=0; haystack[n]; ++n) {
     162      if (!strcmp (haystack[n], needle))
     163          return TRUE;
     164  }
     165  return FALSE;
     166}
     167
     168
     169static gboolean
     170device_has_interface(const gchar *udi, const gchar *iface,
     171        DBusError *derror)
     172{
     173  gboolean result;
     174  gchar **interfaces;
     175
     176  /* determine the info.interfaces property of the device */
     177  interfaces = libhal_device_get_property_strlist (hal_context, udi,
     178          "info.interfaces", derror);
     179
     180  /* check for the interface we need */
     181  result = string_in_list(interfaces, iface);
     182  libhal_free_string_array(interfaces);
     183
     184  return result;
     185}
     186
     187
     188
    148189
    149190/**
    150191 * exo_mount_hal_device_from_udi:
     
    158199 *               or %NULL in case of an error.
    159200 **/
    160201ExoMountHalDevice*
    161 exo_mount_hal_device_from_udi (const gchar *udi,
     202exo_mount_hal_device_from_udi (const gchar *in_udi,
    162203                               GError     **error)
    163204{
    164205  ExoMountHalDevice *device = NULL;
    165206  DBusError          derror;
    166   gchar            **interfaces;
    167   gchar            **volume_udis;
    168   gchar             *volume_udi = NULL;
    169207  gint               n_volume_udis;
    170   gint               n;
     208  gchar             *udi;
    171209
    172   g_return_val_if_fail (udi != NULL, NULL);
     210  g_return_val_if_fail (in_udi != NULL, NULL);
    173211  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
    174212
    175213  /* make sure the HAL support is initialized */
     
    179217  /* initialize D-Bus error */
    180218  dbus_error_init (&derror);
    181219
    182 again:
    183   /* determine the info.interfaces property of the device */
    184   interfaces = libhal_device_get_property_strlist (hal_context, udi, "info.interfaces", &derror);
    185   if (G_UNLIKELY (interfaces == NULL))
     220  udi = g_strdup (in_udi);
     221  /* at this point, we own udi */
     222
     223  /* maybe we have a mountable device here */
     224  while(G_UNLIKELY (!device_has_interface (udi,
     225                  "org.freedesktop.Hal.Device.Volume", &derror)))
    186226    {
    187       /* reset D-Bus error */
    188       dbus_error_free (&derror);
     227      gchar **volume_udis;
    189228
    190       /* release any previous volume UDI */
    191       g_free (volume_udi);
    192       volume_udi = NULL;
     229      /* maybe there was a D-Bus error? gotta check */
     230      if (G_UNLIKELY (dbus_error_is_set (&derror)))
     231        {
     232          exo_mount_hal_propagate_error (error, &derror);
     233          g_free (udi);
     234          return NULL;
     235        }
     236
     237      /* maybe we have a volume whose parent is identified by the udi */
     238      volume_udis = libhal_manager_find_device_string_match (hal_context,
     239              "info.parent", udi, &n_volume_udis, &derror);
    193240
    194       /* ok, but maybe we have a volume whose parent is identified by the udi */
    195       volume_udis = libhal_manager_find_device_string_match (hal_context, "info.parent", udi, &n_volume_udis, &derror);
    196241      if (G_UNLIKELY (volume_udis == NULL))
    197242        {
    198 err0:     exo_mount_hal_propagate_error (error, &derror);
    199           goto out;
     243          exo_mount_hal_propagate_error (error, &derror);
     244          g_free (udi);
     245          return NULL;
    200246        }
    201247      else if (G_UNLIKELY (n_volume_udis < 1))
    202248        {
    203           /* no match, we cannot handle that device */
    204249          libhal_free_string_array (volume_udis);
    205           goto err1;
     250          dbus_error_free (&derror);
     251          /* definitely not a device that we're able to
     252           * mount, eject or unmount */
     253          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
     254                  _("Given device \"%s\" is not a volume or drive"), udi);
     255          g_free (udi);
     256          return NULL;
    206257        }
    207258
     259      g_free (udi);
     260
    208261      /* use the first volume UDI... */
    209       volume_udi = g_strdup (volume_udis[0]);
     262      udi = g_strdup (volume_udis[0]);
    210263      libhal_free_string_array (volume_udis);
    211 
    212264      /* ..and try again using that UDI */
    213       udi = (const gchar *) volume_udi;
    214       goto again;
    215265    }
    216266
    217   /* verify that we have a mountable device here */
    218   for (n = 0; interfaces[n] != NULL; ++n)
    219     if (strcmp (interfaces[n], "org.freedesktop.Hal.Device.Volume") == 0)
    220       break;
    221   if (G_UNLIKELY (interfaces[n] == NULL))
    222     {
    223       /* definitely not a device that we're able to mount, eject or unmount */
    224 err1: g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("Given device \"%s\" is not a volume or drive"), udi);
    225       goto out;
    226     }
     267  /* at this point, udi contains the UDI of something
     268   * that implements Hal.Device.Volume.
     269   * udi is the only resource that we hold here. */
    227270
    228271  /* setup the device struct */
    229272  device = g_new0 (ExoMountHalDevice, 1);
    230   device->udi = g_strdup (udi);
     273  device->udi = udi;
    231274
    232275  /* check if we have a volume here */
    233276  device->volume = libhal_volume_from_udi (hal_context, udi);
     
    269312  if (G_UNLIKELY (device->file == NULL || device->name == NULL))
    270313    {
    271314      exo_mount_hal_device_free (device);
    272       device = NULL;
    273       goto err0;
     315      exo_mount_hal_propagate_error(error, &derror);
     316      return NULL;
    274317    }
    275318
    276319  /* check if we failed */
     
    282325      device = NULL;
    283326    }
    284327
    285 out:
    286   /* cleanup */
    287   libhal_free_string_array (interfaces);
    288   g_free (volume_udi);
    289 
     328  dbus_error_free (&derror);
    290329  return device;
    291330}
    292331
     
    313352  gchar            **interfaces;
    314353  gchar            **udis;
    315354  gint               n_udis;
    316   gint               n, m;
     355  gint               n;
    317356
    318357  g_return_val_if_fail (g_path_is_absolute (file), NULL);
    319358  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
     
    347386        continue;
    348387
    349388      /* check if we have a mountable device here */
    350       for (m = 0; interfaces[m] != NULL; ++m)
    351         if (strcmp (interfaces[m], "org.freedesktop.Hal.Device.Volume") == 0)
    352           break;
    353 
    354       /* check if it's a usable device */
    355       if (interfaces[m] != NULL)
     389      if (string_in_list (interfaces, "org.freedesktop.Hal.Device.Volume"))
    356390        {
    357391          libhal_free_string_array (interfaces);
    358392          break;
     
    647681  gchar       *fstype;
    648682  gchar       *s;
    649683  gint         m, n = 0;
     684  ExoVolumeOptions opts;
    650685
    651686  g_return_val_if_fail (device != NULL, FALSE);
    652687  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
    653688
    654   /* determine the required mount options */
    655   options = g_new0 (gchar *, 20);
    656 
    657   /* check if we know any valid mount options */
    658   if (G_LIKELY (device->fsoptions != NULL))
     689    /* get mount options set by pcmanfm first */
     690    if( exo_volume_hal_get_options( device->fstype, &opts ) )
    659691    {
    660       /* process all valid mount options */
    661       for (m = 0; device->fsoptions[m] != NULL; ++m)
    662         {
    663           /* this is currently mostly Linux specific noise */
    664           if (strcmp (device->fsoptions[m], "uid=") == 0
    665               && (strcmp (device->fstype, "vfat") == 0
    666                || strcmp (device->fstype, "iso9660") == 0
    667                || strcmp (device->fstype, "udf") == 0
    668                || device->volume == NULL))
    669             {
    670               options[n++] = g_strdup_printf ("uid=%u", (guint) getuid ());
    671             }
    672           else if (strcmp (device->fsoptions[m], "shortname=") == 0
    673                 && strcmp (device->fstype, "vfat") == 0)
     692        char** popts = opts.mount_options;
     693        n = g_strv_length( popts );
     694        if( n > 0)
     695        {
     696            int i;
     697            /* We have to allocate a new larger array bacause we might need to
     698             * append new options to the array later */
     699            options = g_new0 (gchar *, n + 4);
     700            for( i = 0; i < n; ++i )
    674701            {
    675               options[n++] = g_strdup_printf ("shortname=winnt");
     702                options[i] = popts[i];
     703                popts[i] = NULL;
     704                /* steal the string */
    676705            }
    677           else if (strcmp (device->fsoptions[m], "sync") == 0
    678                 && device->volume == NULL)
    679             {
    680               /* non-pollable drive... */
    681               options[n++] = g_strdup ("sync");
    682             }
    683           else if (strcmp (device->fsoptions[m], "longnames") == 0
    684                 && strcmp (device->fstype, "vfat") == 0)
     706            /* the strings in the array are already stolen, so strfreev is not needed. */
     707        }
     708        g_free( opts.mount_options );
     709
     710        fstype = opts.fstype_override;
     711    }
     712
     713    if( G_UNLIKELY( ! options ) )
     714    {
     715      /* determine the required mount options */
     716      options = g_new0 (gchar *, 20);
     717
     718      /* check if we know any valid mount options */
     719      if (G_LIKELY (device->fsoptions != NULL))
     720        {
     721          /* process all valid mount options */
     722          for (m = 0; device->fsoptions[m] != NULL; ++m)
    685723            {
    686               /* however this one is FreeBSD specific */
    687               options[n++] = g_strdup ("longnames");
     724              /* this is currently mostly Linux specific noise */
     725              if (strcmp (device->fsoptions[m], "uid=") == 0
     726                  && (strcmp (device->fstype, "vfat") == 0
     727                   || strcmp (device->fstype, "iso9660") == 0
     728                   || strcmp (device->fstype, "udf") == 0
     729                   || device->volume == NULL))
     730                {
     731                  options[n++] = g_strdup_printf ("uid=%u", (guint) getuid ());
     732                }
     733              else if (strcmp (device->fsoptions[m], "shortname=") == 0
     734                    && strcmp (device->fstype, "vfat") == 0)
     735                {
     736                  options[n++] = g_strdup_printf ("shortname=winnt");
     737                }
     738              else if (strcmp (device->fsoptions[m], "sync") == 0
     739                    && device->volume == NULL)
     740                {
     741                  /* non-pollable drive... */
     742                  options[n++] = g_strdup ("sync");
     743                }
     744              else if (strcmp (device->fsoptions[m], "longnames") == 0
     745                    && strcmp (device->fstype, "vfat") == 0)
     746                {
     747                  /* however this one is FreeBSD specific */
     748                  options[n++] = g_strdup ("longnames");
     749                }
     750              else if (strcmp (device->fsoptions[m], "locale=") == 0
     751                    && strcmp (device->fstype, "ntfs-3g") == 0)
     752                {
     753                  options[n++] = g_strdup_printf ("locale=%s", setlocale (LC_ALL, ""));
     754                }
    688755            }
    689756        }
    690757    }
    691 
    692758  /* try to determine a usable mount point */
    693759  if (G_LIKELY (device->volume != NULL))
    694760    {
     
    703769
    704770  /* make sure that the mount point is usable (i.e. does not contain G_DIR_SEPARATOR's) */
    705771  mount_point = (mount_point != NULL && *mount_point != '\0')
    706               ? exo_str_replace (mount_point, G_DIR_SEPARATOR_S, "_") 
     772              ? exo_str_replace (mount_point, G_DIR_SEPARATOR_S, "_")
    707773              : g_strdup ("");
    708774
    709775  /* let HAL guess the fstype */
     
    835901  if (dbus_error_is_set (&derror))
    836902    {
    837903      /* try to translate the error appropriately */
    838       if (strcmp (derror.name, "org.freedesktop.Hal.Device.Volume.PermissionDenied") == 0) 
     904      if (strcmp (derror.name, "org.freedesktop.Hal.Device.Volume.PermissionDenied") == 0)
    839905        {
    840906          /* TRANSLATORS: User tried to mount a volume, but is not privileged to do so. */
    841907          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("You are not privileged to mount the volume \"%s\""), device->name);
     
    10151081  if (G_UNLIKELY (dbus_error_is_set (&derror)))
    10161082    {
    10171083      /* try to translate the error appropriately */
    1018       if (strcmp (derror.name, "org.freedesktop.Hal.Device.Volume.PermissionDenied") == 0) 
     1084      if (strcmp (derror.name, "org.freedesktop.Hal.Device.Volume.PermissionDenied") == 0)
    10191085        {
    10201086          /* TRANSLATORS: User tried to unmount a volume, but is not privileged to do so. */
    10211087          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, _("You are not privileged to unmount the volume \"%s\""), device->name);
     
    10551121  return TRUE;
    10561122}
    10571123
     1124/**
     1125 * exo_volume_hal_get_options:
     1126 * @fs     : files system name.
     1127 * @ret    : an #ExoVolumeOptions.
     1128 *
     1129 * return mount options for specified file sytem or
     1130 * override file system name. If options not found return %NULL
     1131 *
     1132 * code taked from PCManFM project.
     1133 *
     1134 * Return value: %TRUE if options is found or %FALSE if not.
     1135 **/
     1136gboolean
     1137exo_volume_hal_get_options (const char*       fs,
     1138                            ExoVolumeOptions* ret)
     1139{
     1140    GKeyFile* f;
     1141    const gchar* user_opts = g_strconcat(g_getenv("HOME"), "/.config/xfce4/mount.rules", NULL);
     1142    gboolean is_options_read = FALSE;
     1143    if( fs == NULL || ! *fs)
     1144        return FALSE;
     1145    g_return_val_if_fail( ret != NULL, FALSE );
     1146
     1147    f = g_key_file_new();
     1148    if( g_key_file_load_from_file( f, user_opts, 0, NULL ))
     1149    {
     1150        printf("User's mount options is readed\n");
     1151        is_options_read = TRUE;
     1152    }
     1153    else if( g_key_file_load_from_file( f, CONFIG_FILE_GLOBAL, 0, NULL) )
     1154    {
     1155        printf("Global mount options is readed\n");
     1156        is_options_read = TRUE;
     1157    }
     1158
     1159    if(is_options_read == TRUE)
     1160    {
     1161        gsize n = 0;
     1162        int i;
     1163        ret->mount_options = g_key_file_get_string_list( f, fs, "mount_options", &n, NULL );
     1164        ret->fstype_override = g_key_file_get_string(f, fs, "fstype_override", NULL );
     1165
     1166        for( i = 0; i < n; ++i )
     1167        {
     1168            /* replace "uid=" with "uid=<actual uid>" */
     1169#ifndef __FreeBSD__
     1170            if (strcmp (ret->mount_options[i], "uid=") == 0) {
     1171                g_free (ret->mount_options[i]);
     1172                ret->mount_options[i] = g_strdup_printf ("uid=%u", getuid ());
     1173            }
     1174#else
     1175            if (strcmp (ret->mount_options[i], "-u=") == 0) {
     1176                g_free (ret->mount_options[i]);
     1177                ret->mount_options[i] = g_strdup_printf ("-u=%u", getuid ());
     1178            }
     1179#endif
     1180            /* for ntfs-3g */
     1181            if (strcmp (ret->mount_options[i], "locale=") == 0) {
     1182                g_free (ret->mount_options[i]);
     1183                ret->mount_options[i] = g_strdup_printf ("locale=%s", setlocale (LC_ALL, ""));
     1184            }
     1185        }
     1186    }
     1187    else
     1188    {
     1189        ret->mount_options = NULL;
     1190        ret->fstype_override = NULL;
     1191    }
     1192    g_key_file_free(f);
     1193    return (ret->mount_options || ret->fstype_override);
     1194}
  • exo-mount/Makefile.am

    diff -Naur exo-0.3.101-old/exo-mount/Makefile.am exo-0.3.101/exo-mount/Makefile.am
    old new  
    66        -DG_LOG_DOMAIN=\"exo-mount\"                                    \
    77        -DLIBEXECDIR=\"$(libexecdir)\"                                  \
    88        -DLIBEXO_VERSION_API=\"$(LIBEXO_VERSION_API)\"                  \
    9         -DPACKAGE_LOCALE_DIR=\"$(localedir)\"
     9        -DPACKAGE_LOCALE_DIR=\"$(localedir)\"                           \
     10        -DDATADIR=\"$(datadir)\"
    1011
    1112bin_PROGRAMS =                                                          \
    1213        exo-mount
  • exo-mount/Makefile.in

    diff -Naur exo-0.3.101-old/exo-mount/Makefile.in exo-0.3.101/exo-mount/Makefile.in
    old new  
    299299        -DG_LOG_DOMAIN=\"exo-mount\"                                    \
    300300        -DLIBEXECDIR=\"$(libexecdir)\"                                  \
    301301        -DLIBEXO_VERSION_API=\"$(LIBEXO_VERSION_API)\"                  \
    302         -DPACKAGE_LOCALE_DIR=\"$(localedir)\"
     302        -DPACKAGE_LOCALE_DIR=\"$(localedir)\"                           \
     303        -DDATADIR=\"$(datadir)\"
    303304
    304305exo_mount_SOURCES = exo-mount-fstab.c exo-mount-fstab.h \
    305306        exo-mount-utils.c exo-mount-utils.h main.c $(am__append_1)
     
    386387          echo " rm -f $$p $$f"; \
    387388          rm -f $$p $$f ; \
    388389        done
    389 exo-mount$(EXEEXT): $(exo_mount_OBJECTS) $(exo_mount_DEPENDENCIES) 
     390exo-mount$(EXEEXT): $(exo_mount_OBJECTS) $(exo_mount_DEPENDENCIES)
    390391        @rm -f exo-mount$(EXEEXT)
    391392        $(exo_mount_LINK) $(exo_mount_OBJECTS) $(exo_mount_LDADD) $(LIBS)
    392393