//
// aegis - project change supervisor
// Copyright (C) 2004-2006, 2008 Peter Miller
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
// .
//
#include
#include
//
// cvsclient.texi: File Modes
//
// A mode is any number of repetitions of
// =
// separated by comma (,).
//
// The is an identifier composed of alphanumeric characters.
// Currently specified: "u" for user, "g" for group, "o" for other (see
// below for discussion of whether these have their POSIX meaning or are
// more loose). Unrecognized values of are silently ignored.
//
// The consists of any data not containing comma (,), end of
// string (\0) or end if line (\n). For u, g, and o mode types, the
// consists of alphanumeric characters, where "r" means read,
// "w" means write, "x" means execute, and unrecognized letters are
// silently ignored.
//
static int
parse_mode_string(string_ty *s, int *mode_p)
{
int mode;
const char *cp;
unsigned char c;
int lhs;
int rhs;
if (!s)
return 0;
mode = 0;
cp = s->str_text;
for (;;)
{
//
// Question: it says "any number of repetitions", what about zero?
// This code will accept zero repetitions.
//
while (*cp == ',')
++cp;
if (!*cp)
{
*mode_p = mode;
return 1;
}
//
// Get the left hand side.
// Question: what if it's empty?
//
lhs = 0;
for (;;)
{
c = *cp++;
switch (c)
{
case 'u':
lhs |= 0700;
continue;
case 'g':
lhs |= 0070;
continue;
case 'o':
lhs |= 0007;
continue;
case 0:
return 0;
case '=':
break;
default:
//
// The is an identifier composed of
// alphanumeric characters. Unrecognized values of
// are silently ignored.
//
if (!isalnum(c))
return 0;
continue;
}
break;
}
//
// Get the right hand side.
// Question: what if it's empty?
//
rhs = 0;
for (;;)
{
switch (*cp++)
{
case 'r':
rhs |= 0444;
continue;
case 'w':
rhs |= 0222;
continue;
case 'x':
rhs |= 0111;
continue;
case '\0':
--cp;
break;
case '\n':
case ',':
break;
}
break;
}
//
// Add the appropriate bits to the mode.
//
mode |= (lhs & rhs);
}
}
int
server_file_mode_get(server_ty *sp)
{
int mode = 0;
nstring mode_string;
if
(
!server_getline(sp, mode_string)
||
!parse_mode_string(mode_string.get_ref(), &mode)
)
{
server_error(sp, "malformed \"%s\" mode string", mode_string.c_str());
mode = 0644;
}
return mode;
}