Libelektra: mmapstorage不适用于kdb导出

创建于 2019-02-15  ·  22评论  ·  资料来源: ElektraInitiative/libelektra

重现问题的步骤

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

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

预期结果

创建了名为test.mmap的文件,可以使用kdb import重新导入该文件。

实际结果

将创建一个名为test.mmap的空文件,并显示以下消息(包括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

系统信息

  • Elektra版本:大师

更多信息

〜工程时, kdb export称为根〜。(编辑:见下面的评论) kdb export user/tests/hello mmapstorage test.mmap也可以,但是是完全无证功能kdb export 。 因此,我们可能需要更好的错误消息和更新的文档。

最有用的评论

感谢你的回复!

mmap错误消息可能会引起误解。

请改善错误消息。

据我所知,它在stdout上不起作用。 它也不适用于管道

请将该信息添加到错误消息中。

上面的解决方案并没有改变很多毫微存储逻辑。

由于您的插件是目前唯一受影响的插件,因此您有必要进行统计并根据需要复制所有内容。 然后,我们可以在不对框架进行较大更改的情况下解决此问题。

所有22条评论

感谢您尝试此操作以及此详细报告!

因此,我们可能需要更好的错误消息和更新的文档。

是的,我完全同意。

也许我们甚至应该在serializable infos / status#666中有一个@mpranj还是有办法检测文件是否不可映射?它确实等同于被拒绝的权限吗?)

查看代码(和错误消息),我认为当前的问题是,在没有root用户访问权限的情况下,我们无法在stdout上调用unlink 。 同样open也可能会失败,因为stdout已经打开。 stdout是否可映射取决于我认为连接的stdout
使用fstat(fileno(stdout), &stat)检查它是否为常规文件可能有效。 也许isatty(3)也可以。

在任何情况下,我们都可以简单地检查输出文件是否为/dev/stdout (或CON_WIN32 )并创建一个供mmap使用的临时文件,然后将其复制到stdout 。 这当然会慢一些,但是我们将保留管道输出kdb export的可能性。

也许我们甚至应该在serializable infos / status#666中有一个

如果有的话,如果格式不是人类可读的,那么我的状态humanreadable并拒绝导出到tty stdout。

kdb export被称为root时有效。

我拿回去...不要尝试! 以root用户身份调用kdb export <something> mmapstorage (即使重定向了stdout)也会破坏/dev/stdout 。 使用/dev/stdout (例如,通过fopen )在您的系统上不起作用,直到您使用sudo rm /dev/stdout && sudo ln -s /dev/stdout /proc/self/fd/1重新创建默认的符号链接。

我认为最好的解决方案是kdb exportkdb import始终可用于临时文件。 那么kdb export将与KDB更加相似。 这将解决未链接的问题(这对于mmaped文件是必需的。)缺点仅在于性能下降(需要复制所有内容),然后导入/导出将与所有存储插件一起使用,这是非常重要的。

我认为最好的解决方案是kdb exportkdb import始终可用于临时文件。

我认为,如果需要,插件应自行创建临时文件。 这样,我们避免了直接输出到TTY的插件的性能损失。 AFAIK mmapstorage当前是唯一不支持TTY的插件。 我们还可以添加一个简单的shell测试,以确保可以通过kdb export /some/key plugin > export.file调用所有存储插件。 逻辑也更加独立,因为知道如何产生期望的输出确实是插件的责任。

另外,对于kdb import ,不需要临时文件,因为即使对TTY(如果您具有正确的权限),读取文件也应始终有效。

我认为,如果需要,插件应自行创建临时文件。

然后,插件(或更具体地说是mmap)将需要知道它是在KDB还是kdb export

@mpranj您的意见是什么? 可以在mmap插件中解决此问题吗?

这样,我们避免了直接输出到TTY的插件的性能损失。

在哪种情况下,性能下降会成为问题? 也许在每个测试用例的备份/还原中?

AFAIK mmapstorage是当前唯一不能与TTY一起使用的插件。

出口是的。 但是对于导入,我们有几个无效的插件。 如果插件使用fseek或类似工具,则显然无法工作,例如csvstorage或mozprefs。 (转储现在应该已修复)

我们还可以添加一个简单的shell测试,以确保可以通过kdb export / some / key plugin> export.file调用所有存储插件。

您是说tests / shell / check_export.sh第46行?

在哪种情况下,性能下降会成为问题?

实际上,可能永远不会。 只要您使用导出/导入的3个参数版本而不是管道。 请参阅下面的提案。

您是说tests / shell / check_export.sh第46行?

是的,但这是无效的,因为is_not_rw_storage不起作用。 甚至dump都不被视为存储插件。


我认为要快速轻松地解决此问题,我们应该执行以下操作:

  1. include_common.sh.in tests/shell/check_export.sh修复is_not_rw_storage ,以便将来我们能发现类似的问题。
  2. 仅在未给出第三个参数的情况下,在kdb export创建一个临时文件。 在kdbSet调用中使用此文件,然后将其内容复制打印到stdout(在C ++中不应超过一两行)。
  3. 同样,对于kdb import如果使用stdin,则创建一个临时文件。 将所有stdin复制到临时文件中,并使用该文件调用kdbGet
  4. 更新kdb importkdb export的文档以声明第三个参数存在。 还声明如果使用两个参数版本,我们将创建一个临时文件。

PS。 这可能是good first issue

感谢您报告is_not_rw_storage损坏,我打开了#2423

抱歉,我已经离开了一个星期,所以我无法对其进行调查。

mmap错误消息可能会引起误解。 尝试映射非常规文件时, mmap()失败,并带有EACCES 。 据我所知,它在stdout上不起作用。 如#2209中所述,它也不适用于管道。

从POSIX:

以下存储对象应支持mmap()函数:

  • 常规文件
  • [SHM]共享内存对象
  • [TYM]类型的内存对象

至于mmapstorage中的解决方案,我们可以检查它是否是带有stat的常规文件,然后:

  • 如上所述,写入临时的常规文件
  • 写入临时内存位置(仅用malloc代替mmap),然后复制到非常规文件(pipe,stdout等)。

我也欢迎其他解决方案。 上面的解决方案并没有改变很多毫微存储逻辑。 重新构造mmapstorage以直接使用管道或stdout对我来说没有太大意义。

感谢你的回复!

mmap错误消息可能会引起误解。

请改善错误消息。

据我所知,它在stdout上不起作用。 它也不适用于管道

请将该信息添加到错误消息中。

上面的解决方案并没有改变很多毫微存储逻辑。

由于您的插件是目前唯一受影响的插件,因此您有必要进行统计并根据需要复制所有内容。 然后,我们可以在不对框架进行较大更改的情况下解决此问题。

然后,我们可以在不对框架进行较大更改的情况下解决此问题。

我们还应该将手册页更新为kdb importkdb export 。 当前,他们没有提到不依赖于stdin / stdout的3个参数版本。

感谢您报告问题和提供意见!

不幸的是, strerror打印这些误导性错误消息。 在这种情况下,我可以添加一个提示。

我将在本周的PR中进行要求的更改。

我们还应该更新kdb导入和kdb导出的手册页。 当前,他们没有提到不依赖于stdin / stdout的3个参数版本。

也许我们不需要参数来指定文件? 一旦kdb import/export支持多个插件,该参数将发生冲突。

我将在本周的PR中进行要求的更改。

谢谢!

也许我们不需要参数来指定文件?

然后,我们必须在所有插件中支持stdinstdout (重定向到常规文件)。 否则,它们将无法与kdb import/export 。 这对于mmapstorage来说是明智的,因为它不可移植,但是其他可移植的插件(甚至是人类可读的)也可能需要常规文件(例如,如果他们使用fseek )。

一旦kdb import/export支持多个插件,该参数将发生冲突。

当我们切换到使用elektraGetOpts时,我们可以轻松地使用选项-i FILE, --input=FILE-o FILE, --ouput=FILE elektraGetOpts

是的,我们可以添加-i,-o选项。 但是修复插件(或导入/导出框架),使stdin / stdout也可以正常工作。

要使用kdb export解决此问题,

现在可以使用: kdb import user/tests/ mmapstorage < test.mmap
但这不是: cat test.mmap | kdb import user/tests/ mmapstorage ,因为mmap再次无法处理它。

为了使解决方案保持一致(从而与非常规文件完全兼容),也需要针对kdbGet()函数进行解决。 大约有三种解决方案:

  1. 写入临时文件并取消链接(有点难看,但简单的解决方案)
  2. 重做我的mmap工作的一半(难看和大量工作)
  3. 制作大量副本并重新实现ksDeepDup也可以制作元密钥集的副本(非常难看,半简单的代码)

这是可取的还是我们忽略了它?

我想我们现在可以忽略它,因为我们已经有了快速转储。 只需将其记录为不适合序列化即可。 现在,我们将重新修改导入/导出框架,然后我们将找到一个合适的解决方案。 @mpranj

实际上,如果#2639解决此问题,然后@mpranj您为cat ...问题创建一个新对象,则可能会更好。

2639在这里解决了所有问题。 它在Linux上运行良好,我只需要修复一个错误,因此它也可以在BSD上运行。

我有一个非常不错的解决方案(使用realpathstat ),不幸的是,该解决方案在BSD上不起作用。 在其中投入更多时间是没有意义的。

我决定将其丢弃,因此不能使mmapstorage与非常规文件完全兼容。 它仅适用于kdb导入/导出。 通过检查文件是“ /dev/stdin ”还是“ /dev/stdout ”,新的解决方案将简单地检查是否使用了kdb import / export。 同样在quickdump

我有一个非常好的解决方案(使用realpath和stat),不幸的是,该解决方案无法在BSD上使用。

这是注释掉的解决方案吗?

在其中投入更多时间是没有意义的。

没错,框架应处理此问题。 我创建了#2640。

仅适用于kdb导入/导出

还可以使用cat | kdb import变体吗?

在quickdump中也是如此。

区别在哪里?

可以将此代码移至导入/导出框架吗?

这是注释掉的解决方案吗?

我将其保留在历史记录中,但后来删除了这些行。 imho更好的解决方案一直持续到https://github.com/ElektraInitiative/libelektra/pull/2639/commits/a523f9b38b56687d532f5101c7ef44c078e2308d。 请注意,它在Linux上效果很好,但在BSD上效果不好。

我遇到的一个问题是stdin / stdout无法在BSD上打开()ed。 另一个是您确实必须使用realpath来对文件进行stat()并确定它是否为常规文件。 否则,stat只能为我解决一级符号链接。 对于我而言,这种方法在BSD上失败了,因为realpath以某种方式解析为不存在的文件。

还带猫| kdb导入变体?

是!

区别在哪里?

相关部分相同,对于造成的混乱,我们深表歉意。 我的意思是我们为/ dev / stdin strcmp而不是使用stat来确定它是否是常规文件。 这意味着如果我们使用/ dev / fd /,它仍然会失败。 我的其他解决方案使用stat而不是strcmp,因此它可以使用任何路径。

编辑

可以将此代码移至导入/导出框架吗?

是的,我认为代码几乎完全在那里,但是我没有时间正确解决BSD问题。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

mpranj picture mpranj  ·  3评论

sanssecours picture sanssecours  ·  4评论

mpranj picture mpranj  ·  3评论

markus2330 picture markus2330  ·  4评论

mpranj picture mpranj  ·  3评论