Пример #1
0
/*! \brief Save the schematic file
 *  \par Function Description
 *  This function saves the current schematic file in the toplevel object.
 *
 *  \param [in,out] toplevel  The TOPLEVEL object containing the schematic.
 *  \param [in]      filename  The file name to save the schematic to.
 *  \param [in,out] err       #GError structure for error reporting, or
 *                            NULL to disable error reporting
 *  \return 1 on success, 0 on failure.
 */
int f_save(TOPLEVEL *toplevel, PAGE *page, const char *filename, GError **err)
{
  gchar *backup_filename;
  gchar *real_filename;
  gchar *only_filename;
  gchar *dirname;
  mode_t saved_umask, mask;
  struct stat st;
  GError *tmp_err = NULL;

  /* Get the real filename and file permissions */
  real_filename = follow_symlinks (filename, &tmp_err);

  if (real_filename == NULL) {
    g_set_error (err, tmp_err->domain, tmp_err->code,
                 _("Can't get the real filename of %s: %s"),
                 filename,
                 tmp_err->message);
    return 0;
  }
  
  /* Get the directory in which the real filename lives */
  dirname = g_path_get_dirname (real_filename);
  only_filename = g_path_get_basename(real_filename);  

  /* Do a backup if it's not an undo file backup and it was never saved. */
  if (page->saved_since_first_loaded == 0) {
    if ( (g_file_test (real_filename, G_FILE_TEST_EXISTS)) && 
	 (!g_file_test(real_filename, G_FILE_TEST_IS_DIR)) )
    {
      backup_filename = g_strdup_printf("%s%c%s~", dirname, 
					G_DIR_SEPARATOR, only_filename);

      /* Make the backup file read-write before saving a new one */
      if ( g_file_test (backup_filename, G_FILE_TEST_EXISTS) && 
	   (! g_file_test (backup_filename, G_FILE_TEST_IS_DIR))) {
	if (chmod(backup_filename, S_IREAD|S_IWRITE) != 0) {
	  s_log_message (_("Could NOT set previous backup file [%s] read-write\n"),
			 backup_filename);
	}
      }
	
      if (rename(real_filename, backup_filename) != 0) {
	s_log_message (_("Can't save backup file: %s."), backup_filename);
      }
      else {
	/* Make the backup file readonly so a 'rm *' command will ask 
	   the user before deleting it */
	saved_umask = umask(0);
	mask = (S_IWRITE|S_IWGRP|S_IEXEC|S_IXGRP|S_IXOTH);
	mask = (~mask)&0777;
	mask &= ((~saved_umask) & 0777);
	if (chmod(backup_filename, mask) != 0) {
	  s_log_message (_("Could NOT set backup file [%s] readonly\n"),
                         backup_filename);
	}
	umask(saved_umask);
      }

      g_free(backup_filename);
    }
  }
    /* If there is not an existing file with that name, compute the
     * permissions and uid/gid that we will use for the newly-created file.
     */
       
  if (stat (real_filename, &st) != 0)
  {
    struct stat dir_st;
    int result;
    
    /* Use default permissions */
    saved_umask = umask(0);
    st.st_mode = 0666 & ~saved_umask;
    umask(saved_umask);
#ifdef HAVE_CHOWN
    st.st_uid = getuid ();
    
    result = stat (dirname, &dir_st);
    
    if (result == 0 && (dir_st.st_mode & S_ISGID))
	  st.st_gid = dir_st.st_gid;
    else
    st.st_gid = getgid ();
#endif /* HAVE_CHOWN */
  }
  g_free (dirname);
  g_free (only_filename);
  
  if (o_save (toplevel, s_page_objects (page), real_filename, &tmp_err)) {

    page->saved_since_first_loaded = 1;

    /* Reset the last saved timer */
    g_get_current_time (&page->last_load_or_save_time);
    page->ops_since_last_backup = 0;
    page->do_autosave_backup = 0;

    /* Restore permissions. */
    chmod (real_filename, st.st_mode);
#ifdef HAVE_CHOWN
    if (chown (real_filename, st.st_uid, st.st_gid)) {
      /* Error occured with chown */
#warning FIXME: What do we do?
    }
#endif

    g_free (real_filename);
    return 1;
  }
  else {
    g_set_error (err, tmp_err->domain, tmp_err->code,
                 _("Could NOT save file: %s"), tmp_err->message);
    g_clear_error (&tmp_err);
    g_free (real_filename);
    return 0;
  }
}
Пример #2
0
/*! \brief Do autosave on all pages that are marked.
 *  \par Function Description
 *  Looks for pages with the do_autosave_backup flag activated and
 *  autosaves them.
 *
 *  \param [in] w_current  The GSCHEM_TOPLEVEL object to search for autosave's.
 */
void o_autosave_backups(GSCHEM_TOPLEVEL *w_current)
{
  TOPLEVEL *toplevel = w_current->toplevel;
  GList *iter;
  PAGE *p_save, *p_current;
  gchar *backup_filename;
  gchar *real_filename;
  gchar *only_filename;
  gchar *dirname;
  mode_t saved_umask;
  mode_t mask;
  struct stat st;

  /* save current page */
  p_save = toplevel->page_current;

  for ( iter = geda_list_get_glist( toplevel->pages );
        iter != NULL;
        iter = g_list_next( iter ) ) {

    p_current = (PAGE *)iter->data;

    if (p_current->do_autosave_backup == 0) {
      continue;
    }
    if (p_current->ops_since_last_backup != 0) {
      /* make p_current the current page of toplevel */
      s_page_goto (toplevel, p_current);

      /* Get the real filename and file permissions */
      real_filename = follow_symlinks (p_current->page_filename, NULL);

      if (real_filename == NULL) {
        s_log_message (_("o_autosave_backups: Can't get the real filename of %s."), p_current->page_filename);
      } else {
        /* Get the directory in which the real filename lives */
        dirname = g_path_get_dirname (real_filename);
        only_filename = g_path_get_basename(real_filename);

        backup_filename = g_strdup_printf("%s%c"AUTOSAVE_BACKUP_FILENAME_STRING,
                                          dirname, G_DIR_SEPARATOR, only_filename);

        /* If there is not an existing file with that name, compute the
         * permissions and uid/gid that we will use for the newly-created file.
         */

        if (stat (real_filename, &st) != 0) {
#if defined(HAVE_GETUID) && defined(HAVE_GETGID)
            struct stat dir_st;
            int result;
#endif

            /* Use default permissions */
            saved_umask = umask(0);
            st.st_mode = 0666 & ~saved_umask;
            umask(saved_umask);
#if defined(HAVE_GETUID) && defined(HAVE_GETGID)
            st.st_uid = getuid ();

            result = stat (dirname, &dir_st);

            if (result == 0 && (dir_st.st_mode & S_ISGID))
              st.st_gid = dir_st.st_gid;
            else
              st.st_gid = getgid ();
#endif
          }
        g_free (dirname);
        g_free (only_filename);
        g_free (real_filename);

        /* Make the backup file writable before saving a new one */
        if ( g_file_test (backup_filename, G_FILE_TEST_EXISTS) &&
             (! g_file_test (backup_filename, G_FILE_TEST_IS_DIR))) {
          saved_umask = umask(0);
          if (chmod(backup_filename, (S_IWRITE|S_IWGRP|S_IWOTH) &
                    ((~saved_umask) & 0777)) != 0) {
            s_log_message (_("Could NOT set previous backup file [%s] read-write\n"),
                           backup_filename);
          }
          umask(saved_umask);
        }

        if (o_save (toplevel,
                    s_page_objects (toplevel->page_current),
                    backup_filename, NULL)) {

          p_current->ops_since_last_backup = 0;
                p_current->do_autosave_backup = 0;

          /* Make the backup file readonly so a 'rm *' command will ask
             the user before deleting it */
          saved_umask = umask(0);
          mask = (S_IWRITE|S_IWGRP|S_IEXEC|S_IXGRP|S_IXOTH);
          mask = (~mask)&0777;
          mask &= ((~saved_umask) & 0777);
          if (chmod(backup_filename,mask) != 0) {
            s_log_message (_("Could NOT set backup file [%s] readonly\n"),
                           backup_filename);
          }
          umask(saved_umask);
        } else {
          s_log_message (_("Could NOT save backup file [%s]\n"),
                         backup_filename);
        }
        g_free (backup_filename);
      }
    }
  }
  /* restore current page */
  s_page_goto (toplevel, p_save);
}
Пример #3
0
GsfOutput *
gsf_output_stdio_new_valist (char const *filename, GError **err,
			     char const *first_property_name,
			     va_list     var_args)
{
	GsfOutputStdio *stdio;
	FILE *file = NULL;
	char *dirname = NULL;
	char *temp_filename = NULL;
	char *real_filename = follow_symlinks (filename, err);
	int fd;
	mode_t saved_umask;
	struct stat st;
	gboolean fixup_mode = FALSE;

	if (real_filename == NULL)
		goto failure;

	/* Get the directory in which the real filename lives */
	dirname = g_path_get_dirname (real_filename);

	if (g_stat (real_filename, &st) == 0) {
		if (!S_ISREG (st.st_mode)) {
			if (err != NULL) {
				char *dname = g_filename_display_name
					(real_filename);
				*err = g_error_new (gsf_output_error_id (), 0,
						    _("%s: Is not a regular file"),
						    dname);
				g_free (dname);
			}
			goto failure;
		}

		/* FIXME? Race conditions en masse.  */
		if (g_access (real_filename, W_OK) == -1) {
			if (err != NULL) {
				int save_errno = errno;
				char *dname = g_filename_display_name
					(real_filename);
				*err = g_error_new
					(gsf_output_error_id (), errno,
					 "%s: %s",
					 dname, g_strerror (save_errno));
				g_free (dname);
			}
			goto failure;
		}
	} else {
		/*
		 * File does not exist.  Compute the permissions and uid/gid
		 * that we will use for the newly-created file.
		 */

		memset (&st, 0, sizeof (st));

		/* Use default permissions */
		st.st_mode = 0666;  fixup_mode = TRUE;
#ifdef HAVE_CHOWN
		{
			struct stat dir_st;

			st.st_uid = getuid ();

			if (g_stat (dirname, &dir_st) == 0 &&
			    S_ISDIR (dir_st.st_mode) &&
			    (dir_st.st_mode & S_ISGID))
				st.st_gid = dir_st.st_gid;
			else
				st.st_gid = getgid ();
		}
#endif
	}

	/* Save to a temporary file.  We set the umask because some (buggy)
	 * implementations of mkstemp() use permissions 0666 and we want 0600.
	 */
	temp_filename = g_build_filename (dirname, ".gsf-save-XXXXXX", NULL);
	/* Oh, joy.  What about threads?  --MW */
	saved_umask = umask (0077);
	fd = g_mkstemp (temp_filename); /* this modifies temp_filename to the used name */
	umask (saved_umask);

	if (fixup_mode)
		st.st_mode &= ~saved_umask;

	if (fd < 0 || NULL == (file = fdopen (fd, "wb"))) {
		if (err != NULL) {
			int save_errno = errno;
			char *dname = g_filename_display_name
				(temp_filename);
			*err = g_error_new
				(gsf_output_error_id (), errno,
				 "%s: %s",
				 dname, g_strerror (save_errno));
			g_free (dname);
		}
		goto failure;
	}

	stdio = (GsfOutputStdio *)g_object_new_valist (GSF_OUTPUT_STDIO_TYPE,
		first_property_name, var_args);
	stdio->file = file;
	stdio->st = st;
	stdio->create_backup_copy = FALSE;
	stdio->real_filename = real_filename;
	stdio->temp_filename = temp_filename;

	gsf_output_set_name_from_filename (GSF_OUTPUT (stdio), filename);

	g_free (dirname);

	return GSF_OUTPUT (stdio);

 failure:
	g_free (temp_filename);
	g_free (real_filename);
	g_free (dirname);
	return NULL;
}
Пример #4
0
int
main(int argc, char **argv)
{
	int c;
	int rc = EXIT_SUCCESS;

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);
	atexit(close_stdout);

	while ((c = getopt_long(argc, argv, "hVlmnovx", longopts, NULL)) != -1) {
		switch(c) {
		case 'h':
			usage(EXIT_SUCCESS);
			break;
		case 'V':
			printf(UTIL_LINUX_VERSION);
			return EXIT_SUCCESS;
		case 'l':
			flags |= (NAMEI_OWNERS | NAMEI_MODES | NAMEI_VERTICAL);
			break;
		case 'm':
			flags |= NAMEI_MODES;
			break;
		case 'n':
			flags |= NAMEI_NOLINKS;
			break;
		case 'o':
			flags |= NAMEI_OWNERS;
			break;
		case 'x':
			flags |= NAMEI_MNTS;
			break;
		case 'v':
			flags |= NAMEI_VERTICAL;
			break;
		default:
			usage(EXIT_FAILURE);
		}
	}

	if (optind == argc) {
		warnx(_("pathname argument is missing"));
		usage(EXIT_FAILURE);
	}

	for(; optind < argc; optind++) {
		char *path = argv[optind];
		struct namei *nm = NULL;
		struct stat st;

		if (stat(path, &st) != 0)
			rc = EXIT_FAILURE;

		nm = add_namei(NULL, path, 0, NULL);
		if (nm) {
			int sml = 0;
			if (!(flags & NAMEI_NOLINKS))
				sml = follow_symlinks(nm);
			if (print_namei(nm, path)) {
				rc = EXIT_FAILURE;
				continue;
			}
			free_namei(nm);
			if (sml == -1) {
				rc = EXIT_FAILURE;
				warnx(_("%s: exceeded limit of symlinks"), path);
				continue;
			}
		}
	}

	free_idcache(ucache);
	free_idcache(gcache);

	return rc;
}
Пример #5
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 */
  }

}
Пример #6
0
int
main(int argc, char **argv)
{
	extern int optind;
	int c;

	setlocale(LC_ALL, "");
	bindtextdomain(PACKAGE, LOCALEDIR);
	textdomain(PACKAGE);

	if (argc < 2)
		usage(EXIT_FAILURE);

	while ((c = getopt_long(argc, argv, "+h?lmnovx", longopts, NULL)) != -1) {
		switch(c) {
		case 'h':
		case '?':
			usage(EXIT_SUCCESS);
			break;
		case 'l':
			flags |= (NAMEI_OWNERS | NAMEI_MODES | NAMEI_VERTICAL);
			break;
		case 'm':
			flags |= NAMEI_MODES;
			break;
		case 'n':
			flags |= NAMEI_NOLINKS;
			break;
		case 'o':
			flags |= NAMEI_OWNERS;
			break;
		case 'x':
			flags |= NAMEI_MNTS;
			break;
		case 'v':
			flags |= NAMEI_VERTICAL;
		}
	}

	for(; optind < argc; optind++) {
		char *path = argv[optind];
		struct namei *nm = NULL;
		struct stat st;

		if (stat(path, &st) != 0)
			err(EXIT_FAILURE, _("failed to stat: %s"), path);

		nm = add_namei(NULL, path, 0, NULL);
		if (nm) {
			int sml = 0;
			if (!(flags & NAMEI_NOLINKS))
				sml = follow_symlinks(nm);
			print_namei(nm, path);
			free_namei(nm);
			if (sml == -1)
				errx(EXIT_FAILURE,
					_("%s: exceeded limit of symlinks"),
					path);
		}
	}

	free_idcache(ucache);
	free_idcache(gcache);

	return EXIT_SUCCESS;
}
Пример #7
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;

  /*  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 */
  }

}
ALLEGRO_PATH *_al_unix_get_path(int id)
{
   switch (id) {
      case ALLEGRO_TEMP_PATH: {
         /* Check: TMP, TMPDIR, TEMP or TEMPDIR */
         char *envs[] = { "TMP", "TMPDIR", "TEMP", "TEMPDIR", NULL};
         uint32_t i = 0;
         for (; envs[i] != NULL; ++i) {
            char *tmp = getenv(envs[i]);
            if (tmp) {
               return al_create_path_for_directory(tmp);
            }
         }

         /* next try: /tmp /var/tmp /usr/tmp */
         char *paths[] = { "/tmp/", "/var/tmp/", "/usr/tmp/", NULL };
         for (i=0; paths[i] != NULL; ++i) {
            ALLEGRO_FS_ENTRY *fse = al_create_fs_entry(paths[i]);
            bool found = (al_get_fs_entry_mode(fse) & ALLEGRO_FILEMODE_ISDIR) != 0;
            al_destroy_fs_entry(fse);
            if (found) {
               return al_create_path_for_directory(paths[i]);
            }
         }

         /* Give up? */
         return NULL;
      } break;

      case ALLEGRO_RESOURCES_PATH: {
         ALLEGRO_PATH *exe = get_executable_name();
         exe = follow_symlinks(exe);
         al_set_path_filename(exe, NULL);
         return exe;

      } break;

      case ALLEGRO_USER_DATA_PATH:
      case ALLEGRO_USER_SETTINGS_PATH: {
         ALLEGRO_PATH *local_path = NULL;
         const char *org_name = al_get_org_name();
         const char *app_name = al_get_app_name();
         
         /* to avoid writing directly into the user's directory, require at least an app name */
         if (!app_name)
            return NULL;
         
         /* find the appropriate path from the xdg environment variables, if possible */
         if (id == ALLEGRO_USER_DATA_PATH) {
            const char *xdg_data_home = getenv("XDG_DATA_HOME");
            local_path = al_create_path_for_directory(xdg_data_home ? xdg_data_home : ".local/share");
         }
         else {
            const char *xdg_config_home = getenv("XDG_CONFIG_HOME");
            local_path = al_create_path_for_directory(xdg_config_home ? xdg_config_home : ".config");
         }
         
         if (!local_path) 
            return NULL;
         
         /* if the path is relative, prepend the user's home directory */
         if (al_path_cstr(local_path, '/')[0] != '/') {
            ALLEGRO_PATH *home_path = _unix_find_home();
            if (!home_path)
               return NULL;
            
            al_rebase_path(home_path, local_path);
            al_destroy_path(home_path);
         }

         /* only add org name if not blank */
         if (org_name && org_name[0]) {              
            al_append_path_component(local_path, al_get_org_name());
         }
         
         al_append_path_component(local_path, al_get_app_name());

        return local_path;
      } break;

      case ALLEGRO_USER_HOME_PATH:
         return _unix_find_home();
         
      case ALLEGRO_USER_DOCUMENTS_PATH: {
         ALLEGRO_PATH *local_path = _get_xdg_path("DOCUMENTS");
         return local_path ? local_path : _unix_find_home();
      } break;

      case ALLEGRO_EXENAME_PATH:
         return get_executable_name();
         break;

      default:
         return NULL;
   }

   return NULL;
}