Files
cdesktop/cde/programs/dtinfo/DtMmdb/storage/unixf_storage.C
2018-04-28 12:30:20 -06:00

383 lines
9.7 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these libraries and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*
* $TOG: unixf_storage.C /main/8 1998/04/17 11:50:39 mgreess $
*
* Copyright (c) 1993 HAL Computer Systems International, Ltd.
* All rights reserved. Unpublished -- rights reserved under
* the Copyright Laws of the United States. USE OF A COPYRIGHT
* NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
* OR DISCLOSURE.
*
* THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
* SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD. USE,
* DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
* PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
* INTERNATIONAL, LTD.
*
* RESTRICTED RIGHTS LEGEND
* Use, duplication, or disclosure by the Government is subject
* to the restrictions as set forth in subparagraph (c)(l)(ii)
* of the Rights in Technical Data and Computer Software clause
* at DFARS 252.227-7013.
*
* HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
* 1315 Dell Avenue
* Campbell, CA 95008
*
*/
#include "storage/unixf_storage.h"
#ifdef _IBMR2 /* connolly 2/21/95 from the AIX fsync() manpage */
extern "C" int fsync(int fd);
#endif
/***********************************************************/
// Constructor
/***********************************************************/
unixf_storage::
unixf_storage( char* file_path, char* file_name,
rep_policy* rep_p, int m
) :
abs_storage( file_path, file_name, UNIX_STORAGE_CODE, rep_p ),
fstream(), mode(m),
total_bytes(-1), v_file_exist(exist_file(file_name, file_path))
{
}
/***********************************************************/
// Destructor
/***********************************************************/
unixf_storage::~unixf_storage()
{
/*
MESSAGE(cerr, "~unixf storeage ()");
debug(cerr, my_path());
debug(cerr, my_name());
*/
if ( policy )
policy -> remove(*this);
#ifdef REPORT_IO_COUNT
#endif
}
void unixf_storage::remove()
{
#ifdef C_API
int fd = rdbuf() -> fd();
fsync(fd);
::close(fd);
#else
rdbuf() -> close();
#endif
del_file(my_name(), my_path());
/*
int md = mode;
_open(ios::trunc);
mode = md;
_open(mode);
*/
}
/***********************************************************/
// Open the physical file associated with this store
/***********************************************************/
int unixf_storage::_open(int new_mode)
{
char *fmt = NULL;
if ( ! ( *this ) ) {
#ifdef DEBUG
fprintf(stderr, "fstream is in bad status @ %s:%d\n",
__FILE__, __LINE__);
#endif
throw(streamException(fstream::rdstate()));
}
rep_cell* replaced = 0;
if ( policy != 0 ) {
policy -> promote(*this, replaced);
if ( replaced ) {
unixf_storage* us = ((unixf_storage*)replaced);
us -> fstream::close();
if ( us -> fstream::fail() ) {
#ifdef DEBUG
fprintf(stderr, "Can't close db file %s/%s @ %s:%d\n",
us->my_path(), us->my_name(), __FILE__, __LINE__);
#endif
throw(streamException(us -> fstream::rdstate()));
}
}
}
if ( v_file_exist == false ) {
SET_BIT(new_mode, ios::out | ios::trunc);
v_file_exist = true;
}
//MESSAGE(cerr, "_open");
//debug(cerr, total_bytes);
if ( !BIT_TEST(mode, new_mode) ) {
if ( fstream::rdbuf() -> is_open() ) {
fstream::close();
if ( fstream::fail() ) {
#ifdef DEBUG
fprintf(stderr, "Can't close db file %s/%s @ %s:%d\n",
path, name, __FILE__, __LINE__);
#endif
throw(streamException(fstream::rdstate()));
}
}
SET_BIT(mode, new_mode);
fmt = ::form("%s/%s", path, name);
#ifdef C_API
fstream::open((const char *) fmt, mode);
#else
fstream::open((const char *) fmt, (ios_base::openmode)mode);
#endif
// fstream::open((const char *) fmt, mode, open_file_prot());
} else {
if ( ! fstream::rdbuf() -> is_open() ) {
fmt = ::form("%s/%s", path, name);
#ifdef C_API
fstream::open((const char *) fmt, mode);
#else
fstream::open((const char *) fmt, (ios_base::openmode)mode);
#endif
// fstream::open((const char *) fmt, mode, open_file_prot());
}
}
if ( (!(*this)) || !fstream::rdbuf() -> is_open() ) {
MESSAGE(cerr, "_open failed");
debug(cerr, new_mode);
debug(cerr, mode);
debug(cerr, my_path());
debug(cerr, my_name());
#ifdef DEBUG
fprintf(stderr, "Can't close db file %s/%s @ %s:%d\n",
path, name, __FILE__, __LINE__);
#endif
throw(streamException(fstream::rdstate()));
}
return 0;
}
/***********************************************************/
// Read a string from the store. Use internal buffer.
/***********************************************************/
int
unixf_storage::readString(mmdb_pos_t loc, char* base, int len, int str_off)
{
_open(ios::in);
int offset = int(loc) + str_off;
seekg( offset, ios::beg );
if ( bad() ) {
MESSAGE(cerr, "seekg failed");
throw(streamException(fstream::rdstate()));
}
read( base, len );
if ( bad() || len != fstream::gcount() ) {
MESSAGE(cerr, "read() failed");
throw(streamException(fstream::rdstate()));
}
return 0;
}
/***********************************************************/
// Write a string to the store. Use external buffer.
/***********************************************************/
int unixf_storage::updateString(mmdb_pos_t loc, const char* base, int len, int string_ofst, Boolean flush_opt)
{
/*
debug(cerr, len);
debug(cerr, loc);
debug(cerr, int(base));
debug(cerr, string_ofst);
debug(cerr, int(flush_opt));
*/
/*
fprintf(stderr, "updateString():");
fprintf(stderr, "len=%d, ", len);
fprintf(stderr, "loc=%d, ", loc);
fprintf(stderr, "string_ofst=%d, ", string_ofst);
fprintf(stderr, "flush option=%d\n", flush_opt);
*/
_open(ios::out);
#ifdef C_API
if ( ! seekg(loc+string_ofst, ios::beg) ) {
MESSAGE(cerr, form("seek() failed on %s", my_name()));
throw(streamException(fstream::rdstate()));
}
#else
if ( ! seekp(loc+string_ofst, ios::beg) ) {
MESSAGE(cerr, form("seek() failed on %s", my_name()));
throw(streamException(fstream::rdstate()));
}
#endif
if ( ! write( base, len ) ) {
#ifdef DEBUG
fprintf(stderr, "write() failed on %s @ %s:%d\n",
my_name(), __FILE__, __LINE__);
#endif
throw(streamException(fstream::rdstate()));
}
if ( flush_opt == true )
flush();
#ifdef DEBUG
fprintf(stderr, "%d bytes have been written at offset %ld in %s/%s @ %s:%d\n", len, loc+string_ofst, path, name, __FILE__, __LINE__);
#ifndef C_API
{
char fname[64];
snprintf(fname, sizeof(fname), "%s.%ld-%d", name, loc+string_ofst, len);
ofstream output(fname);
output.write(base, len);
output.flush();
}
#endif
#endif
if ( !(*this) ) {
#ifdef DEBUG
fprintf(stderr, "write() failed on %s @ %s:%d\n",
my_name(), __FILE__, __LINE__);
#endif
throw(streamException(fstream::rdstate()));
}
total_bytes = MAX(total_bytes, int(loc)+len);
return 0;
}
/***********************************************************/
// insert a string.
/***********************************************************/
int unixf_storage::appendString(mmdb_pos_t, const char* base, int len, Boolean flush_opt)
{
mmdb_pos_t loc = bytes();
updateString(loc, base, len, 0, flush_opt);
return 0;
}
/***********************************************************/
// Return the number of bytes in the store.
/***********************************************************/
int unixf_storage::bytes()
{
if ( total_bytes == -1 ) {
#ifdef C_API
_open(ios::in);
if ( !good() )
clear();
total_bytes = ::bytes(rdbuf() -> fd());
#else
char* info_lib_file = form("%s/%s", path, name);
total_bytes = ::bytes(info_lib_file);
#endif
}
return total_bytes;
}
Boolean unixf_storage::io_mode(int test_mode)
{
Boolean opened = false;
if ( fstream::rdbuf() -> is_open() ) {
opened = true ;
fstream::close();
}
#ifdef C_API
fstream::open(name, test_mode);
#else
fstream::open(name, (ios_base::openmode)test_mode);
#endif
// fstream::open(name, test_mode, open_file_prot());
if ( ! fstream::rdbuf() -> is_open() )
return false;
else {
fstream::close();
if ( opened == true )
#ifdef C_API
fstream::open(name, mode, open_file_prot());
#else
fstream::open(name, (ios_base::openmode)mode);
#endif
// fstream::open(name, mode, open_file_prot());
return true;
}
}
int unixf_storage::truncate(int target_length_in_bytes)
{
char *fmt = NULL;
_open(ios::out);
if ( total_bytes > target_length_in_bytes ) {
fmt = ::form("%s/%s", path, name);
if ( ::truncate((const char *) fmt, target_length_in_bytes) != 0 ) {
throw(systemException(errno));
}
total_bytes = target_length_in_bytes;
}
return 0;
}