Hi,

The attached test program is extracted from one of p11-kit tests (the
only failing test) in trust/test_token.c:
test_not_writable (): token = p11_token_new (333, "/non-existant",
"Label");
main(): p11_test (test_not_writable, "/token/not-writable");

This test fails with fakeroot-hurd on Hurd due to that /non-existant is
writable for faked nodes according to:
error_t
netfs_report_access (struct iouser *cred, struct node *np, int *types)
{
  struct netnode *nn = netfs_node_netnode (np);
  if (!(nn->faked & FAKE_MODE))
    return file_check_access (nn->file, types);
  else
    *types = O_RDWR|O_EXEC;
  return 0;
}

which is reasonable if fakeroot is to mimic real root accesses. Return
values are *is_writable=1 and errno="No such file or directory".

However, running this program with fakeroot-tcp on Hurd or fakeroot-sysv
on Linux returns *is_writable=0 and errno="Permission denied" while
running it as real root of course returns *is_writable=1 and errno="No
such file or directory" on both Linux and Hurd. Maybe even the tests
should not be run under fakeroot at all as is done now with
fakeroot debian/rules binary?

The attached patch makes the behaviour the same as on Linux and
fakeroot-tcp. The question is which behaviour is the expected one.

Index: hurd-0.6.git20150704/trans/fakeroot.c
===================================================================
--- hurd-0.6.git20150704.orig/trans/fakeroot.c
+++ hurd-0.6.git20150704/trans/fakeroot.c
@@ -785,11 +785,7 @@ error_t
 netfs_report_access (struct iouser *cred, struct node *np, int *types)
 {
   struct netnode *nn = netfs_node_netnode (np);
-  if (!(nn->faked & FAKE_MODE))
-    return file_check_access (nn->file, types);
-  else
-    *types = O_RDWR|O_EXEC;
-  return 0;
+  return = file_check_access (nn->file, types);
 }
 
 error_t

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <error.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <libgen.h>

#define bool int
#define true 1
#define false 0

static bool
check_directory (const char *path,
                 bool *make_directory,
                 bool *is_writable)
{
  struct stat sb;
  char *parent, *path1;
  bool dummy = 0;
  bool ret;

  fprintf(stderr,"\ntrust/token.c (check_directory): ENTERING stat() path=%s, *make_directory=%d, *is_writable=%d\n", path, *make_directory, *is_writable);
  fflush(stderr);
  if (stat (path, &sb) == 0) {
    fprintf(stderr,"\ntrust/token.c (check_directory): stat(path, &sb) == 0 BEFORE *is_writable\n");
    fflush(stderr);
    *make_directory = false;
    int err = access (path, W_OK);
    *is_writable = S_ISDIR (sb.st_mode) && (err == 0);
    fprintf(stderr,"\ntrust/token.c (check_directory): stat(path, &sb) == 0 AFTER *is_writable, access(2) sets errno\n");
    fprintf(stderr,"\ntrust/token.c (check_directory): access(path, W_OK)=%d, errno=%s, *is_writable=%d\n", err, strerror(errno), *is_writable);
    fflush(stderr);
    return true;
  }

  switch (errno) {

  case EACCES:
    fprintf(stderr,"\ntrust/token.c (check_directory): case EACCES\n");
    fflush(stderr);
    *is_writable = false;
    *make_directory = false;
    return true;

  case ENOENT:
    fprintf(stderr,"\ntrust/token.c (check_directory): case ENOENT\n");
    fflush(stderr);
    *make_directory = true;
    //parent = p11_path_parent (path);
    path1 = strdup(path);
    parent = dirname (path1);
    if (parent == NULL)
      ret = false;
    else
      ret = check_directory (parent, &dummy, is_writable);
    return ret;

  default:
    fprintf(stderr,"\ntrust/token.c (check_directory): case default\n");
    fflush(stderr);
    error (1, errno, "couldn't access: %s", path);
    return false;
  }
}

int main(void)
{
  const char *path ="/non-existant";
  bool ret = false, make_directory = false;
  int is_writable = 0;

  ret = check_directory (path, &make_directory, &is_writable);
  return ret;
}

Reply via email to