/* * find_my_exec -- find an absolute path to a valid executable * * argv0 is the name passed on the command line * retpath is the output area (must be of size MAXPGPATH) * Returns 0 if OK, -1 if error. * * The reason we have to work so hard to find an absolute path is that * on some platforms we can't do dynamic loading unless we know the * executable's location. Also, we need a full path not a relative * path because we will later change working directory. Finally, we want * a true path not a symlink location, so that we can locate other files * that are part of our installation relative to the executable. */ int find_my_exec(const char *argv0, char *retpath) { char cwd[MAXPGPATH], test_path[MAXPGPATH]; char *path; if (!getcwd(cwd, MAXPGPATH)) { log_error(_("could not identify current directory: %s"), strerror(errno)); return -1; } /* * If argv0 contains a separator, then PATH wasn't used. */ if (first_dir_separator(argv0) != NULL) { if (is_absolute_path(argv0)) StrNCpy(retpath, argv0, MAXPGPATH); else join_path_components(retpath, cwd, argv0); canonicalize_path(retpath); if (validate_exec(retpath) == 0) return resolve_symlinks(retpath); log_error(_("invalid binary \"%s\""), retpath); return -1; } #ifdef WIN32 /* Win32 checks the current directory first for names without slashes */ join_path_components(retpath, cwd, argv0); if (validate_exec(retpath) == 0) return resolve_symlinks(retpath); #endif /* * Since no explicit path was supplied, the user must have been relying on * PATH. We'll search the same PATH. */ if ((path = getenv("PATH")) && *path) { char *startp = NULL, *endp = NULL; do { if (!startp) startp = path; else startp = endp + 1; endp = first_path_var_separator(startp); if (!endp) endp = startp + strlen(startp); /* point to end */ StrNCpy(test_path, startp, Min(endp - startp + 1, MAXPGPATH)); if (is_absolute_path(test_path)) join_path_components(retpath, test_path, argv0); else { join_path_components(retpath, cwd, test_path); join_path_components(retpath, retpath, argv0); } canonicalize_path(retpath); switch (validate_exec(retpath)) { case 0: /* found ok */ return resolve_symlinks(retpath); case -1: /* wasn't even a candidate, keep looking */ break; case -2: /* found but disqualified */ log_error(_("could not read binary \"%s\""), retpath); break; } } while (*endp); } log_error(_("could not find a \"%s\" to execute"), argv0); return -1; }
static int module_clone(int argc, const char **argv, const char *prefix) { const char *name = NULL, *url = NULL; const char *reference = NULL, *depth = NULL; int quiet = 0; FILE *submodule_dot_git; char *p, *path = NULL, *sm_gitdir; struct strbuf rel_path = STRBUF_INIT; struct strbuf sb = STRBUF_INIT; struct option module_clone_options[] = { OPT_STRING(0, "prefix", &prefix, N_("path"), N_("alternative anchor for relative paths")), OPT_STRING(0, "path", &path, N_("path"), N_("where the new submodule will be cloned to")), OPT_STRING(0, "name", &name, N_("string"), N_("name of the new submodule")), OPT_STRING(0, "url", &url, N_("string"), N_("url where to clone the submodule from")), OPT_STRING(0, "reference", &reference, N_("string"), N_("reference repository")), OPT_STRING(0, "depth", &depth, N_("string"), N_("depth for shallow clones")), OPT__QUIET(&quiet, "Suppress output for cloning a submodule"), OPT_END() }; const char *const git_submodule_helper_usage[] = { N_("git submodule--helper clone [--prefix=<path>] [--quiet] " "[--reference <repository>] [--name <name>] [--depth <depth>] " "--url <url> --path <path>"), NULL }; argc = parse_options(argc, argv, prefix, module_clone_options, git_submodule_helper_usage, 0); if (argc || !url || !path || !*path) usage_with_options(git_submodule_helper_usage, module_clone_options); strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name); sm_gitdir = xstrdup(absolute_path(sb.buf)); strbuf_reset(&sb); if (!is_absolute_path(path)) { strbuf_addf(&sb, "%s/%s", get_git_work_tree(), path); path = strbuf_detach(&sb, NULL); } else path = xstrdup(path); if (!file_exists(sm_gitdir)) { if (safe_create_leading_directories_const(sm_gitdir) < 0) die(_("could not create directory '%s'"), sm_gitdir); if (clone_submodule(path, sm_gitdir, url, depth, reference, quiet)) die(_("clone of '%s' into submodule path '%s' failed"), url, path); } else { if (safe_create_leading_directories_const(path) < 0) die(_("could not create directory '%s'"), path); strbuf_addf(&sb, "%s/index", sm_gitdir); unlink_or_warn(sb.buf); strbuf_reset(&sb); } /* Write a .git file in the submodule to redirect to the superproject. */ strbuf_addf(&sb, "%s/.git", path); if (safe_create_leading_directories_const(sb.buf) < 0) die(_("could not create leading directories of '%s'"), sb.buf); submodule_dot_git = fopen(sb.buf, "w"); if (!submodule_dot_git) die_errno(_("cannot open file '%s'"), sb.buf); fprintf_or_die(submodule_dot_git, "gitdir: %s\n", relative_path(sm_gitdir, path, &rel_path)); if (fclose(submodule_dot_git)) die(_("could not close file %s"), sb.buf); strbuf_reset(&sb); strbuf_reset(&rel_path); /* Redirect the worktree of the submodule in the superproject's config */ p = git_pathdup_submodule(path, "config"); if (!p) die(_("could not get submodule directory for '%s'"), path); git_config_set_in_file(p, "core.worktree", relative_path(path, sm_gitdir, &rel_path)); strbuf_release(&sb); strbuf_release(&rel_path); free(sm_gitdir); free(path); free(p); return 0; }
int main(int argc, char **argv) { static struct option long_options[] = { {"help", no_argument, NULL, '?'}, {"version", no_argument, NULL, 'V'}, {"pgdata", required_argument, NULL, 'D'}, {"format", required_argument, NULL, 'F'}, {"checkpoint", required_argument, NULL, 'c'}, {"write-recovery-conf", no_argument, NULL, 'R'}, {"xlog", no_argument, NULL, 'x'}, {"xlog-method", required_argument, NULL, 'X'}, {"gzip", no_argument, NULL, 'z'}, {"compress", required_argument, NULL, 'Z'}, {"label", required_argument, NULL, 'l'}, {"dbname", required_argument, NULL, 'd'}, {"host", required_argument, NULL, 'h'}, {"port", required_argument, NULL, 'p'}, {"username", required_argument, NULL, 'U'}, {"no-password", no_argument, NULL, 'w'}, {"password", no_argument, NULL, 'W'}, {"status-interval", required_argument, NULL, 's'}, {"verbose", no_argument, NULL, 'v'}, {"progress", no_argument, NULL, 'P'}, {"xlogdir", required_argument, NULL, 1}, {NULL, 0, NULL, 0} }; int c; int option_index; progname = get_progname(argv[0]); set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("pg_basebackup")); if (argc > 1) { if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) { usage(); exit(0); } else if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "--version") == 0) { puts("pg_basebackup (PostgreSQL) " PG_VERSION); exit(0); } } while ((c = getopt_long(argc, argv, "D:F:RxX:l:zZ:d:c:h:p:U:s:wWvP", long_options, &option_index)) != -1) { switch (c) { case 'D': basedir = pg_strdup(optarg); break; case 'F': if (strcmp(optarg, "p") == 0 || strcmp(optarg, "plain") == 0) format = 'p'; else if (strcmp(optarg, "t") == 0 || strcmp(optarg, "tar") == 0) format = 't'; else { fprintf(stderr, _("%s: invalid output format \"%s\", must be \"plain\" or \"tar\"\n"), progname, optarg); exit(1); } break; case 'R': writerecoveryconf = true; break; case 'x': if (includewal) { fprintf(stderr, _("%s: cannot specify both --xlog and --xlog-method\n"), progname); exit(1); } includewal = true; streamwal = false; break; case 'X': if (includewal) { fprintf(stderr, _("%s: cannot specify both --xlog and --xlog-method\n"), progname); exit(1); } includewal = true; if (strcmp(optarg, "f") == 0 || strcmp(optarg, "fetch") == 0) streamwal = false; else if (strcmp(optarg, "s") == 0 || strcmp(optarg, "stream") == 0) streamwal = true; else { fprintf(stderr, _("%s: invalid xlog-method option \"%s\", must be \"fetch\" or \"stream\"\n"), progname, optarg); exit(1); } break; case 1: xlog_dir = pg_strdup(optarg); break; case 'l': label = pg_strdup(optarg); break; case 'z': #ifdef HAVE_LIBZ compresslevel = Z_DEFAULT_COMPRESSION; #else compresslevel = 1; /* will be rejected below */ #endif break; case 'Z': compresslevel = atoi(optarg); if (compresslevel <= 0 || compresslevel > 9) { fprintf(stderr, _("%s: invalid compression level \"%s\"\n"), progname, optarg); exit(1); } break; case 'c': if (pg_strcasecmp(optarg, "fast") == 0) fastcheckpoint = true; else if (pg_strcasecmp(optarg, "spread") == 0) fastcheckpoint = false; else { fprintf(stderr, _("%s: invalid checkpoint argument \"%s\", must be \"fast\" or \"spread\"\n"), progname, optarg); exit(1); } break; case 'd': connection_string = pg_strdup(optarg); break; case 'h': dbhost = pg_strdup(optarg); break; case 'p': dbport = pg_strdup(optarg); break; case 'U': dbuser = pg_strdup(optarg); break; case 'w': dbgetpassword = -1; break; case 'W': dbgetpassword = 1; break; case 's': standby_message_timeout = atoi(optarg) * 1000; if (standby_message_timeout < 0) { fprintf(stderr, _("%s: invalid status interval \"%s\"\n"), progname, optarg); exit(1); } break; case 'v': verbose++; break; case 'P': showprogress = true; break; default: /* * getopt_long already emitted a complaint */ fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } } /* * Any non-option arguments? */ if (optind < argc) { fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"), progname, argv[optind]); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } /* * Required arguments */ if (basedir == NULL) { fprintf(stderr, _("%s: no target directory specified\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } /* * Mutually exclusive arguments */ if (format == 'p' && compresslevel != 0) { fprintf(stderr, _("%s: only tar mode backups can be compressed\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } if (format != 'p' && streamwal) { fprintf(stderr, _("%s: WAL streaming can only be used in plain mode\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } if (strcmp(xlog_dir, "") != 0) { if (format != 'p') { fprintf(stderr, _("%s: transaction log directory location can only be specified in plain mode\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } /* clean up xlog directory name, check it's absolute */ canonicalize_path(xlog_dir); if (!is_absolute_path(xlog_dir)) { fprintf(stderr, _("%s: transaction log directory location must be " "an absolute path\n"), progname); fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); exit(1); } } #ifndef HAVE_LIBZ if (compresslevel != 0) { fprintf(stderr, _("%s: this build does not support compression\n"), progname); exit(1); } #endif /* * Verify that the target directory exists, or create it. For plaintext * backups, always require the directory. For tar backups, require it * unless we are writing to stdout. */ if (format == 'p' || strcmp(basedir, "-") != 0) verify_dir_is_empty_or_create(basedir); /* Create transaction log symlink, if required */ if (strcmp(xlog_dir, "") != 0) { char *linkloc; verify_dir_is_empty_or_create(xlog_dir); /* form name of the place where the symlink must go */ linkloc = psprintf("%s/pg_xlog", basedir); #ifdef HAVE_SYMLINK if (symlink(xlog_dir, linkloc) != 0) { fprintf(stderr, _("%s: could not create symbolic link \"%s\": %s\n"), progname, linkloc, strerror(errno)); exit(1); } #else fprintf(stderr, _("%s: symlinks are not supported on this platform")); exit(1); #endif free(linkloc); } BaseBackup(); return 0; }
/* * Create a table space * * Only superusers can create a tablespace. This seems a reasonable restriction * since we're determining the system layout and, anyway, we probably have * root if we're doing this kind of activity */ void CreateTableSpace(CreateTableSpaceStmt *stmt) { #ifdef HAVE_SYMLINK Relation rel; Datum values[Natts_pg_tablespace]; char nulls[Natts_pg_tablespace]; HeapTuple tuple; Oid tablespaceoid; char *location; char *linkloc; Oid ownerId; /* validate */ /* don't call this in a transaction block */ PreventTransactionChain((void *) stmt, "CREATE TABLESPACE"); /* Must be super user */ if (!superuser()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied to create tablespace \"%s\"", stmt->tablespacename), errhint("Must be superuser to create a tablespace."))); /* However, the eventual owner of the tablespace need not be */ if (stmt->owner) ownerId = get_roleid_checked(stmt->owner); else ownerId = GetUserId(); /* Unix-ify the offered path, and strip any trailing slashes */ location = pstrdup(stmt->location); canonicalize_path(location); /* disallow quotes, else CREATE DATABASE would be at risk */ if (strchr(location, '\'')) ereport(ERROR, (errcode(ERRCODE_INVALID_NAME), errmsg("tablespace location may not contain single quotes"))); /* * Allowing relative paths seems risky * * this also helps us ensure that location is not empty or whitespace */ if (!is_absolute_path(location)) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("tablespace location must be an absolute path"))); /* * Check that location isn't too long. Remember that we're going to append * '/<dboid>/<relid>.<nnn>' (XXX but do we ever form the whole path * explicitly? This may be overly conservative.) */ if (strlen(location) >= (MAXPGPATH - 1 - 10 - 1 - 10 - 1 - 10)) ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("tablespace location \"%s\" is too long", location))); /* * Disallow creation of tablespaces named "pg_xxx"; we reserve this * namespace for system purposes. */ if (!allowSystemTableMods && IsReservedName(stmt->tablespacename)) ereport(ERROR, (errcode(ERRCODE_RESERVED_NAME), errmsg("unacceptable tablespace name \"%s\"", stmt->tablespacename), errdetail("The prefix \"pg_\" is reserved for system tablespaces."))); /* * Check that there is no other tablespace by this name. (The unique * index would catch this anyway, but might as well give a friendlier * message.) */ if (OidIsValid(get_tablespace_oid(stmt->tablespacename))) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("tablespace \"%s\" already exists", stmt->tablespacename))); /* * Insert tuple into pg_tablespace. The purpose of doing this first is to * lock the proposed tablename against other would-be creators. The * insertion will roll back if we find problems below. */ rel = heap_open(TableSpaceRelationId, RowExclusiveLock); MemSet(nulls, ' ', Natts_pg_tablespace); values[Anum_pg_tablespace_spcname - 1] = DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename)); values[Anum_pg_tablespace_spcowner - 1] = ObjectIdGetDatum(ownerId); values[Anum_pg_tablespace_spclocation - 1] = DirectFunctionCall1(textin, CStringGetDatum(location)); nulls[Anum_pg_tablespace_spcacl - 1] = 'n'; tuple = heap_formtuple(rel->rd_att, values, nulls); tablespaceoid = simple_heap_insert(rel, tuple); CatalogUpdateIndexes(rel, tuple); heap_freetuple(tuple); /* Record dependency on owner */ recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId); /* * Attempt to coerce target directory to safe permissions. If this fails, * it doesn't exist or has the wrong owner. */ if (chmod(location, 0700) != 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not set permissions on directory \"%s\": %m", location))); /* * Check the target directory is empty. */ if (!directory_is_empty(location)) ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("directory \"%s\" is not empty", location))); /* * Create the PG_VERSION file in the target directory. This has several * purposes: to make sure we can write in the directory, to prevent * someone from creating another tablespace pointing at the same directory * (the emptiness check above will fail), and to label tablespace * directories by PG version. */ set_short_version(location); /* * All seems well, create the symlink */ linkloc = (char *) palloc(10 + 10 + 1); sprintf(linkloc, "pg_tblspc/%u", tablespaceoid); if (symlink(location, linkloc) < 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not create symbolic link \"%s\": %m", linkloc))); /* Record the filesystem change in XLOG */ { xl_tblspc_create_rec xlrec; XLogRecData rdata[2]; xlrec.ts_id = tablespaceoid; rdata[0].data = (char *) &xlrec; rdata[0].len = offsetof(xl_tblspc_create_rec, ts_path); rdata[0].buffer = InvalidBuffer; rdata[0].next = &(rdata[1]); rdata[1].data = (char *) location; rdata[1].len = strlen(location) + 1; rdata[1].buffer = InvalidBuffer; rdata[1].next = NULL; (void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_CREATE, rdata); } pfree(linkloc); pfree(location); /* We keep the lock on pg_tablespace until commit */ heap_close(rel, NoLock); #else /* !HAVE_SYMLINK */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("tablespaces are not supported on this platform"))); #endif /* HAVE_SYMLINK */ }
static char *prefix_copy(const char *prefix, const char *filename) { if (!prefix || is_absolute_path(filename)) return xstrdup(filename); return xstrdup(prefix_filename(prefix, strlen(prefix), filename)); }
int cmd_config(int argc, const char **argv, const char *prefix) { int nongit; char* value; const char *file = setup_git_directory_gently(&nongit); while (1 < argc) { if (!strcmp(argv[1], "--int")) type = T_INT; else if (!strcmp(argv[1], "--bool")) type = T_BOOL; else if (!strcmp(argv[1], "--bool-or-int")) type = T_BOOL_OR_INT; else if (!strcmp(argv[1], "--list") || !strcmp(argv[1], "-l")) { if (argc != 2) usage(git_config_set_usage); if (git_config(show_all_config) < 0 && file && errno) die("unable to read config file %s: %s", file, strerror(errno)); return 0; } else if (!strcmp(argv[1], "--global")) { char *home = getenv("HOME"); if (home) { char *user_config = xstrdup(mkpath("%s/.gitconfig", home)); setenv(CONFIG_ENVIRONMENT, user_config, 1); free(user_config); } else { die("$HOME not set"); } } else if (!strcmp(argv[1], "--system")) setenv(CONFIG_ENVIRONMENT, git_etc_gitconfig(), 1); else if (!strcmp(argv[1], "--file") || !strcmp(argv[1], "-f")) { if (argc < 3) usage(git_config_set_usage); if (!is_absolute_path(argv[2]) && file) file = prefix_filename(file, strlen(file), argv[2]); else file = argv[2]; setenv(CONFIG_ENVIRONMENT, file, 1); argc--; argv++; } else if (!strcmp(argv[1], "--null") || !strcmp(argv[1], "-z")) { term = '\0'; delim = '\n'; key_delim = '\n'; } else if (!strcmp(argv[1], "--rename-section")) { int ret; if (argc != 4) usage(git_config_set_usage); ret = git_config_rename_section(argv[2], argv[3]); if (ret < 0) return ret; if (ret == 0) { fprintf(stderr, "No such section!\n"); return 1; } return 0; } else if (!strcmp(argv[1], "--remove-section")) { int ret; if (argc != 3) usage(git_config_set_usage); ret = git_config_rename_section(argv[2], NULL); if (ret < 0) return ret; if (ret == 0) { fprintf(stderr, "No such section!\n"); return 1; } return 0; } else if (!strcmp(argv[1], "--get-color")) { return get_color(argc-2, argv+2); } else if (!strcmp(argv[1], "--get-colorbool")) { return get_colorbool(argc-2, argv+2); } else break; argc--; argv++; } switch (argc) { case 2: return get_value(argv[1], NULL); case 3: if (!strcmp(argv[1], "--unset")) return git_config_set(argv[2], NULL); else if (!strcmp(argv[1], "--unset-all")) return git_config_set_multivar(argv[2], NULL, NULL, 1); else if (!strcmp(argv[1], "--get")) return get_value(argv[2], NULL); else if (!strcmp(argv[1], "--get-all")) { do_all = 1; return get_value(argv[2], NULL); } else if (!strcmp(argv[1], "--get-regexp")) { show_keys = 1; use_key_regexp = 1; do_all = 1; return get_value(argv[2], NULL); } else { value = normalize_value(argv[1], argv[2]); return git_config_set(argv[1], value); } case 4: if (!strcmp(argv[1], "--unset")) return git_config_set_multivar(argv[2], NULL, argv[3], 0); else if (!strcmp(argv[1], "--unset-all")) return git_config_set_multivar(argv[2], NULL, argv[3], 1); else if (!strcmp(argv[1], "--get")) return get_value(argv[2], argv[3]); else if (!strcmp(argv[1], "--get-all")) { do_all = 1; return get_value(argv[2], argv[3]); } else if (!strcmp(argv[1], "--get-regexp")) { show_keys = 1; use_key_regexp = 1; do_all = 1; return get_value(argv[2], argv[3]); } else if (!strcmp(argv[1], "--add")) { value = normalize_value(argv[2], argv[3]); return git_config_set_multivar(argv[2], value, "^$", 0); } else if (!strcmp(argv[1], "--replace-all")) { value = normalize_value(argv[2], argv[3]); return git_config_set_multivar(argv[2], value, NULL, 1); } else { value = normalize_value(argv[1], argv[2]); return git_config_set_multivar(argv[1], value, argv[3], 0); } case 5: if (!strcmp(argv[1], "--replace-all")) { value = normalize_value(argv[2], argv[3]); return git_config_set_multivar(argv[2], value, argv[4], 1); } case 1: default: usage(git_config_set_usage); } return 0; }
G_GNUC_COLD void upload_stats_load_history(void) { FILE *upload_stats_file; file_path_t fp; char line[FILENAME_MAX + 64]; guint lineno = 0; gcu_upload_stats_gui_freeze(); file_path_set(&fp, settings_config_dir(), ul_stats_file); /* open file for reading */ upload_stats_file = file_config_open_read(ul_stats_what, &fp, 1); if (upload_stats_file == NULL) goto done; /* parse, insert names into ul_stats_clist */ while (fgets(line, sizeof(line), upload_stats_file)) { static const struct ul_stats zero_item; struct ul_stats item; struct sha1 sha1_buf; const char *p; size_t i; lineno++; if (line[0] == '#' || line[0] == '\n') continue; p = strchr(line, '\t'); if (NULL == p) goto corrupted; line[p - line] = '\0'; /* line is now the URL-escaped file name */ p++; /* URL-unescape in-place */ if (!url_unescape(line, TRUE)) goto corrupted; item = zero_item; item.pathname = line; for (i = 0; i < 8; i++) { guint64 v; int error; const char *endptr; p = skip_ascii_spaces(p); /* SVN versions up to 15322 had only 6 fields in the history */ if (5 == i && '\0' == *p) break; switch (i) { case 7: /* We have a SHA1 or '*' if none known */ if ('*' != *p) { size_t len = clamp_strlen(p, SHA1_BASE32_SIZE); error = !parse_base32_sha1(p, len, &sha1_buf); item.sha1 = error ? NULL : &sha1_buf; } else { error = FALSE; } p = skip_ascii_non_spaces(p); v = 0; break; default: v = parse_uint64(p, &endptr, 10, &error); p = deconstify_gchar(endptr); } if (error || !is_ascii_space(*endptr)) goto corrupted; switch (i) { case 0: item.size = v; break; case 1: item.attempts = v; break; case 2: item.complete = v; break; case 3: item.bytes_sent |= ((guint64) (guint32) v) << 32; break; case 4: item.bytes_sent |= (guint32) v; break; case 5: item.rtime = MIN(v + (time_t) 0, TIME_T_MAX + (guint64) 0); case 6: item.dtime = MIN(v + (time_t) 0, TIME_T_MAX + (guint64) 0); case 7: break; /* Already stored above */ default: g_assert_not_reached(); goto corrupted; } } /* * We store the filenames UTF-8 encoded but the file might have been * edited or corrupted. */ if (is_absolute_path(item.pathname)) { item.filename = lazy_filename_to_utf8_normalized( filepath_basename(item.pathname), UNI_NORM_NFC); } else { item.filename = lazy_unknown_to_utf8_normalized( filepath_basename(item.pathname), UNI_NORM_NFC, NULL); } if (upload_stats_find(NULL, item.pathname, item.size)) { g_warning("upload_stats_load_history():" " Ignoring line %u due to duplicate file.", lineno); } else if (upload_stats_find(item.sha1, item.pathname, item.size)) { g_warning("upload_stats_load_history():" " Ignoring line %u due to duplicate file.", lineno); } else { upload_stats_add(item.pathname, item.size, item.filename, item.attempts, item.complete, item.bytes_sent, item.rtime, item.dtime, item.sha1); } continue; corrupted: g_warning("upload statistics file corrupted at line %u.", lineno); } /* close file */ fclose(upload_stats_file); done: gcu_upload_stats_gui_thaw(); return; }
/* * The `url` argument is the URL that navigates to the submodule origin * repo. When relative, this URL is relative to the superproject origin * URL repo. The `up_path` argument, if specified, is the relative * path that navigates from the submodule working tree to the superproject * working tree. Returns the origin URL of the submodule. * * Return either an absolute URL or filesystem path (if the superproject * origin URL is an absolute URL or filesystem path, respectively) or a * relative file system path (if the superproject origin URL is a relative * file system path). * * When the output is a relative file system path, the path is either * relative to the submodule working tree, if up_path is specified, or to * the superproject working tree otherwise. * * NEEDSWORK: This works incorrectly on the domain and protocol part. * remote_url url outcome expectation * http://a.com/b ../c http://a.com/c as is * http://a.com/b/ ../c http://a.com/c same as previous line, but * ignore trailing slash in url * http://a.com/b ../../c http://c error out * http://a.com/b ../../../c http:/c error out * http://a.com/b ../../../../c http:c error out * http://a.com/b ../../../../../c .:c error out * NEEDSWORK: Given how chop_last_dir() works, this function is broken * when a local part has a colon in its path component, too. */ static char *relative_url(const char *remote_url, const char *url, const char *up_path) { int is_relative = 0; int colonsep = 0; char *out; char *remoteurl = xstrdup(remote_url); struct strbuf sb = STRBUF_INIT; size_t len = strlen(remoteurl); if (is_dir_sep(remoteurl[len-1])) remoteurl[len-1] = '\0'; if (!url_is_local_not_ssh(remoteurl) || is_absolute_path(remoteurl)) is_relative = 0; else { is_relative = 1; /* * Prepend a './' to ensure all relative * remoteurls start with './' or '../' */ if (!starts_with_dot_slash(remoteurl) && !starts_with_dot_dot_slash(remoteurl)) { strbuf_reset(&sb); strbuf_addf(&sb, "./%s", remoteurl); free(remoteurl); remoteurl = strbuf_detach(&sb, NULL); } } /* * When the url starts with '../', remove that and the * last directory in remoteurl. */ while (url) { if (starts_with_dot_dot_slash(url)) { url += 3; colonsep |= chop_last_dir(&remoteurl, is_relative); } else if (starts_with_dot_slash(url)) url += 2; else break; } strbuf_reset(&sb); strbuf_addf(&sb, "%s%s%s", remoteurl, colonsep ? ":" : "/", url); if (ends_with(url, "/")) strbuf_setlen(&sb, sb.len - 1); free(remoteurl); if (starts_with_dot_slash(sb.buf)) out = xstrdup(sb.buf + 2); else out = xstrdup(sb.buf); strbuf_reset(&sb); if (!up_path || !is_relative) return out; strbuf_addf(&sb, "%s%s", up_path, out); free(out); return strbuf_detach(&sb, NULL); }
static int module_clone(int argc, const char **argv, const char *prefix) { const char *name = NULL, *url = NULL, *depth = NULL; int quiet = 0; int progress = 0; char *p, *path = NULL, *sm_gitdir; struct strbuf sb = STRBUF_INIT; struct string_list reference = STRING_LIST_INIT_NODUP; char *sm_alternate = NULL, *error_strategy = NULL; struct option module_clone_options[] = { OPT_STRING(0, "prefix", &prefix, N_("path"), N_("alternative anchor for relative paths")), OPT_STRING(0, "path", &path, N_("path"), N_("where the new submodule will be cloned to")), OPT_STRING(0, "name", &name, N_("string"), N_("name of the new submodule")), OPT_STRING(0, "url", &url, N_("string"), N_("url where to clone the submodule from")), OPT_STRING_LIST(0, "reference", &reference, N_("repo"), N_("reference repository")), OPT_STRING(0, "depth", &depth, N_("string"), N_("depth for shallow clones")), OPT__QUIET(&quiet, "Suppress output for cloning a submodule"), OPT_BOOL(0, "progress", &progress, N_("force cloning progress")), OPT_END() }; const char *const git_submodule_helper_usage[] = { N_("git submodule--helper clone [--prefix=<path>] [--quiet] " "[--reference <repository>] [--name <name>] [--depth <depth>] " "--url <url> --path <path>"), NULL }; argc = parse_options(argc, argv, prefix, module_clone_options, git_submodule_helper_usage, 0); if (argc || !url || !path || !*path) usage_with_options(git_submodule_helper_usage, module_clone_options); strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), name); sm_gitdir = absolute_pathdup(sb.buf); strbuf_reset(&sb); if (!is_absolute_path(path)) { strbuf_addf(&sb, "%s/%s", get_git_work_tree(), path); path = strbuf_detach(&sb, NULL); } else path = xstrdup(path); if (!file_exists(sm_gitdir)) { if (safe_create_leading_directories_const(sm_gitdir) < 0) die(_("could not create directory '%s'"), sm_gitdir); prepare_possible_alternates(name, &reference); if (clone_submodule(path, sm_gitdir, url, depth, &reference, quiet, progress)) die(_("clone of '%s' into submodule path '%s' failed"), url, path); } else { if (safe_create_leading_directories_const(path) < 0) die(_("could not create directory '%s'"), path); strbuf_addf(&sb, "%s/index", sm_gitdir); unlink_or_warn(sb.buf); strbuf_reset(&sb); } /* Connect module worktree and git dir */ connect_work_tree_and_git_dir(path, sm_gitdir); p = git_pathdup_submodule(path, "config"); if (!p) die(_("could not get submodule directory for '%s'"), path); /* setup alternateLocation and alternateErrorStrategy in the cloned submodule if needed */ git_config_get_string("submodule.alternateLocation", &sm_alternate); if (sm_alternate) git_config_set_in_file(p, "submodule.alternateLocation", sm_alternate); git_config_get_string("submodule.alternateErrorStrategy", &error_strategy); if (error_strategy) git_config_set_in_file(p, "submodule.alternateErrorStrategy", error_strategy); free(sm_alternate); free(error_strategy); strbuf_release(&sb); free(sm_gitdir); free(path); free(p); return 0; }
static void load_one_catalogue(catalog_file * file) { FILE *src = fopen(file->file, "r"); char buffer[2 * FILENAME_MAX]; char base[2 * FILENAME_MAX]; char *p; int t; catalogue_item_ptr this_item; int override = 0; if ( src == 0 ) { gripe(ERC_NO_CATALOGUE, file->file); return; } (void) strcpy(base, file->file); p = base + strlen(base); while (p != base && !isDirSep(p[-1])) p--; for (;;) { t = scan(src, buffer, sizeof buffer, 1); switch (t) { case CAT_BASE: if (scan(src, buffer, sizeof buffer, 0) == EOF) break; (void) strcpy(base, buffer); p = base + strlen(base); if (p != base && !isDirSep(p[-1])) *p++ = '/'; continue; case CAT_OVERRIDE: if (scan(src, buffer, sizeof buffer, 0) == EOF) break; override = tolower(buffer[0]) == 'y' ? CAT_OVERRIDE : 0; continue; case CAT_PUBLIC: case CAT_SYSTEM: case CAT_ENTITY: case CAT_DOCTYPE: this_item = sgml_malloc(sizeof *this_item); if (scan(src, buffer, sizeof buffer, 0) == EOF) break; if (t == CAT_PUBLIC) squish(buffer); this_item->next = 0; this_item->kind = t == CAT_SYSTEM ? t : t + override; this_item->target = istrdup(buffer); if (scan(src, buffer, sizeof buffer, 0) == EOF) break; if (is_absolute_path(buffer) || p == base) { this_item->replacement = istrdup(buffer); } else { (void) strcpy(p, buffer); this_item->replacement = istrdup(base); } if (file->first_item == 0) { file->first_item = this_item; } else { file->last_item->next = this_item; } file->last_item = this_item; continue; case EOF: break; default: continue; } break; }
/* * Actually do a base backup for the specified tablespaces. * * This is split out mainly to avoid complaints about "variable might be * clobbered by longjmp" from stupider versions of gcc. */ static void perform_base_backup(basebackup_options *opt, DIR *tblspcdir) { XLogRecPtr startptr; TimeLineID starttli; XLogRecPtr endptr; TimeLineID endtli; char *labelfile; int datadirpathlen; datadirpathlen = strlen(DataDir); backup_started_in_recovery = RecoveryInProgress(); startptr = do_pg_start_backup(opt->label, opt->fastcheckpoint, &starttli, &labelfile); SendXlogRecPtrResult(startptr, starttli); /* * Calculate the relative path of temporary statistics directory * in order to skip the files which are located in that directory later. */ if (is_absolute_path(pgstat_stat_directory) && strncmp(pgstat_stat_directory, DataDir, datadirpathlen) == 0) statrelpath = psprintf("./%s", pgstat_stat_directory + datadirpathlen + 1); else if (strncmp(pgstat_stat_directory, "./", 2) != 0) statrelpath = psprintf("./%s", pgstat_stat_directory); else statrelpath = pgstat_stat_directory; PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0); { List *tablespaces = NIL; ListCell *lc; struct dirent *de; tablespaceinfo *ti; /* Collect information about all tablespaces */ while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL) { char fullpath[MAXPGPATH]; char linkpath[MAXPGPATH]; char *relpath = NULL; int rllen; /* Skip special stuff */ if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue; snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name); #if defined(HAVE_READLINK) || defined(WIN32) rllen = readlink(fullpath, linkpath, sizeof(linkpath)); if (rllen < 0) { ereport(WARNING, (errmsg("could not read symbolic link \"%s\": %m", fullpath))); continue; } else if (rllen >= sizeof(linkpath)) { ereport(WARNING, (errmsg("symbolic link \"%s\" target is too long", fullpath))); continue; } linkpath[rllen] = '\0'; /* * Relpath holds the relative path of the tablespace directory * when it's located within PGDATA, or NULL if it's located * elsewhere. */ if (rllen > datadirpathlen && strncmp(linkpath, DataDir, datadirpathlen) == 0 && IS_DIR_SEP(linkpath[datadirpathlen])) relpath = linkpath + datadirpathlen + 1; ti = palloc(sizeof(tablespaceinfo)); ti->oid = pstrdup(de->d_name); ti->path = pstrdup(linkpath); ti->rpath = relpath ? pstrdup(relpath) : NULL; ti->size = opt->progress ? sendTablespace(fullpath, true) : -1; tablespaces = lappend(tablespaces, ti); #else /* * If the platform does not have symbolic links, it should not be * possible to have tablespaces - clearly somebody else created * them. Warn about it and ignore. */ ereport(WARNING, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("tablespaces are not supported on this platform"))); #endif } /* Add a node for the base directory at the end */ ti = palloc0(sizeof(tablespaceinfo)); ti->size = opt->progress ? sendDir(".", 1, true, tablespaces) : -1; tablespaces = lappend(tablespaces, ti); /* Send tablespace header */ SendBackupHeader(tablespaces); /* Send off our tablespaces one by one */ foreach(lc, tablespaces) { tablespaceinfo *ti = (tablespaceinfo *) lfirst(lc); StringInfoData buf; /* Send CopyOutResponse message */ pq_beginmessage(&buf, 'H'); pq_sendbyte(&buf, 0); /* overall format */ pq_sendint(&buf, 0, 2); /* natts */ pq_endmessage(&buf); if (ti->path == NULL) { struct stat statbuf; /* In the main tar, include the backup_label first... */ sendFileWithContent(BACKUP_LABEL_FILE, labelfile); /* ... then the bulk of the files ... */ sendDir(".", 1, false, tablespaces); /* ... and pg_control after everything else. */ if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not stat control file \"%s\": %m", XLOG_CONTROL_FILE))); sendFile(XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf, false); } else sendTablespace(ti->path, false); /* * If we're including WAL, and this is the main data directory we * don't terminate the tar stream here. Instead, we will append * the xlog files below and terminate it then. This is safe since * the main data directory is always sent *last*. */ if (opt->includewal && ti->path == NULL) { Assert(lnext(lc) == NULL); } else pq_putemptymessage('c'); /* CopyDone */ } }
/* * Checks if the cache is enabled for the given path. */ int fscache_enabled(const char *path) { return enabled > 0 && !is_absolute_path(path); }
/* * Entry point of pg_arman command. */ int main(int argc, char *argv[]) { const char *cmd = NULL; const char *range1 = NULL; const char *range2 = NULL; pgBackupRange range; int i; /* do not buffer progress messages */ setvbuf(stdout, 0, _IONBF, 0); /* TODO: remove this */ /* initialize configuration */ catalog_init_config(¤t); /* overwrite configuration with command line arguments */ i = pgut_getopt(argc, argv, options); for (; i < argc; i++) { if (cmd == NULL) cmd = argv[i]; else if (range1 == NULL) range1 = argv[i]; else if (range2 == NULL) range2 = argv[i]; else elog(ERROR, "too many arguments"); } /* command argument (backup/restore/show/...) is required. */ if (cmd == NULL) { help(false); return 1; } /* get object range argument if any */ if (range1 && range2) parse_range(&range, range1, range2); else if (range1) parse_range(&range, range1, ""); else range.begin = range.end = 0; /* Read default configuration from file. */ if (backup_path) { char path[MAXPGPATH]; /* Check if backup_path is directory. */ struct stat stat_buf; int rc = stat(backup_path, &stat_buf); /* If rc == -1, there is no file or directory. So it's OK. */ if (rc != -1 && !S_ISDIR(stat_buf.st_mode)) elog(ERROR, "-B, --backup-path must be a path to directory"); join_path_components(path, backup_path, PG_RMAN_INI_FILE); pgut_readopt(path, options, ERROR); } /* BACKUP_PATH is always required */ if (backup_path == NULL) elog(ERROR, "required parameter not specified: BACKUP_PATH (-B, --backup-path)"); /* path must be absolute */ if (backup_path != NULL && !is_absolute_path(backup_path)) elog(ERROR, "-B, --backup-path must be an absolute path"); if (pgdata != NULL && !is_absolute_path(pgdata)) elog(ERROR, "-D, --pgdata must be an absolute path"); if (arclog_path != NULL && !is_absolute_path(arclog_path)) elog(ERROR, "-A, --arclog-path must be an absolute path"); /* Sanity checks with commands */ if (pg_strcasecmp(cmd, "delete") == 0 && arclog_path == NULL) elog(ERROR, "delete command needs ARCLOG_PATH (-A, --arclog-path) to be set"); /* setup exclusion list for file search */ for (i = 0; pgdata_exclude[i]; i++) /* find first empty slot */ ; if (arclog_path) pgdata_exclude[i++] = arclog_path; /* do actual operation */ if (pg_strcasecmp(cmd, "init") == 0) return do_init(); else if (pg_strcasecmp(cmd, "backup") == 0) { pgBackupOption bkupopt; int res; bkupopt.smooth_checkpoint = smooth_checkpoint; bkupopt.keep_data_generations = keep_data_generations; bkupopt.keep_data_days = keep_data_days; /* Do the backup */ res = do_backup(bkupopt); if (res != 0) return res; /* If validation has been requested, do it */ range.begin = current.start_time; range.end = current.start_time + 1; if (backup_validate) do_validate(&range); } else if (pg_strcasecmp(cmd, "restore") == 0) return do_restore(target_time, target_xid, target_inclusive, target_tli); else if (pg_strcasecmp(cmd, "show") == 0) return do_show(&range, show_all); else if (pg_strcasecmp(cmd, "validate") == 0) return do_validate(&range); else if (pg_strcasecmp(cmd, "delete") == 0) return do_delete(&range); else elog(ERROR, "invalid command \"%s\"", cmd); return 0; }
char * get_prompt(promptStatus_t status) { #define MAX_PROMPT_SIZE 256 static char destination[MAX_PROMPT_SIZE + 1]; char buf[MAX_PROMPT_SIZE + 1]; bool esc = false; const char *p; const char *prompt_string = "? "; const char *prompt_name = NULL; switch (status) { case PROMPT_READY: prompt_name = "PROMPT1"; break; case PROMPT_CONTINUE: case PROMPT_SINGLEQUOTE: case PROMPT_DOUBLEQUOTE: case PROMPT_DOLLARQUOTE: case PROMPT_COMMENT: case PROMPT_PAREN: prompt_name = "PROMPT2"; break; case PROMPT_COPY: prompt_name = "PROMPT3"; break; } if (prompt_name) prompt_string = GetVariable(pset.vars, prompt_name); destination[0] = '\0'; for (p = prompt_string; p && *p && strlen(destination) < MAX_PROMPT_SIZE; p++) { memset(buf, 0, MAX_PROMPT_SIZE + 1); if (esc) { switch (*p) { /* Current database */ case '/': if (pset.db) strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE); break; case '~': if (pset.db) { const char *var; if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 || ((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0)) strcpy(buf, "~"); else strncpy(buf, PQdb(pset.db), MAX_PROMPT_SIZE); } break; /* DB server hostname (long/short) */ case 'M': case 'm': if (pset.db) { const char *host = PQhost(pset.db); /* INET socket */ if (host && host[0] && !is_absolute_path(host)) { strncpy(buf, host, MAX_PROMPT_SIZE); if (*p == 'm') buf[strcspn(buf, ".")] = '\0'; } #ifdef HAVE_UNIX_SOCKETS /* UNIX socket */ else { if (!host || strcmp(host, DEFAULT_PGSOCKET_DIR) == 0 || *p == 'm') strncpy(buf, "[local]", MAX_PROMPT_SIZE); else snprintf(buf, MAX_PROMPT_SIZE, "[local:%s]", host); } #endif } break; /* DB server port number */ case '>': if (pset.db && PQport(pset.db)) strncpy(buf, PQport(pset.db), MAX_PROMPT_SIZE); break; /* DB server user name */ case 'n': if (pset.db) strncpy(buf, session_username(), MAX_PROMPT_SIZE); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': *buf = (char) strtol(p, (char **) &p, 8); --p; break; case 'R': switch (status) { case PROMPT_READY: if (!pset.db) buf[0] = '!'; else if (!GetVariableBool(pset.vars, "SINGLELINE")) buf[0] = '='; else buf[0] = '^'; break; case PROMPT_CONTINUE: buf[0] = '-'; break; case PROMPT_SINGLEQUOTE: buf[0] = '\''; break; case PROMPT_DOUBLEQUOTE: buf[0] = '"'; break; case PROMPT_DOLLARQUOTE: buf[0] = '$'; break; case PROMPT_COMMENT: buf[0] = '*'; break; case PROMPT_PAREN: buf[0] = '('; break; default: buf[0] = '\0'; break; } break; case 'x': if (!pset.db) buf[0] = '?'; else switch (PQtransactionStatus(pset.db)) { case PQTRANS_IDLE: buf[0] = '\0'; break; case PQTRANS_ACTIVE: case PQTRANS_INTRANS: buf[0] = '*'; break; case PQTRANS_INERROR: buf[0] = '!'; break; default: buf[0] = '?'; break; } break; case '?': /* not here yet */ break; case '#': if (is_superuser()) buf[0] = '#'; else buf[0] = '>'; break; /* execute command */ case '`': { FILE *fd = NULL; char *file = pg_strdup(p + 1); int cmdend; cmdend = strcspn(file, "`"); file[cmdend] = '\0'; if (file) fd = popen(file, "r"); if (fd) { fgets(buf, MAX_PROMPT_SIZE - 1, fd); pclose(fd); } if (strlen(buf) > 0 && buf[strlen(buf) - 1] == '\n') buf[strlen(buf) - 1] = '\0'; free(file); p += cmdend + 1; break; } /* interpolate variable */ case ':': { char *name; const char *val; int nameend; name = pg_strdup(p + 1); nameend = strcspn(name, ":"); name[nameend] = '\0'; val = GetVariable(pset.vars, name); if (val) strncpy(buf, val, MAX_PROMPT_SIZE); free(name); p += nameend + 1; break; } case '[': case ']': #if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE) /* * readline >=4.0 undocumented feature: non-printing * characters in prompt strings must be marked as such, in * order to properly display the line during editing. */ buf[0] = (*p == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE; buf[1] = '\0'; #endif /* USE_READLINE */ break; default: buf[0] = *p; buf[1] = '\0'; break; } esc = false; } else if (*p == '%') esc = true; else { buf[0] = *p; buf[1] = '\0'; esc = false; } if (!esc) strncat(destination, buf, MAX_PROMPT_SIZE - strlen(destination)); } destination[MAX_PROMPT_SIZE] = '\0'; return destination; }