Skip to content

Commit

Permalink
Test whether using C++ permissions lookup helps on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
starseeker committed Sep 19, 2024
1 parent c1b1a0e commit fe17b76
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 44 deletions.
1 change: 1 addition & 0 deletions regress/repository/repocheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ regex_init(repo_info_t &r) {
"cursor[.]c$",
"misc/CMake/compat/.*",
"ttcp[.]c$",
"file[.]cpp$",
NULL
};
cnt = 0;
Expand Down
2 changes: 1 addition & 1 deletion src/libbu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ set(LIBBU_SOURCES
escape.c
fchmod.cpp
fgets.c
file.c
file.cpp
fort.c
fnmatch.c
getcwd.c
Expand Down
131 changes: 88 additions & 43 deletions src/libbu/file.c → src/libbu/file.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* F I L E . C
/* F I L E . C P P
* BRL-CAD
*
* Copyright (c) 2004-2024 United States Government as represented by
Expand All @@ -20,6 +20,9 @@

#include "common.h"

#include <filesystem>
#include <system_error>

#include <string.h>
#include <ctype.h>
#ifdef HAVE_SYS_TYPES_H
Expand Down Expand Up @@ -260,7 +263,6 @@ bu_file_same(const char *fn1, const char *fn2)
return ret;
}


/**
* common guts to the file access functions that returns truthfully if
* the current user has the ability permission-wise to access the
Expand All @@ -270,18 +272,13 @@ static int
file_access(const char *path, int access_level)
{
struct stat sb;
int mask = 0;

/* 0 is root or Windows user */
uid_t uid = 0;

/* 0 is wheel or Windows group */
gid_t gid = 0;

int usr_mask = S_IRUSR | S_IWUSR | S_IXUSR;
int grp_mask = S_IRGRP | S_IWGRP | S_IXGRP;
int oth_mask = S_IROTH | S_IWOTH | S_IXOTH;

if (UNLIKELY(!path || (path[0] == '\0'))) {
return 0;
}
Expand All @@ -290,20 +287,19 @@ file_access(const char *path, int access_level)
return 0;
}

if (access_level & R_OK) {
mask = S_IRUSR | S_IRGRP | S_IROTH;
}
if (access_level & W_OK) {
mask = S_IWUSR | S_IWGRP | S_IWOTH;
std::filesystem::perms p = std::filesystem::perms::none;
try
{
p = std::filesystem::status(path).permissions();
}
if (access_level & X_OK) {
#ifndef HAVE_WINDOWS_H
// Windows _chmod doesn't have a concept of executable, so there isn't
// anything to check for this case. See:
// https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/chmod-wchmod
mask = S_IXUSR | S_IXGRP | S_IXOTH;
#endif
catch (std::filesystem::filesystem_error const &)
{
bu_log("Error: unable to get permissions for %s\n", path);
return 0;
}
if (p == std::filesystem::perms::unknown)
return 0;


#ifdef HAVE_GETEUID
uid = geteuid();
Expand All @@ -312,37 +308,86 @@ file_access(const char *path, int access_level)
gid = getegid();
#endif

// If we're not checking for anything, pass
if (!mask)
return 1;

if ((uid_t)sb.st_uid == uid) {
/* we own it */
return sb.st_mode & (mask & usr_mask);
} else if ((gid_t)sb.st_gid == gid) {
/* our primary group */
return sb.st_mode & (mask & grp_mask);
}

bool we_own = ((uid_t)sb.st_uid == uid);
if (we_own) {
switch (access_level) {
case R_OK:
if (std::filesystem::perms::none != (p & std::filesystem::perms::owner_read))
return 1;
break;
case W_OK:
if (std::filesystem::perms::none != (p & std::filesystem::perms::owner_write))
return 1;
break;
case X_OK:
if (std::filesystem::perms::none != (p & std::filesystem::perms::owner_exec))
return 1;
break;
default:
bu_log("Error - unknown access level\n");
return 0;
};
}

bool in_grp = ((gid_t)sb.st_gid == gid);
/* search group database to see if we're in the file's group */
#if defined(HAVE_PWD_H) && defined (HAVE_GRP_H)
{
if (!in_grp) {
struct passwd *pwdb = getpwuid(uid);
if (pwdb && pwdb->pw_name) {
int i;
struct group *grdb = getgrgid(sb.st_gid);
for (i = 0; grdb && grdb->gr_mem[i]; i++) {
if (BU_STR_EQUAL(grdb->gr_mem[i], pwdb->pw_name)) {
/* one of our other groups */
return sb.st_mode & (mask & grp_mask);
in_grp = true;
}
}
}
}
#endif

if (in_grp) {
switch (access_level) {
case R_OK:
if (std::filesystem::perms::none != (p & std::filesystem::perms::group_read))
return 1;
break;
case W_OK:
if (std::filesystem::perms::none != (p & std::filesystem::perms::group_write))
return 1;
break;
case X_OK:
if (std::filesystem::perms::none != (p & std::filesystem::perms::group_exec))
return 1;
break;
default:
bu_log("Error - unknown access level\n");
return 0;
};
}

/* check other */
return sb.st_mode & (mask & oth_mask);
switch (access_level) {
case R_OK:
if (std::filesystem::perms::none != (p & std::filesystem::perms::others_read))
return 1;
break;
case W_OK:
if (std::filesystem::perms::none != (p & std::filesystem::perms::others_write))
return 1;
break;
case X_OK:
if (std::filesystem::perms::none != (p & std::filesystem::perms::others_exec))
return 1;
break;
default:
bu_log("Error - unknown access level\n");
return 0;
};

// Shouldn't get here
return 0;
}


Expand Down Expand Up @@ -561,12 +606,12 @@ bu_ftell(FILE *stream)
return ret;
}

/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8

0 comments on commit fe17b76

Please sign in to comment.