Changeset 950e2da


Ignore:
Timestamp:
Nov 19, 2010, 2:15:49 AM (11 years ago)
Author:
Karl Ramm <kcr@1ts.org>
Branches:
master, release-1.7, release-1.8, release-1.9
Children:
1dd285b
Parents:
5fca55f
git-author:
Jason Gross <jgross@MIT.EDU> (11/17/10 02:18:48)
git-committer:
Karl Ramm <kcr@1ts.org> (11/19/10 02:15:49)
Message:
Fixed :unsub to make it work if ~/.zephyr.subs is a symlink (trac 133)

link() fails on AFS if the target is a symlink.  Additionally, on
systems where link() succeeds, barnowl overwrites the symlink, instead
of the actual file.  To fix this, I've changed owl_util_file_deleteline
to resolve symlinks on the passed file name first.  The new (backup)
file is written in the resolved directory, not the directory where the
symlink itself is found.

A helper function, owl_util_recursive_resolve_link, is added to
recursivly resolve symlinks (if necessary).

Reviewed-By: Karl Ramm <kcr@1ts.org>
File:
1 edited

Legend:

Unmodified
Added
Removed
  • util.c

    r5fca55f r950e2da  
    77#include <sys/stat.h>
    88#include <sys/types.h>
    9 
     9#include <assert.h>
     10#include <glib.h>
     11#include <glib/gstdio.h>
    1012#include <glib-object.h>
    1113
     
    376378}
    377379
     380
     381/* If filename is a link, recursively resolve symlinks.  Otherwise, return the filename
     382 * unchanged.  On error, call owl_function_error and return NULL.
     383 *
     384 * This function assumes that filename eventually resolves to an acutal file.
     385 * If you want to check this, you should stat() the file first.
     386 *
     387 * The caller of this function is responsible for freeing the return value.
     388 *
     389 * Error conditions are the same as g_file_read_link.
     390 */
     391gchar *owl_util_recursive_resolve_link(const char *filename)
     392{
     393  gchar *last_filename = g_strdup(filename);
     394  GError *err = NULL;
     395  while (last_filename != NULL && g_file_test(last_filename, G_FILE_TEST_IS_SYMLINK)) {
     396    gchar *cur_filename = g_file_read_link(last_filename, &err);
     397    g_free(last_filename);
     398    last_filename = cur_filename;
     399  }
     400  if (last_filename == NULL) {
     401    owl_function_error("Cannot resolve symlinked file %s: %s",
     402                       filename, err->message);
     403    g_error_free(err);
     404  }
     405  return last_filename;
     406}
     407
    378408/* Delete all lines matching "line" from the named file.  If no such
    379409 * line is found the file is left intact.  If backup==1 then leave a
     
    386416{
    387417  char *backupfile, *newfile, *buf = NULL;
     418  gchar *actual_filename; /* gchar; we need to g_free it */
    388419  FILE *old, *new;
    389420  struct stat st;
     
    401432  }
    402433
    403   newfile = owl_sprintf("%s.new", filename);
     434  /* resolve symlinks, because link() fails on symlinks, at least on AFS */
     435  actual_filename = owl_util_recursive_resolve_link(filename);
     436  if (actual_filename == NULL)
     437    return -1; /* resolving the symlink failed, but we already logged this error */
     438
     439  newfile = owl_sprintf("%s.new", actual_filename);
    404440  if ((new = fopen(newfile, "w")) == NULL) {
    405441    owl_function_error("Cannot open %s (for writing): %s",
    406                        filename, strerror(errno));
     442                       actual_filename, strerror(errno));
    407443    owl_free(newfile);
    408444    fclose(old);
     445    free(actual_filename);
    409446    return -1;
    410447  }
     
    412449  if (fchmod(fileno(new), st.st_mode & 0777) != 0) {
    413450    owl_function_error("Cannot set permissions on %s: %s",
    414                        filename, strerror(errno));
     451                       actual_filename, strerror(errno));
    415452    unlink(newfile);
    416453    fclose(new);
    417454    owl_free(newfile);
    418455    fclose(old);
     456    free(actual_filename);
    419457    return -1;
    420458  }
     
    431469
    432470  if (backup) {
    433     backupfile = owl_sprintf("%s.backup", filename);
     471    backupfile = owl_sprintf("%s.backup", actual_filename);
    434472    unlink(backupfile);
    435     if (link(filename, backupfile) != 0) {
     473    if (link(actual_filename, backupfile) != 0) {
    436474      owl_function_error("Cannot link %s: %s", backupfile, strerror(errno));
    437475      owl_free(backupfile);
     
    443481  }
    444482
    445   if (rename(newfile, filename) != 0) {
     483  if (rename(newfile, actual_filename) != 0) {
    446484    owl_function_error("Cannot move %s to %s: %s",
    447                        newfile, filename, strerror(errno));
     485                       newfile, actual_filename, strerror(errno));
    448486    numremoved = -1;
    449487  }
     
    451489  unlink(newfile);
    452490  owl_free(newfile);
     491
     492  g_free(actual_filename);
    453493
    454494  return numremoved;
Note: See TracChangeset for help on using the changeset viewer.