/*! \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; } }
/*! \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); }
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; }
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; }
/*! \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 */ } }
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; }
/*! \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; }