user/dev discussion of public-inbox itself
 help / color / mirror / code / Atom feed
From: Eric Wong <e@80x24.org>
To: meta@public-inbox.org
Subject: [PATCH 4/9] lei: set PWD correctly for path expansion
Date: Wed, 27 Jan 2021 03:42:25 -0600	[thread overview]
Message-ID: <20210127094230.31174-5-e@80x24.org> (raw)
In-Reply-To: <20210127094230.31174-1-e@80x24.org>

While commit d1b9582872d1824f166a038dcf32b6ae8c6dc735
("lei: pass FD to CWD via cmsg, use fchdir on server")
ensured things work properly to get the daemon in the
right directory, it forgot to deal with places where
we expand relative paths based on the current working
directory.
---
 lib/PublicInbox/LEI.pm | 56 ++++++++++++++++++++++++++++--------------
 1 file changed, 37 insertions(+), 19 deletions(-)

diff --git a/lib/PublicInbox/LEI.pm b/lib/PublicInbox/LEI.pm
index c017fd4e..0ce6a00b 100644
--- a/lib/PublicInbox/LEI.pm
+++ b/lib/PublicInbox/LEI.pm
@@ -13,6 +13,7 @@ use parent qw(PublicInbox::DS PublicInbox::LeiExternal
 use Getopt::Long ();
 use Socket qw(AF_UNIX SOCK_SEQPACKET MSG_EOR pack_sockaddr_un);
 use Errno qw(EAGAIN EINTR ECONNREFUSED ENOENT ECONNRESET);
+use Cwd qw(getcwd);
 use POSIX ();
 use IO::Handle ();
 use Fcntl qw(SEEK_SET);
@@ -65,18 +66,37 @@ sub opt_dash ($$) {
 	($spec, '<>' => $cb, $GLP_PASS) # for Getopt::Long
 }
 
+sub rel2abs ($$) {
+	my ($self, $p) = @_;
+	return $p if index($p, '/') == 0; # already absolute
+	my $pwd = $self->{env}->{PWD};
+	if (defined $pwd) {
+		my $cwd = $self->{3} // getcwd() // die "getcwd(PWD=$pwd): $!";
+		if (my @st_pwd = stat($pwd)) {
+			my @st_cwd = stat($cwd) or die "stat($cwd): $!";
+			"@st_pwd[1,0]" eq "@st_cwd[1,0]" or
+				$self->{env}->{PWD} = $pwd = $cwd;
+		} else { # PWD was invalid
+			delete $self->{env}->{PWD};
+			undef $pwd;
+		}
+	}
+	$pwd //= $self->{env}->{PWD} = getcwd() // die "getcwd(PWD=$pwd): $!";
+	File::Spec->rel2abs($p, $pwd);
+}
+
 sub _store_path ($) {
-	my ($env) = @_;
-	File::Spec->rel2abs(($env->{XDG_DATA_HOME} //
-		($env->{HOME} // '/nonexistent').'/.local/share')
-		.'/lei/store', $env->{PWD});
+	my ($self) = @_;
+	rel2abs($self, ($self->{env}->{XDG_DATA_HOME} //
+		($self->{env}->{HOME} // '/nonexistent').'/.local/share')
+		.'/lei/store');
 }
 
 sub _config_path ($) {
-	my ($env) = @_;
-	File::Spec->rel2abs(($env->{XDG_CONFIG_HOME} //
-		($env->{HOME} // '/nonexistent').'/.config')
-		.'/lei/config', $env->{PWD});
+	my ($self) = @_;
+	rel2abs($self, ($self->{env}->{XDG_CONFIG_HOME} //
+		($self->{env}->{HOME} // '/nonexistent').'/.config')
+		.'/lei/config');
 }
 
 # TODO: generate shell completion + help using %CMD and %OPTDESC
@@ -295,7 +315,7 @@ sub atfork_prepare_wq {
 	my ($self, $wq) = @_;
 	my $tcafc = $wq->{-ipc_atfork_child_close} //= [ $listener // () ];
 	if (my $sock = $self->{sock}) {
-		push @$tcafc, @$self{qw(0 1 2)}, $sock;
+		push @$tcafc, @$self{qw(0 1 2 3)}, $sock;
 	}
 	if (my $pgr = $self->{pgr}) {
 		push @$tcafc, @$pgr[1,2];
@@ -345,7 +365,7 @@ sub atfork_parent_wq {
 		$ret->{dedupe} = $wq->deep_clone($dedupe);
 	}
 	$self->{env} = $env;
-	delete @$ret{qw(-lei_store cfg old_1 pgr lxs)}; # keep l2m
+	delete @$ret{qw(3 -lei_store cfg old_1 pgr lxs)}; # keep l2m
 	my @io = delete @$ret{0..2};
 	$io[3] = delete($ret->{sock}) // $io[2];
 	my $l2m = $ret->{l2m};
@@ -362,7 +382,7 @@ sub _help ($;$) {
 	my @info = @{$CMD{$cmd} // [ '...', '...' ]};
 	my @top = ($cmd, shift(@info) // ());
 	my $cmd_desc = shift(@info);
-	$cmd_desc = $cmd_desc->($self->{env}) if ref($cmd_desc) eq 'CODE';
+	$cmd_desc = $cmd_desc->($self) if ref($cmd_desc) eq 'CODE';
 	my @opt_desc;
 	my $lpad = 2;
 	for my $sw (grep { !ref } @info) { # ("prio=s", "z", $GLP_PASS)
@@ -520,7 +540,7 @@ sub dispatch {
 
 sub _lei_cfg ($;$) {
 	my ($self, $creat) = @_;
-	my $f = _config_path($self->{env});
+	my $f = _config_path($self);
 	my @st = stat($f);
 	my $cur_st = @st ? pack('dd', $st[10], $st[7]) : ''; # 10:ctime, 7:size
 	if (my $cfg = $PATH2CFG{$f}) { # reuse existing object in common case
@@ -550,8 +570,7 @@ sub _lei_store ($;$) {
 	$cfg->{-lei_store} //= do {
 		require PublicInbox::LeiStore;
 		my $dir = $cfg->{'leistore.dir'};
-		$dir //= _store_path($self->{env}) if $creat;
-		return unless $dir;
+		$dir //= $creat ? _store_path($self) : return;
 		PublicInbox::LeiStore->new($dir, { creat => $creat });
 	};
 }
@@ -587,9 +606,8 @@ sub lei_init {
 	my ($self, $dir) = @_;
 	my $cfg = _lei_cfg($self, 1);
 	my $cur = $cfg->{'leistore.dir'};
-	my $env = $self->{env};
-	$dir //= _store_path($env);
-	$dir = File::Spec->rel2abs($dir, $env->{PWD}); # PWD is symlink-aware
+	$dir //= _store_path($self);
+	$dir = rel2abs($self, $dir);
 	my @cur = stat($cur) if defined($cur);
 	$cur = File::Spec->canonpath($cur // $dir);
 	my @dir = stat($dir);
@@ -601,7 +619,7 @@ sub lei_init {
 		}
 
 		# some folks like symlinks and bind mounts :P
-		if (@dir && "$cur[0] $cur[1]" eq "$dir[0] $dir[1]") {
+		if (@dir && "@cur[1,0]" eq "@dir[1,0]") {
 			lei_config($self, 'leistore.dir', $dir);
 			_lei_store($self, 1)->done;
 			return qerr($self, "$exists (as $cur)");
@@ -771,7 +789,7 @@ sub accept_dispatch { # Listener {post_accept} callback
 	my ($argc, @argv) = split(/\0/, $buf, -1);
 	undef $buf;
 	my %env = map { split(/=/, $_, 2) } splice(@argv, $argc);
-	if (chdir(delete($self->{3}))) {
+	if (chdir($self->{3})) {
 		local %ENV = %env;
 		$self->{env} = \%env;
 		eval { dispatch($self, @argv) };

  parent reply	other threads:[~2021-01-27  9:42 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-27  9:42 [PATCH 0/9] lei completion, some small updates Eric Wong
2021-01-27  9:42 ` [PATCH 1/9] eml: favor index() over regexp match Eric Wong
2021-01-27  9:42 ` [PATCH 2/9] lei: drop "git" command forwarding Eric Wong
2021-01-27  9:42 ` [PATCH 3/9] lei: fix comment regarding client payload Eric Wong
2021-01-27  9:42 ` Eric Wong [this message]
2021-01-27  9:42 ` [PATCH 5/9] gcf2: rely on Perl 5.10 to avoid needless ++ Eric Wong
2021-01-27  9:42 ` [PATCH 6/9] lei: complete option switch args Eric Wong
2021-01-27  9:42 ` [PATCH 7/9] lei_overview: clear redundant ovv_buf definition Eric Wong
2021-01-27  9:42 ` [PATCH 8/9] v2writable: nproc: use sysconf() on Linux and FreeBSD Eric Wong
2021-01-27  9:42 ` [PATCH 9/9] lei: dclose: fix typo Eric Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://public-inbox.org/README

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210127094230.31174-5-e@80x24.org \
    --to=e@80x24.org \
    --cc=meta@public-inbox.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/public-inbox.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).