libelektra: mmapstorage doesn't work with kdb export

Steps to Reproduce the Problem

kdb set user/tests/hello world
#> Create a new key user/tests/hello with string "world"

kdb export user/tests/hello mmapstorage > test.mmap

Expected Result

A file called test.mmap is created, which can be re-imported with kdb import.

Actual Result

An empty file called test.mmap is created and the following message is printed (includes logs from ENABLE_LOGGER):

src/plugins/mmapstorage/mmapstorage.c:944:libelektra_mmapstorage_LTX_elektraPluginset: could not unlink
src/plugins/mmapstorage/mmapstorage.c:1003:libelektra_mmapstorage_LTX_elektraPluginset: strerror: Permission denied
Sorry, the error (#9) occurred ;(
Description: Insufficient permissions to open configuration file for writing. You might want to retry as root.
Reason: Permission denied
Ingroup: kdb
Module: 
At: /home/klemens/data/bsc/libelektra/src/plugins/mmapstorage/mmapstorage.c:1004
Mountpoint: user
Configfile: /dev/stdout

System Information

  • Elektra Version: master

Further Information

~Works when kdb export is called as root.~ (EDIT: see comment below) kdb export user/tests/hello mmapstorage test.mmap also works, but is a completely undocumented feature of kdb export. So a better error message and updated documentation might be all we need.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 2
  • Comments: 22 (22 by maintainers)

Most upvoted comments

Thank you for your reply!

The mmap error messages might be misleading.

Please improve the error messages.

To my knowledge it will not work on stdout. It also does not work with pipes

Please add that info to the error messages.

The solutions above do not change much of the mmapstorage logic.

As your plugin is currently the only affected one, it makes sense that you do the stat and copy everything if needed. Then we could close this issue without larger changes in the framework.

This is the commented out solution?

I left it in the history but removed the lines later. The imho better solution was up until https://github.com/ElektraInitiative/libelektra/pull/2639/commits/a523f9b38b56687d532f5101c7ef44c078e2308d. Note that it worked well on Linux but not BSD.

One problem I encountered is that stdin/stdout can not be open()ed on BSDs. The other is that you really have to use the realpath to stat() the file and determine whether it is a regular file. Otherwise stat only resolved one level of symlinks for me. This approach failed on BSDs for me, because realpath resolved to a nonexistent file somehow.

Also with the cat | kdb import variant?

Yes!

Where are the differences?

The relevant part is the same, sorry for the confusion. What I meant is that we strcmp for /dev/stdin instead of using stat to determine whether it is a regular file. That means that it will still fail if we use /dev/fd/<num>. My other solution used stat instead of strcmp so it worked with any path.

Edit:

Can this code be moved to the import/export framework?

Yes I think the code was almost completely there, but I had no time to fix the BSD problems properly.

I had a really nice solution (using realpath and stat) which unfortunately will not work on BSDs. It does not make sense to invest much more time into it.

I have decided to throw it away, thus not making mmapstorage completely compatible with non-regular files. It will only work with kdb import/export. The new solution will simply check if kdb import/export is used, by checking if the file is “/dev/stdin” or “/dev/stdout”. It’s done similarly in quickdump.

#2639 closes all problems here. It works fine on Linux, I just need to fix a bug so it works on the BSDs too.

Actually, it is maybe better if #2639 closes this issue and @mpranj you make a new one for the cat ... problem.

Works when kdb export is called as root.

I take that back… DON’T TRY THAT! Calling kdb export <something> mmapstorage as root user (even if stdout is redirected) destroys /dev/stdout. Using /dev/stdout (e.g. via fopen) won’t work on your system until you recreate the default symlink with sudo rm /dev/stdout && sudo ln -s /dev/stdout /proc/self/fd/1.