示例#1
0
/*! \brief Check if a file has an active autosave file
 *  \par Function Description
 *  Checks whether an autosave file exists for the \a filename passed
 *  which has a modification time newer than the file itself.  If the
 *  check fails, sets \a err with the reason.  N.b. if the autosave
 *  file exists but it was not possible to get its modification time,
 *  returns TRUE.
 *
 *  \param [in] filename File to check
 *  \param [in,out] err  #GError structure for error reporting, or
 *                       NULL to disable error reporting
 *
 *  \returns TRUE if autosave active, FALSE otherwise
 */
gboolean f_has_active_autosave (const gchar *filename, GError **err)
{
  gboolean result = FALSE;
  gchar *auto_filename;
  gint file_err = 0;
  gint auto_err = 0;
  GFileError g_errcode = 0;
  struct stat file_stat, auto_stat;

  auto_filename = f_get_autosave_filename (filename);
  if (stat (filename, &file_stat) != 0) {
    file_err = errno;
  }
  if (stat (auto_filename, &auto_stat) != 0) {
    auto_err = errno;
  }

  /* A valid use of goto! (checks for raptors) */
  if (auto_err & ENOENT) {
    /* The autosave file does not exist. */
    result = FALSE;
    goto check_autosave_finish;
  }
  if (auto_err) {
    g_errcode = g_file_error_from_errno (auto_err);
    g_set_error (err, G_FILE_ERROR, g_errcode,
                 _("Failed to stat [%s]: %s"),
                 auto_filename, g_strerror (auto_err));
    result = TRUE;
    goto check_autosave_finish;
  }
  if (file_err & ENOENT) {
    /* The autosave file exists, but the actual file does not. */
    result = TRUE;
    goto check_autosave_finish;
  }
  if (file_err) {
    g_errcode = g_file_error_from_errno (file_err);
    g_set_error (err, G_FILE_ERROR, g_errcode,
                 _("Failed to stat [%s]: %s"),
                 auto_filename, g_strerror (file_err));
    result = TRUE;
    goto check_autosave_finish;
  }
  /* If we got this far, both files exist and we have managed to get
   * their stat info. */
  if (difftime (file_stat.st_mtime, auto_stat.st_mtime) < 0) {
    result = TRUE;
  }

 check_autosave_finish:
  g_free (auto_filename);
  return result;
}
示例#2
0
/*! \brief Opens the schematic file with fine-grained control over behaviour.
 *  \par Function Description
 *  Opens the schematic file and carries out a number of actions
 *  depending on the \a flags set.  If #F_OPEN_RC is set, executes
 *  configuration files found in the target directory.  If
 *  #F_OPEN_CHECK_BACKUP is set, warns user if a backup is found for
 *  the file being loaded, and possibly prompts user for whether to
 *  load the backup instead.  If #F_OPEN_RESTORE_CWD is set, does not
 *  change the working directory to that of the file being loaded.
 *
 *  \param [in,out] toplevel  The TOPLEVEL object to load the schematic into.
 *  \param [in]     filename   A character string containing the file name
 *                             to open.
 *  \param [in]     flags      Combination of #FOpenFlags values.
 *  \param [in,out] err  #GError structure for error reporting, or
 *                       NULL to disable error reporting
 *
 *  \return 0 on failure, 1 on success.
 */
int f_open_flags(TOPLEVEL *toplevel, PAGE *page,
                 const gchar *filename,
                 const gint flags, GError **err)
{
  int opened=FALSE;
  char *full_filename = NULL;
  char *full_rcfilename = NULL;
  char *file_directory = NULL;
  char *saved_cwd = NULL;
  char *backup_filename = NULL;
  char load_backup_file = 0;
  GError *tmp_err = NULL;

  /* has the head been freed yet? */
  /* probably not hack PAGE */

  set_window(toplevel, page,
             toplevel->init_left, toplevel->init_right,
             toplevel->init_top,  toplevel->init_bottom);


  /* Cache the cwd so we can restore it later. */
  if (flags & F_OPEN_RESTORE_CWD) {
    saved_cwd = g_get_current_dir();
  }

  /* get full, absolute path to file */
  full_filename = f_normalize_filename (filename, &tmp_err);
  if (full_filename == NULL) {
    g_set_error (err, G_FILE_ERROR, tmp_err->code,
                 _("Cannot find file %s: %s"),
                 filename, tmp_err->message);
    g_error_free(tmp_err);
    return 0;
  }

  /* write full, absolute filename into page->page_filename */
  g_free(page->page_filename);
  page->page_filename = g_strdup(full_filename);

  /* Before we open the page, let's load the corresponding gafrc. */
  /* First cd into file's directory. */
  file_directory = g_dirname (full_filename);

  if (file_directory) { 
    if (chdir (file_directory)) {
      /* Error occurred with chdir */
#warning FIXME: What do we do?
    }
  }

  /* Now open RC and process file */
  if (flags & F_OPEN_RC) {
    full_rcfilename = g_build_filename (file_directory, "gafrc", NULL);
    g_rc_parse_file (toplevel, full_rcfilename, &tmp_err);
    if (tmp_err != NULL) {
      /* Config files are allowed to be missing or skipped; check for
       * this. */
      if (!g_error_matches (tmp_err, G_FILE_ERROR, G_FILE_ERROR_NOENT) &&
          !g_error_matches (tmp_err, EDA_ERROR, EDA_ERROR_RC_TWICE)) {
        s_log_message ("%s\n", tmp_err->message);
      }
      g_error_free (tmp_err);
      tmp_err = NULL;
    }
  }

  g_free (file_directory);

  if (flags & F_OPEN_CHECK_BACKUP) {
    /* Check if there is a newer autosave backup file */
    GString *message;
    gboolean active_backup = f_has_active_autosave (full_filename, &tmp_err);
    backup_filename = f_get_autosave_filename (full_filename);

    if (tmp_err != NULL) g_warning ("%s\n", tmp_err->message);
    if (active_backup) {
      message = g_string_new ("");
      g_string_append_printf(message, _("\nWARNING: Found an autosave backup file:\n  %s.\n\n"), backup_filename);
      if (tmp_err != NULL) {
        g_string_append(message, _("I could not guess if it is newer, so you have to do it manually.\n"));
      } else {
        g_string_append(message, _("The backup copy is newer than the schematic, so it seems you should load it instead of the original file.\n"));
      }
      g_string_append (message, _("Gschem usually makes backup copies automatically, and this situation happens when it crashed or it was forced to exit abruptly.\n"));
      if (toplevel->load_newer_backup_func == NULL) {
        g_warning ("%s", message->str);
        g_warning (_("\nRun gschem and correct the situation.\n\n"));
      } else {
        /* Ask the user if load the backup or the original file */
        if (toplevel->load_newer_backup_func
            (toplevel->load_newer_backup_data, message)) {
          /* Load the backup file */
          load_backup_file = 1;
        }
      }
      g_string_free (message, TRUE);
    }
    if (tmp_err != NULL) g_error_free (tmp_err);
  }

  /* Now that we have set the current directory and read
   * the RC file, it's time to read in the file. */
  if (load_backup_file == 1) {
    /* Load the backup file */
    s_page_append_list (toplevel, page,
                        o_read (toplevel, NULL, backup_filename, &tmp_err));
  } else {
    /* Load the original file */
    s_page_append_list (toplevel, page,
                        o_read (toplevel, NULL, full_filename, &tmp_err));
  }

  if (tmp_err == NULL)
    opened = TRUE;
  else
    g_propagate_error (err, tmp_err);

  if (load_backup_file == 0) {
    /* If it's not the backup file */
    page->CHANGED=0; /* added 4/7/98 */
  } else {
    /* We are loading the backup file, so gschem should ask
       the user if save it or not when closing the page. */
    page->CHANGED=1;
  }

  g_free(full_filename);
  g_free(full_rcfilename);
  g_free (backup_filename);

  /* Reset the directory to the value it had when f_open was
   * called. */
  if (flags & F_OPEN_RESTORE_CWD) {
    if (chdir (saved_cwd)) {
      /* Error occurred with chdir */
#warning FIXME: What do we do?
    }
    g_free(saved_cwd);
  }

  return opened;
}
示例#3
0
/*! \brief delete a page and it's contents
 *  \par Function Description
 *  Deletes a single page <B>page</B> from <B>toplevel</B>'s list of pages.
 *
 *  See #s_page_delete_list() to delete all pages of a <B>toplevel</B>
 *
 *  If the current page of toplevel is given as parameter <B>page</B>,
 *  the function sets the field <B>page_current</B> of the TOPLEVEL
 *  struct to NULL.
 */
void s_page_delete (TOPLEVEL *toplevel, PAGE *page)
{
  PAGE *tmp;
  gchar *backup_filename;
  gchar *real_filename;

  /* We need to temporarily make the page being deleted current because
   * various functions called below (some indirectly) assume they are
   * deleting objects from the current page.
   *
   * These functions are known to include:
   *   s_delete_object ()
   */

  /* save page_current and switch to page */
  if (page == toplevel->page_current) {
    tmp = NULL;
  } else {
    tmp = toplevel->page_current;
    s_page_goto (toplevel, page);
  }

  /* Get the real filename and file permissions */
  real_filename = follow_symlinks (page->page_filename, NULL);
  
  if (real_filename == NULL) {
    s_log_message (_("s_page_delete: Can't get the real filename of %s."),
                   page->page_filename);
  }
  else {
    backup_filename = f_get_autosave_filename (real_filename);

    /* Delete the backup file */
    if ( (g_file_test (backup_filename, G_FILE_TEST_EXISTS)) && 
	 (!g_file_test(backup_filename, G_FILE_TEST_IS_DIR)) )
    {
      if (unlink(backup_filename) != 0) {
	s_log_message(_("s_page_delete: Unable to delete backup file %s."),
                      backup_filename);
      }
    }
    g_free (backup_filename);
  }
  g_free(real_filename);

  /* Free the selection object */
  g_object_unref( page->selection_list );

  /* then delete objects of page */
  s_page_delete_objects (toplevel, page);

  /* Free the objects in the place list. */
  s_delete_object_glist (toplevel, page->place_list);
  page->place_list = NULL;

#if DEBUG
  printf("Freeing page: %s\n", page->page_filename);
  s_tile_print(toplevel);
#endif
  s_tile_free_all (page);

  s_stretch_destroy_all (page->stretch_list);

  /* free current page undo structs */
  s_undo_free_all (toplevel, page); 

  /* ouch, deal with parents going away and the children still around */
  page->up = -2;
  g_free (page->page_filename);

  geda_list_remove( toplevel->pages, page );

#if DEBUG
  s_tile_print (toplevel);
#endif

  g_free (page);

  /* restore page_current */
  if (tmp != NULL) {
    s_page_goto (toplevel, tmp);
  } else {
    /* page was page_current */
    toplevel->page_current = NULL;
    /* page_current must be updated by calling function */
  }

}
示例#4
0
文件: s_page.c 项目: vzh/geda-gaf
/*! \brief delete a page and it's contents
 *  \par Function Description
 *  Deletes a single page <B>page</B> from <B>toplevel</B>'s list of pages.
 *
 *  See #s_page_delete_list() to delete all pages of a <B>toplevel</B>
 *
 *  If the current page of toplevel is given as parameter <B>page</B>,
 *  the function sets the field <B>page_current</B> of the TOPLEVEL
 *  struct to NULL.
 */
void s_page_delete (TOPLEVEL *toplevel, PAGE *page)
{
  PAGE *tmp;
  gchar *backup_filename;
  gchar *real_filename;

  /* We need to temporarily make the page being deleted current because
   * various functions called below (some indirectly) assume they are
   * deleting objects from the current page.
   *
   * These functions are known to include:
   *   s_delete_object ()
   */

  /* save page_current and switch to page */
  if (page == toplevel->page_current) {
    tmp = NULL;
  } else {
    tmp = toplevel->page_current;
    s_page_goto (toplevel, page);
  }

  /* Get the real filename and file permissions */
  real_filename = follow_symlinks (page->page_filename, NULL);
  
  if (real_filename == NULL) {
    s_log_message (_("s_page_delete: Can't get the real filename of %s."),
                   page->page_filename);
  }
  else {
    backup_filename = f_get_autosave_filename (real_filename);

    /* Delete the backup file */
    if ( (g_file_test (backup_filename, G_FILE_TEST_EXISTS)) && 
	 (!g_file_test(backup_filename, G_FILE_TEST_IS_DIR)) )
    {
      if (unlink(backup_filename) != 0) {
	s_log_message(_("s_page_delete: Unable to delete backup file %s."),
                      backup_filename);
      }
    }
    g_free (backup_filename);
  }
  g_free(real_filename);

  /* Free the selection object */
  g_object_unref( page->selection_list );

  /* then delete objects of page */
  s_page_delete_objects (toplevel, page);

  /* Free the objects in the place list. */
  s_delete_object_glist (toplevel, page->place_list);
  page->place_list = NULL;

  /*  This removes all objects from the list of connectible objects
   *  of the given \a page. */
  if (g_list_length (page->connectible_list) != 0) {
    fprintf (stderr,
            "OOPS! page->connectible_list had something in it when it was freed!\n");
    fprintf (stderr, "Length: %d\n", g_list_length (page->connectible_list));
  }

  g_list_free (page->connectible_list);
  page->connectible_list = NULL;

  /* free current page undo structs */
  s_undo_free_all (toplevel, page); 

  /* ouch, deal with parents going away and the children still around */
  page->up = -2;
  g_free (page->page_filename);

  geda_list_remove( toplevel->pages, page );

  s_weakref_notify (page, page->weak_refs);

  g_free (page);

  /* restore page_current */
  if (tmp != NULL) {
    s_page_goto (toplevel, tmp);
  } else {
    /* page was page_current */
    s_toplevel_set_page_current (toplevel, NULL);
    /* page_current must be updated by calling function */
  }

}