Plan 9 from Bell Labs’s /usr/web/sources/contrib/de0u/root/sys/src/cmd/divergefs/moderule.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <fcall.h>
#include <String.h>
#include "common.h"
#include "debug.h"
#include "utils.h"
#include "rule.h"
#include "moderule.h"

enum 
{ 
  DEBUG_MODERULE = false,
  DEBUG_MODEBASICRULE = false
};


static void modebasicrule_free(Rule *rule);
static bool modebasicrule_issatisfy(Rule *rule, char *path, Dir *d);
static bool modebasicrule_contains(
  Rule *rule, char *path, int omode, ulong perm);

typedef struct ModeBasicRuleOperations
{
  bool (*isperm)(ulong perm);
  bool (*ismode)(ulong perm, char *path, Dir *d);
} ModeBasicRuleOperations;

typedef struct ModeBasicRule
{
  Rule;
  ModeBasicRuleOperations mbops; 
} ModeBasicRule;

static RuleOperations modebasicruleops = 
{
  .free = modebasicrule_free,
  .issatisfy = modebasicrule_issatisfy,
  .contains = modebasicrule_contains
};


static bool isperm_true(ulong)
{
  return true;
}

static bool isperm_append(ulong perm)
{
  return perm_isappend(perm);
}

static bool isperm_exclusive(ulong perm)
{
  return perm_isexclusive(perm);
}

static bool isperm_directory(ulong perm)
{
  return perm_isdir(perm);
}

static bool isperm_regular(ulong perm)
{
  return !isperm_directory(perm);
}


static bool ismode_true(ulong, char *, Dir *)
{
  return true;
}


static bool ismode_read(ulong perm, char *path, Dir *)
{
  if(path != nil)
  {
    return access(path, AREAD) == 0;
  }
  return perm_isread(perm);
}

static bool moderule_dirismode(Dir *d, bool (*modetest)(ulong))
{
  assert_valid(modetest);
  return d != nil && qid_isdir(&d->qid) && modetest(d->mode);
}

static bool ismode_write(ulong perm, char *path, Dir *d)
{
  if(path != nil)
  {
    return moderule_dirismode(d, dirmode_iswrite) || access(path, AWRITE) == 0;
  }
  return perm_iswrite(perm);
}

static bool ismode_exec(ulong perm, char *path, Dir *d)
{
  if(path != nil)
  {
    return moderule_dirismode(d, dirmode_isexec) || access(path, AEXEC) == 0;
  }
  return perm_isexec(perm);
}

static bool ismode_exist(ulong, char *path, Dir *)
{
  if(path != nil)
  {
    return access(path, AEXIST) == 0;
  }
  return true;
}


typedef struct CharMbopsPair
{
  char mode;
  ModeBasicRuleOperations;
} CharMbopsPair;

CharMbopsPair mbopsregistry[] =
{
  {'A', isperm_append,    ismode_true},
  {'L', isperm_exclusive, ismode_true}, 
  {'f', isperm_regular,   ismode_true},
  {'d', isperm_directory, ismode_true},
  {'r', isperm_true,      ismode_read},
  {'w', isperm_true,      ismode_write},
  {'x', isperm_true,      ismode_exec},
  {'e', isperm_true,      ismode_exist}
};

static void modebasicrule_findmbops(char mode, ModeBasicRuleOperations *mbops)
{
  int i;
  assert_valid(mbops);
  for(i = 0; i < static_array_length(mbopsregistry); ++i)
  {
    if(mode == mbopsregistry[i].mode)
    {
      NOISE(DEBUG_MODEBASICRULE, 
        "modebasicrule_findmbops found mode: %c", mode);
      mbops->isperm = mbopsregistry[i].isperm;
      mbops->ismode = mbopsregistry[i].ismode;
      break;
    }
  }
}

Rule *modebasicrule_new(char *mode, char *root)
{
  ModeBasicRule *result;
  char buf[RULE_MAXNAMELEN];
  assert_valid(mode);
  assert_valid(root);

  if(strlen(mode) > 1)
  {
    return nil;
  }

  result = (ModeBasicRule *)emallocz_fs(sizeof(*result));
  result->ops = &modebasicruleops;
  result->root = estrdup_fs(root);
  snprint(buf, sizeof(buf), "mode<%c>", *mode);
  result->name = estrdup_fs(buf);
  modebasicrule_findmbops(*mode, &(result->mbops));
  if(result->mbops.isperm == nil || result->mbops.ismode == nil)
  {
    NOISE(DEBUG_MODEBASICRULE, 
      "modebasicrule_new did not find any matching mode");
    rule_free(result);
    result = nil;
  }
  return result;
}

static void modebasicrule_free(Rule *rule)
{
  assert_valid(rule);
  free(rule->name);
  rule->name = nil;
  free(rule);
}

static bool modebasicrule_issatisfy(Rule *rule, char *path, Dir *d)
{
  bool result;
  String *fullpath;
  ModeBasicRule *self = (ModeBasicRule *)rule;

  NOISE(DEBUG_MODEBASICRULE, 
    "entering modebasicrule_issatisfy with path: %s d->mode: %ulX", 
    path, d->mode);

  fullpath = rule_assemble_path(rule, path);
  result = 
    self->mbops.ismode(0, s_to_c(fullpath), d) && self->mbops.isperm(d->mode);

  NOISE(DEBUG_MODEBASICRULE,
    "leaving modebasicrule_issatisfy with result: %d", result);

  s_free(fullpath);
  return result;
}

static bool modebasicrule_contains(
  Rule *rule, char *, int omode, ulong perm)
{
  bool result;
  ModeBasicRule *self = (ModeBasicRule *)rule;

  NOISE(DEBUG_MODEBASICRULE, 
    "entering modebasicrule_contains with omode: %b perm: %ulb", omode, perm);
  result = self->mbops.ismode(perm, nil, nil) && self->mbops.isperm(perm);

  NOISE(DEBUG_MODEBASICRULE, 
    "leaving modebasicrule_contains with result: %d", result);
  return result;
}


Rule *moderule_parse(char *rule, char *setting, char *path)
{  
  assert_valid(rule);
  assert_valid(setting);
  assert_valid(path);
  if(strcmp(rule, "mode") != 0)
  {
    return nil;
  }
  
  INFO(DEBUG_MODERULE, "parsed mode rule with path: %s", path);
  return modebasicrule_new(setting, path);
}


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.