/* -*-Mode: C++;-*-
* PRCS - The Project Revision Control System
* Copyright (C) 1997 Josh MacDonald
*
* 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 2
* 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* $Id: fileent.cc 1.9.1.1.1.7.1.13.1.6.1.1.1.20 Sun, 28 Oct 2001 00:54:02 -0700 jmacd $
*/
extern "C" {
#include <pwd.h>
#include <utime.h>
}
#include "prcs.h"
#include "projdesc.h"
#include "fileent.h"
#include "repository.h"
#include "misc.h"
#include "system.h"
#include "vc.h"
FileEntry::FileEntry (Dstring *working_path,
const ListMarker &ent_marker,
const PrcsAttrs *attrs,
Dstring *desc_ver,
Dstring *desc_name,
Dstring *link_name,
mode_t mode)
:_stat_mode(0),
_stat_mtime(-1),
_stat_size(0),
_stat_ino(0),
_unkeyed_length(0),
_unmodified(false),
_present(false),
_file_mode(mode),
_on_command_line(true),
_ent_marker (ent_marker),
_user (NULL),
_date (NULL),
_link_name (link_name),
_work_path (working_path),
_rcs_version_string (desc_ver),
_descriptor_name (desc_name),
_temp_path (NULL),
_full_rep_path (NULL),
_attrs (attrs) { }
const char* FileEntry::descriptor_name() const
{ return _descriptor_name ? _descriptor_name->cast() : NULL; }
const char* FileEntry::descriptor_version_number() const
{ return _rcs_version_string ? _rcs_version_string->cast() : NULL; }
const char* FileEntry::full_descriptor_name()const
{ return _full_rep_path ? _full_rep_path->cast() : NULL; }
const char* FileEntry::working_path() const { return _work_path ? _work_path->cast() : NULL; }
const char* FileEntry::temp_file_path() const { return _temp_path ? _temp_path->cast() : NULL; }
const char* FileEntry::link_name() const { return _link_name ? _link_name->cast() : NULL; }
const char* FileEntry::last_mod_date() const { return _date ? _date->cast() : NULL; }
const char* FileEntry::last_mod_user() const { return _user ? _user->cast() : NULL; }
const PrcsAttrs* FileEntry::file_attrs() const { return _attrs; }
ProjectDescriptor* FileEntry::project() const { return _attrs->project(); }
bool FileEntry::keyword_sub() const { return _attrs->keyword_sub(); }
FileType FileEntry::file_type() const { return _attrs->type(); }
const ListMarker* FileEntry::ent_marker() const { return &_ent_marker; }
mode_t FileEntry::file_mode() const { return _file_mode; }
mode_t FileEntry::stat_permissions() const { return _stat_mode & 0x1ff; }
mode_t FileEntry::stat_mode() const { return _stat_mode; }
off_t FileEntry::stat_length() const { return _stat_size; }
time_t FileEntry::stat_mtime() const { return _stat_mtime; }
ino_t FileEntry::stat_inode() const { return _stat_ino; }
int FileEntry::plus_lines() const { return _plus_lines; }
int FileEntry::minus_lines() const { return _minus_lines; }
void FileEntry::set_lines (int plus, int minus)
{
_plus_lines = plus;
_minus_lines = minus;
}
bool FileEntry::unmodified() const { return _unmodified; }
bool FileEntry::present() const { return _present; }
bool FileEntry::on_command_line() const { return _on_command_line; }
bool FileEntry::real_on_cmd_line() const
{ return _on_command_line && file_type() == RealFile; }
int FileEntry::unkeyed_length() const { return _unkeyed_length; }
const char* FileEntry::checksum() const { return _checksum; }
void FileEntry::set_on_command_line(bool b) { _on_command_line = b; }
void FileEntry::set_unmodified(bool b) { _unmodified = b; }
void FileEntry::set_present(bool b) { _present = b; }
void FileEntry::set_checksum(const char* c) { memcpy(_checksum, c, 16); }
void FileEntry::set_unkeyed_length(int len) { _unkeyed_length = len; }
void FileEntry::set_file_mode(mode_t mode) { _file_mode = mode; }
void FileEntry::set_working_path(const char* name) { _work_path->assign (name); }
void FileEntry::set (FileEntry* fe)
{
switch (fe->file_type()) {
case RealFile:
set_descriptor_name(fe->descriptor_name());
set_version_number(fe->descriptor_version_number());
set_file_mode(fe->file_mode());
break;
case SymLink:
set_link_name(fe->link_name());
break;
case Directory:
break;
}
If_fail (_attrs << project()->intern_attrs(&fe->file_attrs()->_vals,
fe->file_attrs()->_ngroup,
working_path(),
false))
ASSERT (false, "The attrs were already validated.");
}
void FileEntry::set_link_name(const char* name)
{
if (!_link_name)
_link_name = new Dstring;
_link_name->assign (name);
}
FileEntry::~FileEntry()
{
if (_full_rep_path) delete _full_rep_path;
if (_temp_path) delete _temp_path;
if (_user) delete _user;
if (_date) delete _date;
if (_link_name && _link_name->is_dstring()) delete _link_name;
if (_work_path && _work_path->is_dstring()) delete _work_path;
if (_rcs_version_string && _rcs_version_string->is_dstring()) delete _rcs_version_string;
if (_descriptor_name && _descriptor_name->is_dstring()) delete _descriptor_name;
}
PrVoidError FileEntry::initialize_descriptor(RepEntry* rep,
bool regist,
bool init_temp_path)
{
if(file_type() == Directory || file_type() == SymLink)
return NoError;
_full_rep_path = new Dstring;
if (init_temp_path)
_temp_path = new Dstring;
if (!_descriptor_name) {
_descriptor_name = new Dstring;
_rcs_version_string = new Dstring;
Return_if_fail(rep->Rep_new_filename(strip_leading_path(working_path()),
_descriptor_name));
rep->Rep_name_in_entry(_descriptor_name->cast(), _full_rep_path);
_full_rep_path->append(",v");
if(regist)
Return_if_fail(VC_register(*_full_rep_path));
} else {
const char* vc_file_path;
Return_if_fail(vc_file_path << rep->Rep_prepare_file(_descriptor_name->cast()));
_full_rep_path->assign(vc_file_path);
}
if (init_temp_path) {
_temp_path->assign(*_full_rep_path);
_temp_path->truncate(_full_rep_path->length() - 2);
}
return NoError;
}
void FileEntry::set_descriptor_name(const char* name)
{
if (!_descriptor_name)
_descriptor_name = new Dstring;
_descriptor_name->assign(name);
}
void FileEntry::set_version_number(const char* ver)
{
if (!_rcs_version_string)
_rcs_version_string = new Dstring;
_rcs_version_string->assign(ver);
}
bool FileEntry::empty_descriptor() const
{
switch (file_type()) {
case SymLink:
return _link_name == NULL;
case RealFile:
return _descriptor_name == NULL;
default:
return false;
}
}
PrBoolError FileEntry::check_working_file()
{
const char* name = working_path();
/* see that its there and that its readable */
if (Failure(stat()) || (file_type() == RealFile && !fs_file_readable(name))) {
if(errno != ENOENT)
prcswarning << "Can't stat " << squote(name) << perror;
return false;
}
switch (file_type()) {
case Directory:
if (!S_ISDIR(_stat_mode))
pthrow prcserror << "Named directory " << squote(name)
<< " is not a directory" << dotendl;
break;
case SymLink:
if (!S_ISLNK(_stat_mode))
pthrow prcserror << "Named symlink " << squote(name)
<< " is not a symlink" << dotendl;
break;
case RealFile:
if (!S_ISREG(_stat_mode))
pthrow prcserror << "Named file " << squote(name)
<< " is not a regular file" << dotendl;
break;
}
return true;
}
PrVoidError FileEntry::get_repository_info(RepEntry* rep_entry)
{
RcsVersionData* data;
Return_if_fail(data << rep_entry->lookup_rcs_file_data(descriptor_name(), descriptor_version_number()));
_stat_mtime = data->date();
_user = new Dstring(data->author());
_date = new Dstring(time_t_to_rfc822(_stat_mtime));
_plus_lines = data->plus_lines ();
_minus_lines = data->minus_lines ();
return NoError;
}
PrVoidError FileEntry::get_file_sys_info()
{
If_fail(stat())
pthrow prcserror << "Stat failed on file "
<< squote(working_path()) << perror;
struct passwd* pwd = getpwuid(_stat_uid);
const char* name = pwd == NULL ? "unknown" : pwd->pw_name;
_user = new Dstring(name);
_date = new Dstring(time_t_to_rfc822(_stat_mtime));
return NoError;
}
NprVoidError FileEntry::stat()
{
struct stat buf;
if (file_type() == SymLink) {
if (::lstat(working_path(), &buf) < 0)
return NonFatalError;
} else {
if (::stat(working_path(), &buf) < 0)
return NonFatalError;
}
_present = true;
_stat_mode = buf.st_mode;
_stat_mtime = buf.st_mtime;
_stat_size = buf.st_size;
_stat_ino = buf.st_ino;
_stat_uid = buf.st_uid;
return NoError;
}
PrVoidError FileEntry::chmod(mode_t new_mode0) const
{
mode_t new_mode = new_mode0;
if (new_mode == 0)
new_mode = _file_mode;
if(!option_preserve_permissions && !new_mode0)
/* Only clip with umask if -p and we're creating a file with
* _file_mode, otherwise preserve old mode. */
new_mode &= (0777 ^ get_umask());
If_fail(Err_chmod(working_path(), new_mode))
prcswarning << "Chmod failed on " << squote(working_path()) << perror;
return NoError;
}
PrVoidError FileEntry::utime(time_t mod_time) const
{
if (mod_time > 0) {
struct utimbuf ut;
ut.modtime = mod_time;
ut.actime = get_utc_time_t();
If_fail (Err_utime(working_path(), &ut))
prcswarning << "Utime failed on " << squote(working_path())
<< perror;
}
return NoError;
}
void describe_versionfile (const char* file, RcsVersionData *ver, Dstring &ds)
{
ds.append (file);
ds.append (":");
ds.append (ver->rcs_version ());
}
void FileEntry::describe (Dstring &ds)
{
ds.append (full_descriptor_name ());
ds.append (":");
ds.append (descriptor_version_number ());
}
syntax highlighted by Code2HTML, v. 0.9.1