1
0
Files
2022-09-29 17:59:04 +03:00

263 lines
4.9 KiB
C

#include "Fsd.H"
#include <assert.h>
#include <errno.h>
#include <fam.h>
#include <mntent.h>
#include <string.h>
#include <unistd.h>
Fsd *Fsd::_auto;
//Fsd *Fsd::_tab;
Fsd::Fsd(const char *path)
: _path(strcpy(new char[strlen(path) + 1], path)),
_nentries(0),
_entries(NULL),
_mon(path, change_proc, this),
_end_exist_seen(false)
{
read();
}
Fsd::~Fsd()
{
destroy();
}
const mntent *
Fsd::operator [] (unsigned int index) const
{
if (index < _nentries)
return _entries + index;
else
return NULL;
}
mntent *
Fsd::operator [] (unsigned int index)
{
if (index < _nentries)
return _entries + index;
else
return NULL;
}
mntent *
Fsd::at_fsname_type(const char *fsname, const char *type)
{
for (mntent *mnt = _entries, *end = mnt + _nentries; mnt < end; mnt++)
if (!strcmp(fsname, mnt->mnt_fsname) && !strcmp(type, mnt->mnt_type))
return mnt;
return NULL;
}
mntent *
Fsd::at_dir(const char *dir)
{
for (mntent *mnt = _entries, *end = mnt + _nentries; mnt < end; mnt++)
if (!strcmp(dir, mnt->mnt_dir))
return mnt;
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
void
Fsd::replace(unsigned int index, const mntent *new_entry)
{
const char tmplate[] = "/etc/fsdXXXXXX";
char tmpname[sizeof tmplate];
(void) strcpy(tmpname, tmplate);
mktemp(tmpname);
FILE *f = setmntent(_path, "r+");
if (!f)
return;
FILE *tf = setmntent(tmpname, "w");
if (!tf)
{ (void) endmntent(f);
return;
}
destroy();
const mntent *mnt;
int error = 0; // assume not found
for (int i = 0; mnt = getmntent(f); i++)
{ if (i == index)
mnt = new_entry;
if (addmntent(tf, mnt))
{ error = errno;
break;
}
}
if (i <= index)
if (addmntent(tf, mnt))
error = errno;
// Rename the files before releasing the lock on either one.
if (error == 0)
{ if (::rename(tmpname, _path))
error = errno;
}
else
(void) unlink(tmpname);
endmntent(f);
endmntent(tf);
read();
}
#if 0
void
Fsd::remove(unsigned int index)
{
const char tmplate[] = "/etc/fsdXXXXXX";
char tmpname[sizeof tmplate];
(void) strcpy(tmpname, tmplate);
mktemp(tmpname);
FILE *f = setmntent(_path, "r+");
if (!f)
return;
FILE *tf = setmntent(tmpname, "w");
if (!tf)
{ (void) endmntent(f);
return;
}
destroy();
const mntent *mnt;
int error = 0; // assume not found
for (int i = 0; mnt = getmntent(f); i++)
if (i != index && addmntent(tf, mnt))
{ error = errno;
break;
}
if (i <= index)
if (addmntent(tf, mnt))
error = errno;
// Rename the files before releasing the lock on either one.
if (error == 0)
{ if (::rename(tmpname, _path))
error = errno;
}
else
(void) unlink(tmpname);
endmntent(f);
endmntent(tf);
read();
}
#endif
void
Fsd::append(const mntent *new_entry)
{
FILE *f = setmntent(_path, "w+");
if (f)
{ (void) addmntent(f, new_entry);
(void) endmntent(f);
destroy();
read();
}
}
///////////////////////////////////////////////////////////////////////////////
void
Fsd::read()
{
unsigned int i;
FILE *f = setmntent(_path, "r+");
if (!f)
return;
for (_nentries = 0; getmntent(f); _nentries++)
continue;
rewind(f);
_entries = new mntent[_nentries];
for (i = 0; i < _nentries; i++)
{
mntent *mnt = getmntent(f);
assert(mnt);
// Allocate one string per mntent, copy all _mnt* strings
// into that one string.
int nchar = strlen(mnt->mnt_fsname) + strlen(mnt->mnt_dir) +
strlen(mnt->mnt_type) + strlen(mnt->mnt_opts) + 4;
char *buf = new char[nchar];
char *p = buf;
_entries[i].mnt_fsname = strcpy(p, mnt->mnt_fsname);
p += strlen(p) + 1;
_entries[i].mnt_dir = strcpy(p, mnt->mnt_dir);
p += strlen(p) + 1;
_entries[i].mnt_type = strcpy(p, mnt->mnt_type);
p += strlen(p) + 1;
_entries[i].mnt_opts = strcpy(p, mnt->mnt_opts);
p += strlen(p) + 1;
_entries[i].mnt_freq = mnt->mnt_freq;
_entries[i].mnt_passno = mnt->mnt_passno;
}
assert(!getmntent(f));
endmntent(f);
}
void
Fsd::destroy()
{
if (_entries)
{ for (unsigned int i = 0; i < _nentries; i++)
delete [] _entries[i].mnt_fsname;
delete [] _entries;
_nentries = 0;
_entries = NULL;
}
}
void
Fsd::change_proc(FAMonitor&, const FAMEvent& event, void *closure)
{
Fsd *fsd = (Fsd *) closure;
FAMCodes code = event.code;
if (code == FAMEndExist)
fsd->_end_exist_seen = true;
else if (fsd->_end_exist_seen)
{ fsd->destroy();
fsd->read();
}
}
//////////////////////////////////////////////////////////////////////////////
Fsd&
Fsd::fsd_auto()
{
if (!_auto)
_auto = new Fsd("/etc/fsd.auto");
assert(_auto);
return *_auto;
}
#if 0 // not needed
Fsd&
Fsd::fsd_tab()
{
if (!_tab)
_tab = new Fsd("/etc/fsd.tab");
assert(_tab);
return *_tab;
}
#endif /* 0 */