mle icon indicating copy to clipboard operation
mle copied to clipboard

Buffers are written to the current working directory

Open hovsater opened this issue 4 years ago • 2 comments

Not sure if this is considered a bug or not but I think it's odd.

Given a directory structure like follows

~/example $ tree
.
└── subdir

1 directory, 0 files

If I write a file named test.txt in the root directory and then do C-b and enter the subdir directory, followed by switching to test.txt buffer by doing C-\ and hitting C-s again. The file is now saved into the subdir directory as a new file, not to the original location.

hovsater avatar Aug 14 '20 19:08 hovsater

Good call @KevinSjoberg. This behavior feels natural to me only because I know under the hood that browsing (C-b) into a directory is a plain chdir(2) call which changes the cwd of the entire process. However I agree the example you give feels wrong.

Some potential solutions...

  1. Every time buffer_t.path is set, realpath(3) it into buffer_t.path_absolute and use that for all file operations. Save-as would be a little more complicated because we'd have to build a new absolute path.

  2. Maintain a dirfd for each buffer and use openat(2) instead of fopen(3) when saving the file. Maybe more elegant than above but has the downside of costing an fd for each open buffer which potentially runs us into system rlimit if you have a lot of buffers open.

  3. Similar to above, maintain a cwd string for each buffer and chdir(2) before all file operations if buffer_t.cwd != getcwd(). Does not cost an fd but feels bad.

Any other ideas? Leaning toward option 1.

adsr avatar Aug 25 '20 02:08 adsr

Since you are saving files using (original) file names (as opposed to original file descriptor), option 1. seems to be the most sensible among your propositions.

But relying on the realpath() invoked only at the opening time would introduce potential mismatches, eg there could be a symbolic link somewhere on the path that changes after opening.

pkitszel avatar Jul 14 '21 08:07 pkitszel

In 3253070 I implemented a 4th option not described above:

Avoid chdir entirely and maintain a bview_t.browse_path variable used by cmd_browse. When entering a directory via cmd_browse, we append to browse_path. Right before executing tree we cd into browse_path. That happens in a forked shell so the cwd of the editor process is unchanged. When selecting a file via cmd_browse, we prepend browse_path.

The downside is that file paths can get kind of verbose if you're using cmd_browse to go up and down directories. For example if I repeatedly browse into a subdir a followed by going up a directory, then finally open a file, the path will look like a/../a/../a/../a/../a/../test.

Surely there's a way to collapse a relative path into its most succinct form, but I don't see anything in libc that does exactly that. (Please share if I'm missing something.) realpathing everything with some sort of display logic to only show the portion after cwd is another option, however it may be tricky to get right with symlinks. Leaving it alone for the time being.

adsr avatar Aug 27 '22 19:08 adsr

I would write a simple "shortener" for those paths, you would avoid getting over MAX_PATH for some cases then.

I also see nohing in standard C lib for that.

pkitszel avatar Aug 29 '22 09:08 pkitszel