From patchwork Wed Aug 12 18:20:57 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Doug Evans X-Patchwork-Id: 8160 Received: (qmail 98117 invoked by alias); 12 Aug 2015 18:21:01 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 98107 invoked by uid 89); 12 Aug 2015 18:21:00 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL, BAYES_00, MIME_BASE64_BLANKS, RCVD_IN_DNSWL_LOW, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pd0-f201.google.com Received: from mail-pd0-f201.google.com (HELO mail-pd0-f201.google.com) (209.85.192.201) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Wed, 12 Aug 2015 18:20:59 +0000 Received: by pdbfa8 with SMTP id fa8so2032874pdb.1 for ; Wed, 12 Aug 2015 11:20:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:message-id:date:subject:from:to :content-type:content-transfer-encoding; bh=tLQ8bL9YHZqLh7he0QND//qP3KtO8DzIZZByxvJj6m0=; b=PhKbkw2S1ukJ42LM57HJfZ8q+VVFK+hM6ng1sMMGV9QXSLlo89BdzDyo2hDWjRhv0g ozAl2htFE/FtExoYGQT8hoDHO/d/jRhfzocCjx9Fvc5Sb/pADeFufhtvJdnUv+U54kXr vrQx46HcetrrkymfUj+rZefI+aK7iXH9xidtdAzs4sVTCChdJtVZZOIoh3N4xWOw6zCf Haz6LS23g655fQyadteH2gXUPa36j9zgkeHxwAjR3zLFlNaPSoQ/1YfmhMqSD2uUfFul wOl8tw93HG6jlHXRim0zQ8Ypxqpov5RcTXNpKQO3XhqZl/3YvvWrukTxNxBEqgu7Z1Gx gz8A== X-Gm-Message-State: ALoCoQmdjVr2SPyn2/x/fz00gY4iLTXezhd1gLw/M8t1mJ9ygUu91Y3nZ5ZSaoDncfA2LQOnViaGkensV5ztcVHGcwVS37LVSb5rShfE/FUXAAsv6vMVaHMn1+YR/elG90nk1rNjHQGUMPTvvbGWdC/1UoWJskQsxhcrWwS+Hy9AedMwsivaQ5A= MIME-Version: 1.0 X-Received: by 10.68.132.1 with SMTP id oq1mr31065513pbb.12.1439403657342; Wed, 12 Aug 2015 11:20:57 -0700 (PDT) Message-ID: <047d7b15fd01af6a62051d214793@google.com> Date: Wed, 12 Aug 2015 18:20:57 +0000 Subject: [PATCH 1/2] Try both make_relative_prefix{, ignore_links} for relocatability From: Doug Evans To: gdb-patches@sourceware.org X-IsSubscribed: yes Hi. I have a use-case where I need relocatability in a tree of symlinks. The fix is straightforward enough. The testcase may need some thought. It does a "make install" into the testsuite subdir, and then sets up the necessary conditions to properly test make_relative_prefix{,ignore_links}. The test runs fast enough, that's not the issue. Just dunno how people will feel about doing a "make install" in a testcase. OTOH, this is what we need to test: the behaviour of the installed gdb. The test is contingent on whether the user configured the tree in a relocatable way. The test won't fail, but I'm guessing re-running configure/make for this test is a bit too much, whereas what's here is a reasonable compromise. 1/2 is the patch 2/2 is the testcase 2015-08-12 Doug Evans * completer.c (gdb_path_isdir): Move to ... * utils.c (gdb_path_isdir): ... here. (gdb_path_isfile): New function. * utils.h (gdb_path_isdir): Declare. (gdb_path_isfile): Declare. * main.c (relocate_gdb_file): Renamed from relocate_path. Try both make_relative_prefix and make_relative_prefix_ignore_symlinks. All callers updated. (maybe_lrealpath): New function. (relocate_gdb_directory: Try both make_relative_prefix and make_relative_prefix_ignore_symlinks. diff --git a/gdb/completer.c b/gdb/completer.c index 7fc27b1..870e70f 100644 --- a/gdb/completer.c +++ b/gdb/completer.c @@ -1461,17 +1461,6 @@ gdb_display_match_list_pager (int lines, return 0; } -/* Return non-zero if FILENAME is a directory. - Based on readline/complete.c:path_isdir. */ - -static int -gdb_path_isdir (const char *filename) -{ - struct stat finfo; - - return (stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode)); -} - /* Return the portion of PATHNAME that should be output when listing possible completions. If we are hacking filename completion, we are only interested in the basename, the portion following the diff --git a/gdb/main.c b/gdb/main.c index aecd60a..34dd850 100644 --- a/gdb/main.c +++ b/gdb/main.c @@ -137,58 +137,97 @@ set_gdb_data_directory (const char *new_datadir) } } -/* Relocate a file or directory. PROGNAME is the name by which gdb - was invoked (i.e., argv[0]). INITIAL is the default value for the - file or directory. FLAG is true if the value is relocatable, false - otherwise. Returns a newly allocated string; this may return NULL - under the same conditions as make_relative_prefix. */ +/* Relocate a file. + INITIAL is the default value of the file. + FLAG is true if the value is relocatable, false otherwise. + Returns a newly allocated string; this may return NULL + under the same conditions as gdb_make_relative_prefix. */ static char * -relocate_path (const char *progname, const char *initial, int flag) +relocate_gdb_file (const char *initial, int flag) { - if (flag) - return make_relative_prefix (progname, BINDIR, initial); + char *path; + + /* Early exit if there's nothing we can do. */ + if (!flag) + return xstrdup (initial); + + /* We have to try both make_relative_prefix and + make_relative_prefix_ignore_links. The first handles a symlink to + gdb where it is installed. The second handles the case where the + installation tree is itself a collection of symlinks to random places. + Alas we can't distinguish a NULL return from make_relative_prefix* + due to lack of memory or due to failure to find a common prefix. + make_relative_prefix is tried first for backward compatibility. Ugh. */ + + path = make_relative_prefix (gdb_program_name, BINDIR, initial); + if (path != NULL && gdb_path_isfile (path)) + return path; + xfree (path); + path = make_relative_prefix_ignore_links (gdb_program_name, BINDIR, initial); + if (path != NULL && gdb_path_isfile (path)) + return path; + xfree (path); return xstrdup (initial); } -/* Like relocate_path, but specifically checks for a directory. - INITIAL is relocated according to the rules of relocate_path. If - the result is a directory, it is used; otherwise, INITIAL is used. - The chosen directory is then canonicalized using lrealpath. This - function always returns a newly-allocated string. */ +/* Return the lrealpath form of PATH. + Space for PATH must have been malloc'd. + PATH is freed if the lrealpath'd form is different. */ -char * -relocate_gdb_directory (const char *initial, int flag) +static char * +maybe_lrealpath (char *path) { - char *dir; + char *canon; - dir = relocate_path (gdb_program_name, initial, flag); - if (dir) - { - struct stat s; + if (*path == '\0') + return path; - if (*dir == '\0' || stat (dir, &s) != 0 || !S_ISDIR (s.st_mode)) - { - xfree (dir); - dir = NULL; - } + canon = lrealpath (path); + if (canon != NULL) + { + xfree (path); + path = canon; } - if (!dir) - dir = xstrdup (initial); - /* Canonicalize the directory. */ - if (*dir) - { - char *canon_sysroot = lrealpath (dir); + return path; +} - if (canon_sysroot) - { - xfree (dir); - dir = canon_sysroot; - } - } +/* Relocate a directory. + INITIAL is the default value of the directory. + FLAG is true if the value is relocatable, false otherwise. + If the result is a directory, it is used; otherwise, INITIAL is used. + The chosen directory is then canonicalized using lrealpath. This + function always returns a newly-allocated string. */ + +char * +relocate_gdb_directory (const char *initial, int flag) +{ + char *dir; - return dir; + /* Early exit if there's nothing we can do. */ + if (initial[0] == '\0') + return xstrdup (""); + if (!flag) + return maybe_lrealpath (xstrdup (initial)); + + /* We have to try both make_relative_prefix and + make_relative_prefix_ignore_links. The first handles a symlink to + gdb where it is installed. The second handles the case where the + installation tree is itself a collection of symlinks to random places. + Alas we can't distinguish a NULL return from make_relative_prefix* + due to lack of memory or due to failure to find a common prefix. Ugh. + make_relative_prefix is tried first for backward compatibility. */ + + dir = make_relative_prefix (gdb_program_name, BINDIR, initial); + if (dir != NULL && gdb_path_isdir (dir)) + return maybe_lrealpath (dir); + xfree (dir); + dir = make_relative_prefix_ignore_links (gdb_program_name, BINDIR, initial); + if (gdb_path_isdir (dir)) + return maybe_lrealpath (dir); + xfree (dir); + return maybe_lrealpath (xstrdup (initial)); } /* Compute the locations of init files that GDB should source and @@ -237,9 +276,9 @@ get_init_files (const char **system_gdbinit, } else { - relocated_sysgdbinit = relocate_path (gdb_program_name, - SYSTEM_GDBINIT, - SYSTEM_GDBINIT_RELOCATABLE); + relocated_sysgdbinit + = relocate_gdb_file (SYSTEM_GDBINIT, + SYSTEM_GDBINIT_RELOCATABLE); } if (relocated_sysgdbinit && stat (relocated_sysgdbinit, &s) == 0) sysgdbinit = relocated_sysgdbinit; diff --git a/gdb/utils.c b/gdb/utils.c index e5ad195..dfdd04d 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -3015,6 +3015,28 @@ ldirname (const char *filename) return dirname; } +/* See utils.h. + Based on readline/complete.c:path_isdir. */ + +int +gdb_path_isdir (const char *path) +{ + struct stat s; + + return stat (path, &s) == 0 && S_ISDIR (s.st_mode); +} + +/* See utils.h. + Based on readline/complete.c:path_isdir. */ + +int +gdb_path_isfile (const char *path) +{ + struct stat s; + + return stat (path, &s) == 0 && S_ISREG (s.st_mode); +} + /* Call libiberty's buildargv, and return the result. If buildargv fails due to out-of-memory, call nomem. Therefore, the returned value is guaranteed to be non-NULL, diff --git a/gdb/utils.h b/gdb/utils.h index 995a1cf..0adb097 100644 --- a/gdb/utils.h +++ b/gdb/utils.h @@ -135,6 +135,14 @@ extern void substitute_path_component (char **stringp, const char *from, const char *to); char *ldirname (const char *filename); + +/* Return non-zero if PATH is a directory. */ + +extern int gdb_path_isdir (const char *path); + +/* Return non-zero if PATH is a plain file. */ + +extern int gdb_path_isfile (const char *path); /* GDB output, ui_file utilities. */