由startproc运行的程序的QDir :: homePath()的非预期结果

时间:2018-03-15 15:33:24

标签: c++ linux qt

我有以下小程序:

#include <unistd.h>
#include <pwd.h>

#include <QCoreApplication>
#include <QDir>

const char * homeDir()
{
  return getpwuid(geteuid())->pw_dir;
}

int main(int argc, char *argv[])
{
  printf("Qt homedir: %s\n", qPrintable(QDir::homePath()));
  printf("Native homedir: %s\n", homeDir());

  QCoreApplication a(argc, argv);
  return a.exec();
}

现在:

  • 直接由“普通”用户./program运行时,输出为:
      

    Qt homedir:/ home / user
      本地homedir:/ home / usr

没关系

  • 直接由root ./program运行时,输出为:
      

    Qt homedir:/ root
      本地homedir:/ root

没关系

  • 当root作为不同的用户通过sudo运行时,例如sudo -u user ./program,输出为:
      

    Qt homedir:/ home / user
      本地homedir:/ home / user

没关系

  • 当通过startproc以root身份作为其他用户运行时,例如startproc -u user /full/path/to/program,输出为:
      

    Qt homedir:/ root
      本地homedir:/ home / user

确定,或者不期望(至少对我而言)

我的问题是:为什么最后一次运行会产生与其他运行不同的结果?它是Qt中的一个错误(没有考虑到有效用户与真实用户不同的事实,或者不同的东西),或者我是否缺少一些背景信息(例如startproc如何工作的机制)? / p>

有问题的Qt版本是5.6.1。

1 个答案:

答案 0 :(得分:1)

Qt&#39; QFileSystemEngine使用Unix上HOME环境变量的内容 - 请参阅implementation。但是startproc -u没有设置HOME:这就是失败的原因。

getpwuid电话可能非常昂贵并且可以阻止,即通过从LDAP或AD服务器等获取信息,如果您自己处理它,它是最好的。此外,它不是线程安全的,您应该使用getpwuid_r代替。

实现可能如下所示:

static QString getHomeDir() {
  auto const N = sysconf(_SC_GETPW_R_SIZE_MAX);
  auto *buffer = std::make_unique<char[]>(N);
  passwd pwd;
  passwd *result;
  getpwuid_r(geteuid(), &pwd, buffer.get(), N, &result);
  if (result) {
    auto *dir = result->pw_dir;
    auto const decoded = QFile::decodeName(dir);
    return QDir::cleanPath(decoded);
  }
  return {};
}

enum class HomeDir { Default, Init };
QString homeDir(HomeDir option = HomeDir::Default) {
  // needs a C++11 compiler for thread-safe initialization
  static QFuture<QString> home = QtConcurrent::run(getHomeDir);
  return (option == HomeDir::Init) ? QString() : home;
};

int main(int argc, char **argv) {
  QCoreApplication app(argc, argv);
  homeDir(HomeDir::Init);
  // do other time-consuming initializations here
  QString () << homeDir();
}