tt_old_db: use TT_DB_OK instead of NULL
[oweals/cde.git] / cde / lib / tt / lib / db / tt_old_db.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 //%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                  
24 //%%  (c) Copyright 1993, 1994 International Business Machines Corp.    
25 //%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                   
26 //%%  (c) Copyright 1993, 1994 Novell, Inc.                             
27 //%%  $XConsortium: tt_old_db.C /main/3 1995/10/23 10:05:40 rswiston $                                                  
28 /*
29  * tt_old_db.cc - Defines the old TT DB server database.
30  *
31  * Copyright (c) 1992 by Sun Microsystems, Inc.
32  */
33
34 #include <string.h>
35 #include <sys/errno.h>
36 #include <sys/stat.h>
37 #include <sys/types.h>
38 #include <netinet/in.h>
39
40 #include "api/c/tt_c.h"
41 #include "util/tt_port.h"
42 #include "util/tt_gettext.h"
43 #include "db/tt_old_db_consts.h"
44 #include "db/tt_old_db_results.h"
45 #include "db/tt_old_db.h"
46 #include "db/tt_db_create_objid.h"
47 #include "db/tt_db_property.h"
48 #include "db/tt_db_access.h"
49
50 _Tt_old_db::
51 _Tt_old_db()
52 {
53   propertyTableFD = 0;
54   dbResults = TT_DB_OK;
55 }
56
57 _Tt_old_db::_Tt_old_db (const _Tt_string        &partition,
58                         const _Tt_db_client_ptr &db_conn)
59 {
60   connectToDB(partition, db_conn);
61 }
62
63 void _Tt_old_db::connectToDB (const _Tt_string        &partition,
64                               const _Tt_db_client_ptr &db_conn)
65 {
66   dbResults = TT_DB_OK;
67   dbPartition = partition;
68   dbHostname = db_conn->getHostname();
69
70   _Tt_string base_dir = partition;
71   if (base_dir[base_dir.len()-1] != '/') {
72     base_dir = base_dir.cat("/");
73   }
74   base_dir = base_dir.cat("TT_DB/");
75
76   _Tt_string file_table_file(TT_OLD_DB_FILE_TABLE_FILE);
77   file_table_file = base_dir.cat(file_table_file);
78
79   _Tt_string file_object_map_file(TT_OLD_DB_FILE_OBJECT_MAP_FILE);
80   file_object_map_file = base_dir.cat(file_object_map_file);
81
82   _Tt_string property_table_file(TT_OLD_DB_PROPERTY_TABLE_FILE);
83   property_table_file = base_dir.cat(property_table_file);
84
85   _Tt_string access_table_file(TT_OLD_DB_ACCESS_TABLE_FILE);
86   access_table_file = base_dir.cat(access_table_file);
87
88   // Create key descriptor for the file key in the file table
89   fileTableFileKey = new _Tt_client_isam_key_descriptor;
90   fileTableFileKey->addKeyPart(TT_OLD_DB_FIRST_KEY_OFFSET,
91                                TT_OLD_DB_KEY_LENGTH,
92                                BINTYPE);
93
94   fileTable = new _Tt_client_isam_file(file_table_file,
95                                 TT_OLD_DB_KEY_LENGTH+MAXPATHLEN,
96                                 TT_OLD_DB_KEY_LENGTH+TT_OLD_DB_MAX_KEY_LENGTH,
97                                 fileTableFileKey,
98                                 ISVARLEN+ISINOUT+ISEXCLLOCK,
99                                 db_conn);
100   dbLastFileAccessed = fileTable->getName();
101   int results = fileTable->getErrorStatus();
102
103   // Create key descriptor for the file path in the file table
104   fileTableFilePathKey = new _Tt_client_isam_key_descriptor;
105   fileTableFilePathKey->addKeyPart(TT_OLD_DB_FILE_PATH_OFFSET,
106                                    TT_OLD_DB_MAX_KEY_LENGTH,
107                                    CHARTYPE);
108
109   // If this is new file add the key as an index
110   if (!results && fileTable->isNew()) {
111     (void)fileTable->addIndex(fileTableFilePathKey);
112     (void)fileTable->writeMagicString(_Tt_string(TT_OLD_DB_VERSION));
113   }
114   else if (results) {
115     dbResults = TT_DB_ERR_DB_OPEN_FAILED;
116   }
117   else {
118     _Tt_string version = fileTable->readMagicString();
119     if (version != _Tt_string(TT_OLD_DB_VERSION)) {
120       dbResults = TT_DB_ERR_DB_OPEN_FAILED;
121
122       _tt_syslog(0, LOG_ERR,
123                  catgets(_ttcatd, 1, 6,
124                          "server version (%s) does not"
125                          "match the version of the database tables (%s). "
126                          "Please run a version %s database server"),
127                  (char *)TT_OLD_DB_VERSION, (char *)version, (char *)version);
128     }
129   }
130
131   if (dbResults == TT_DB_OK) {
132     // Create key descriptor for the object key in the file-object map
133     fileObjectMapObjectKey = new _Tt_client_isam_key_descriptor;
134     fileObjectMapObjectKey->addKeyPart(TT_OLD_DB_FIRST_KEY_OFFSET,
135                                        TT_OLD_DB_KEY_LENGTH,
136                                        BINTYPE);
137
138     fileObjectMap = new _Tt_client_isam_file(file_object_map_file,
139                                       2*TT_OLD_DB_KEY_LENGTH,
140                                       2*TT_OLD_DB_KEY_LENGTH,
141                                       fileObjectMapObjectKey,
142                                       ISFIXLEN+ISINOUT+ISEXCLLOCK,
143                                       db_conn);
144     dbLastFileAccessed = fileObjectMap->getName();
145     results = fileObjectMap->getErrorStatus();
146
147     // Create key descriptor for the file key in the file-object map
148     fileObjectMapFileKey = new _Tt_client_isam_key_descriptor;
149     fileObjectMapFileKey->addKeyPart(TT_OLD_DB_SECOND_KEY_OFFSET,
150                                      TT_OLD_DB_KEY_LENGTH,
151                                      BINTYPE);
152     fileObjectMapFileKey->setDuplicates(TRUE);
153
154     // If this is new file add the key as an index
155     if (!results && fileObjectMap->isNew()) {
156       (void)fileObjectMap->addIndex(fileObjectMapFileKey);
157       (void)fileObjectMap->writeMagicString(_Tt_string(TT_OLD_DB_VERSION));
158     }
159     else if (results) {
160       dbResults = TT_DB_ERR_DB_OPEN_FAILED;
161     }
162   }
163
164   if (dbResults == TT_DB_OK) {
165     // Create key descriptor for the object key and property name in
166     // the property table
167     propertyTablePropertyKey = new _Tt_client_isam_key_descriptor;
168     propertyTablePropertyKey->addKeyPart(TT_OLD_DB_FIRST_KEY_OFFSET,
169                                          TT_OLD_DB_KEY_LENGTH,
170                                          BINTYPE);
171     propertyTablePropertyKey->addKeyPart(TT_OLD_DB_PROPERTY_NAME_OFFSET,
172                                          TT_OLD_DB_MAX_PROPERTY_NAME_LENGTH,
173                                          CHARTYPE);
174     propertyTablePropertyKey->setDuplicates(TRUE);
175
176     propertyTable =
177       new _Tt_client_isam_file(property_table_file,
178                         ISMAXRECLEN,
179                         TT_OLD_DB_KEY_LENGTH+TT_OLD_DB_MAX_PROPERTY_NAME_LENGTH,
180                         propertyTablePropertyKey,
181                         ISVARLEN+ISINOUT+ISEXCLLOCK,
182                         db_conn);
183     propertyTableFD = propertyTable->getFileDescriptor();
184     dbLastFileAccessed = propertyTable->getName();
185     results = propertyTable->getErrorStatus();
186
187     if (!results && propertyTable->isNew()) {
188       (void)propertyTable->writeMagicString(_Tt_string(TT_OLD_DB_VERSION));
189     }
190     else if (results) {
191       dbResults = TT_DB_ERR_DB_OPEN_FAILED;
192     }
193   }
194
195   if (dbResults == TT_DB_OK) {
196     // Create the key descriptor for the object key in the access table
197     accessTableKey = new _Tt_client_isam_key_descriptor;
198     accessTableKey->addKeyPart(TT_OLD_DB_FIRST_KEY_OFFSET,
199                                TT_OLD_DB_KEY_LENGTH,
200                                BINTYPE);
201
202     accessTable = new _Tt_client_isam_file(access_table_file,
203                                     TT_OLD_DB_KEY_LENGTH+3*TT_OLD_DB_SHORT_SIZE,
204                                     TT_OLD_DB_KEY_LENGTH+3*TT_OLD_DB_SHORT_SIZE,
205                                     accessTableKey,
206                                     ISFIXLEN+ISINOUT+ISEXCLLOCK,
207                                     db_conn);
208     dbLastFileAccessed = accessTable->getName();
209     results = accessTable->getErrorStatus();
210
211     if (!results && accessTable->isNew()) {
212       (void)accessTable->writeMagicString(_Tt_string(TT_OLD_DB_VERSION));
213     }
214     else if (results) {
215       dbResults = TT_DB_ERR_DB_OPEN_FAILED;
216     }
217   }
218 }
219
220 _Tt_old_db::~_Tt_old_db ()
221 {
222 }
223
224 _Tt_db_results _Tt_old_db::createFile (const _Tt_string        &file,
225                                              const _Tt_db_access_ptr &access)
226 {
227   _Tt_db_key_ptr file_key = new _Tt_db_key;
228
229   _Tt_client_isam_record_ptr record_ptr = fileTable->getEmptyRecord();
230   record_ptr->setKeyPartValue(0, 0, file_key->binary());
231   record_ptr->setBytes(TT_OLD_DB_FILE_PATH_OFFSET, file);
232
233   int results = fileTable->writeRecord(record_ptr);
234   dbLastFileAccessed = fileTable->getName();
235
236   if (!results) {
237     dbResults = TT_DB_OK;
238
239     _Tt_string file_key_bytes(TT_OLD_DB_KEY_LENGTH);
240     memcpy((char *)file_key_bytes,
241            (char *)file_key->binary(),
242            TT_OLD_DB_KEY_LENGTH);
243     if (setAccess(file_key_bytes, access) != TT_DB_OK) {
244       dbResults = TT_DB_ERR_CORRUPT_DB;
245     }
246   }
247   else if (results == EDUPL) {
248     dbResults = TT_DB_ERR_FILE_EXISTS;
249   }
250   else if (results == ELOCKED) {
251     dbResults = TT_DB_ERR_DB_LOCKED;
252   }
253   else if (results == ENOSPC) {
254     dbResults = TT_DB_ERR_DISK_FULL;
255   }
256   else {
257     dbResults = TT_DB_ERR_CORRUPT_DB;
258   }
259
260   return dbResults;
261 }
262
263 _Tt_db_results
264 _Tt_old_db::createObject (const _Tt_string        &file,
265                                 const _Tt_string        &objid,
266                                 const _Tt_db_access_ptr &object_access,
267                                 const _Tt_db_access_ptr &file_access)
268 {
269   _Tt_string file_key;
270
271   // If a file has been specified, get the key
272   _Tt_string        real_file;
273   if (!file.len()) {
274     real_file = TT_OLD_DB_FORWARD_POINTER_FILE;
275   }
276   else {
277     real_file = file;
278   }
279
280   dbResults = getFileKey(real_file, file_key);
281
282   // If the file does not exist...
283   if (dbResults == TT_DB_ERR_NO_SUCH_FILE) {
284     _Tt_db_access_ptr real_file_access;
285     if (!file.len()) {
286       real_file_access = new _Tt_db_access;
287       real_file_access->user = 0;
288       real_file_access->group = 0;
289       real_file_access->mode = (mode_t)-1;
290     }
291     else {
292       real_file_access = file_access;
293     }
294
295     // Create the file
296     dbResults = createFile(real_file, real_file_access);
297
298     if (dbResults == TT_DB_OK) {
299       // Get the new file key
300       dbResults = getFileKey(real_file, file_key);
301     }
302
303     if (dbResults != TT_DB_OK) {
304       return dbResults;
305     }
306   }
307   // Else, if some sort of fatal error
308   else if (dbResults != TT_DB_OK) {
309     return dbResults;
310   }
311   
312   // Verify access to the file
313   if (verifyAccess(file_key, object_access, TRUE) != TT_DB_OK) {
314     return dbResults;
315   }
316
317   if (dbResults == TT_DB_OK) {
318     _Tt_string object_key = getObjectKey(objid);
319     int        results;
320
321     // Write a record to the file-object map
322     _Tt_client_isam_record_ptr record_ptr = fileObjectMap->getEmptyRecord();
323     record_ptr->setKeyPartValue(0, 0, object_key);
324     record_ptr->setKeyPartValue(1, 0, file_key);
325     results = fileObjectMap->writeRecord(record_ptr);
326     dbLastFileAccessed = fileObjectMap->getName();
327
328     if (!results) {
329       if (setAccess(object_key, object_access) != TT_DB_OK) {
330         dbResults = TT_DB_ERR_CORRUPT_DB;
331       }
332     }
333     else if (results == EDUPL) {
334       dbResults = TT_DB_ERR_OBJECT_EXISTS;
335     }
336     else if (results == ELOCKED) {
337       dbResults = TT_DB_ERR_DB_LOCKED;
338     }
339     else if (results == ENOSPC) {
340       dbResults = TT_DB_ERR_DISK_FULL;
341     }
342     else {
343       dbResults = TT_DB_ERR_CORRUPT_DB;
344     }
345   }
346
347   return dbResults;
348 }
349
350 _Tt_db_results _Tt_old_db::removeFile (const _Tt_string        &file,
351                                              const _Tt_db_access_ptr &access)
352 {
353   _Tt_string file_key;
354   if (getFileKey(file, file_key) != TT_DB_OK) {
355     return dbResults;
356   }
357
358   if (verifyAccess(file_key, access, TRUE, TRUE) != TT_DB_OK) {
359     return dbResults;
360   }
361
362   _Tt_string_list_ptr objids;
363
364   // Find and remove the file's objects
365   dbResults = getFileObjects(file, access, objids);
366   if (dbResults == TT_DB_OK) {
367     _Tt_string_list_cursor objids_cursor(objids);
368     while (objids_cursor.next()) {
369       dbResults = removeObject(*objids_cursor, access);
370     }
371   }
372   else {
373     return dbResults;
374   }
375   
376   if (dbResults == TT_DB_OK) {
377     dbResults = deleteProperties(file_key);
378     
379     if (dbResults == TT_DB_OK) {
380       // Remove the file from the file table
381       _Tt_client_isam_record_ptr key_record = fileTable->getEmptyRecord();
382       key_record->setKeyPartValue(0, 0, file_key);
383       long record_number = fileTable->getLastRecordNumber();
384       int results = fileTable->deleteRecord(record_number, key_record);
385       dbLastFileAccessed = fileTable->getName();
386
387       if (!results) {
388         // Reposition the access table at the file's access record
389         if (verifyAccess(file_key, access, TRUE, TRUE) != TT_DB_OK) {
390           return dbResults;
391         }
392
393         // Remove the file's access info
394         record_number = accessTable->getLastRecordNumber();
395         results = accessTable->deleteRecord(record_number, key_record);
396         dbLastFileAccessed = accessTable->getName();
397       }
398
399       if (results) {
400         dbResults = TT_DB_ERR_CORRUPT_DB;
401       }
402     }
403   }
404
405   return dbResults;
406 }
407
408 _Tt_db_results _Tt_old_db::removeObject (const _Tt_string        &objid,
409                                                const _Tt_db_access_ptr &access)
410 {
411   _Tt_string object_key = getObjectKey(objid);
412   if (verifyUserOnlyObjectAccess (object_key, access) != TT_DB_OK) {
413     return dbResults;
414   }
415
416   dbResults = deleteProperties(object_key);
417
418   if (dbResults == TT_DB_OK) {
419     _Tt_client_isam_record_ptr record_ptr = fileObjectMap->getEmptyRecord();
420     record_ptr->setKeyPartValue(0, 0, object_key);
421
422     // Position the file just before the object in the file-object map
423     int results = fileObjectMap->findStartRecord(fileObjectMapObjectKey,
424                                                  0,
425                                                  record_ptr,
426                                                  ISEQUAL);
427     dbLastFileAccessed = fileObjectMap->getName();
428  
429     if (!results) {
430       // Read the object record
431       (void)fileObjectMap->readRecord(ISNEXT);
432       results = fileObjectMap->getErrorStatus();
433
434       if (!results) {
435         // Delete the record
436         _Tt_client_isam_record_ptr key_record =
437                                    fileObjectMap->getEmptyRecord();
438         key_record->setKeyPartValue(0, 0, object_key);
439         long record_number = fileObjectMap->getLastRecordNumber();
440         results = fileObjectMap->deleteRecord(record_number, key_record);
441  
442         if (!results) {
443           // Delete the object's access info
444           record_number = accessTable->getLastRecordNumber();
445           results = accessTable->deleteRecord(record_number, key_record);
446           dbLastFileAccessed = accessTable->getName();
447         }
448  
449         if (results) {
450           dbResults = TT_DB_ERR_CORRUPT_DB;
451         }
452       }
453       else {
454         dbResults = TT_DB_ERR_CORRUPT_DB;
455       }
456     }
457     else {
458       dbResults = TT_DB_ERR_CORRUPT_DB;
459     }    
460   }
461
462   return dbResults;
463 }
464
465 _Tt_db_results
466 _Tt_old_db::setFileProperty (const _Tt_string          &file,
467                                    const _Tt_db_property_ptr &property,
468                                    const _Tt_db_access_ptr   &access)
469 {
470   _Tt_string file_key;
471   if (getFileKey(file, file_key) != TT_DB_OK) {
472     return dbResults;
473   }
474
475   if (verifyAccess(file_key, access, TRUE) != TT_DB_OK) {
476     return dbResults;
477   }
478
479   return setProperty(file_key, property);
480 }
481
482 _Tt_db_results _Tt_old_db
483 ::setFileProperties (const _Tt_string               &file,
484                      const _Tt_db_property_list_ptr &properties,
485                      const _Tt_db_access_ptr        &access)
486 {
487   _Tt_string file_key;
488   if (getFileKey(file, file_key) != TT_DB_OK) {
489     return dbResults;
490   }
491
492   if (verifyAccess(file_key, access, TRUE) != TT_DB_OK) {
493     return dbResults;
494   }
495
496   return setProperties(file_key, properties);
497 }
498
499 _Tt_db_results
500 _Tt_old_db::addFileProperty (const _Tt_string          &file,
501                                    const _Tt_db_property_ptr &property,
502                                    bool_t                     unique,
503                                    const _Tt_db_access_ptr   &access)
504 {
505   _Tt_string file_key;
506   if (getFileKey(file, file_key) != TT_DB_OK) {
507     return dbResults;
508   }
509
510   if (verifyAccess(file_key, access, TRUE) != TT_DB_OK) {
511     return dbResults;
512   }
513
514   return addProperty(file_key, property, unique);
515 }
516
517 _Tt_db_results
518 _Tt_old_db::deleteFileProperty (const _Tt_string          &file,
519                                       const _Tt_db_property_ptr &property,
520                                       const _Tt_db_access_ptr   &access)
521 {
522   _Tt_string file_key;
523   if (getFileKey(file, file_key) != TT_DB_OK) {
524     return dbResults;
525   }
526
527   if (verifyAccess(file_key, access, TRUE) != TT_DB_OK) {
528     return dbResults;
529   }
530
531   return deleteProperty(file_key, property);
532 }
533
534 _Tt_db_results
535 _Tt_old_db::deleteFileProperties (const _Tt_string        &file,
536                                         const _Tt_db_access_ptr &access)
537 {
538   _Tt_string file_key;
539   if (getFileKey(file, file_key) != TT_DB_OK) {
540     return dbResults;
541   }
542
543   if (verifyAccess(file_key, access, TRUE) != TT_DB_OK) {
544     return dbResults;
545   }
546
547   return deleteProperties(file_key);
548 }
549
550 _Tt_db_results
551 _Tt_old_db::getFileProperty (const _Tt_string        &file,
552                                    const _Tt_string        &name,
553                                    const _Tt_db_access_ptr &access,
554                                    _Tt_db_property_ptr     &property)
555 {
556   property = (_Tt_db_property *)NULL;
557
558   _Tt_string file_key;
559   if (getFileKey(file, file_key) != TT_DB_OK) {
560     return dbResults;
561   }
562
563   if (verifyAccess(file_key, access) != TT_DB_OK) {
564     return dbResults;
565   }
566
567   return getProperty(file_key, name, property);
568 }
569
570 _Tt_db_results _Tt_old_db
571 ::getFileProperties (const _Tt_string         &file,
572                      const _Tt_db_access_ptr  &access,
573                      _Tt_db_property_list_ptr &properties)
574 {
575   properties = (_Tt_db_property_list *)NULL;
576
577   _Tt_string file_key;
578   if (getFileKey(file, file_key) != TT_DB_OK) {
579     return dbResults;
580   }
581
582   if (verifyAccess(file_key, access) != TT_DB_OK) {
583     return dbResults;
584   }
585
586   return getProperties(file_key, properties);
587 }
588
589 _Tt_db_results
590 _Tt_old_db::getFileObjects (const _Tt_string        &file,
591                                   const _Tt_db_access_ptr &access,
592                                   _Tt_string_list_ptr     &objids)
593 {
594   objids = (_Tt_string_list *)NULL;
595
596   _Tt_string file_key;
597   if (getFileKey(file, file_key) != TT_DB_OK) {
598     return dbResults;
599   }
600
601   if (verifyAccess(file_key, access) != TT_DB_OK) {
602     return dbResults;
603   }
604
605   _Tt_client_isam_record_ptr record_ptr = fileObjectMap->getEmptyRecord();
606   record_ptr->setKeyPartValue(1, 0, file_key);
607
608   // Position just before record with the specified file key in the
609   // file-object map
610   int results = fileObjectMap->findStartRecord(fileObjectMapFileKey,
611                                                0,
612                                                record_ptr,
613                                                ISEQUAL);
614   dbLastFileAccessed = (char *)fileObjectMap->getName();
615
616   if (results == ENOREC) {
617     dbResults = TT_DB_OK;
618   }
619   else if (results) {
620     dbResults = TT_DB_ERR_CORRUPT_DB;
621   }
622   else if (!results) {
623     for (;;) {
624       // Read the next file record
625       record_ptr = fileObjectMap->readRecord(ISNEXT);
626       results = fileObjectMap->getErrorStatus();
627
628       if (!results) {
629         // Extract the file key from the record just read
630         _Tt_string file_key_bytes = record_ptr->getKeyPartValue(1, 0);
631
632         // If the extracted key doesn't match the specified key,
633         // then there are no more records with this key value,
634         // therefore break out of the loop...
635         if (file_key != file_key_bytes) {
636           dbResults = TT_DB_OK;
637           break;
638         }
639         // Else the file record matches...
640         else {
641           // Extract the object key bytes and create a key object
642           _Tt_string object_key_bytes = record_ptr->getKeyPartValue(0, 0);
643           _Tt_db_key_ptr object_key = new _Tt_db_key(object_key_bytes);
644
645           // Construct the actual object ID
646           _Tt_string objid = _tt_db_create_objid(object_key,
647                                                  "NFS",
648                                                  dbHostname,
649                                                  dbPartition);
650           if (objids.is_null()) {
651             objids = new _Tt_string_list;
652           }
653           objids->append(objid);
654         }
655       }
656       // Else if no more records match the file key...
657       else if ((results == ENOREC) || (results == EENDFILE)) {
658         dbResults = TT_DB_OK;
659         break;
660       }
661       else if (results) {
662         dbResults = TT_DB_ERR_CORRUPT_DB;
663         break;
664       }
665     }
666   }
667
668   return dbResults;
669 }
670                                
671 _Tt_db_results
672 _Tt_old_db::deleteFileObjects (const _Tt_string        &file,
673                                      const _Tt_db_access_ptr &access)
674 {
675   _Tt_string file_key;
676   if (getFileKey(file, file_key) != TT_DB_OK) {
677     return dbResults;
678   }
679
680   if (verifyAccess(file_key, access, TRUE) != TT_DB_OK) {
681     return dbResults;
682   }
683
684   // Gets the object IDs, loop through them, and remove them...
685   _Tt_string_list_ptr objids;
686   if (getFileObjects(file, access, objids) == TT_DB_OK) {
687     _Tt_string_list_cursor objids_cursor(objids);
688     while (objids_cursor.next() && (dbResults == TT_DB_OK)) {
689       dbResults = removeObject(*objids_cursor, access);
690     }
691   }
692
693   return dbResults;
694 }
695
696 _Tt_db_results
697 _Tt_old_db::setFileFile (const _Tt_string        &file,
698                                const _Tt_string        &new_file,
699                                const _Tt_db_access_ptr &access)
700 {
701   if (file == new_file) {
702     return TT_DB_ERR_SAME_FILE;
703   }
704
705   _Tt_string file_key;
706
707   // Use the "getFileKey" to position the current record of the
708   // file table  on the record to update.
709   if (getFileKey(file, file_key) != TT_DB_OK) {
710     return dbResults;
711   }
712
713   if (verifyAccess(file_key, access, TRUE) != TT_DB_OK) {
714     return dbResults;
715   }
716
717   // Re-read the current file-object map record
718   _Tt_client_isam_record_ptr record_ptr;
719   record_ptr = fileTable->readRecord(ISCURR);
720   int results = fileTable->getErrorStatus();
721
722   if (!results) {
723     // Get a clean record
724     _Tt_client_isam_record_ptr new_record = fileTable->getEmptyRecord();
725
726     // Put the file key into the new record
727     record_ptr->setKeyPartValue(0, 0, file_key);
728
729     // Put the new file into the record
730     record_ptr->setBytes(TT_OLD_DB_FILE_PATH_OFFSET, new_file);
731
732     // Update the current file table record with the new info
733     long record_number = fileTable->getLastRecordNumber();
734     results = fileTable->updateRecord(record_number, record_ptr);
735   }
736
737   if (results) {
738     dbResults = TT_DB_ERR_CORRUPT_DB;
739   }
740
741   return dbResults;
742 }
743
744 _Tt_db_results
745 _Tt_old_db::getFileChildren (const _Tt_string    &file,
746                                    _Tt_string_list_ptr &children)
747 {
748   int results;
749
750   // Construct the root path for finding children files
751   _Tt_string root_path = file;
752   root_path = root_path.cat("/");
753
754   children = new _Tt_string_list;
755
756   // Use the "getFileKey" to position the the file table on the first
757   // record that matches our file and to see if the file exists
758   // in the database.
759   _Tt_string file_key;
760   dbResults = getFileKey(file, file_key);
761   if (dbResults == TT_DB_OK) {
762     children->append(file);
763   }
764   else if (dbResults == TT_DB_ERR_NO_SUCH_FILE) {
765     dbResults = TT_DB_OK;
766
767     // Position the file at the first record that has the file name
768     // as the root of its path
769     _Tt_client_isam_record_ptr record_ptr = fileTable->getEmptyRecord();
770     record_ptr->setKeyPartValue(1, 0, root_path);
771
772     results =
773       fileTable->findStartRecord(fileTableFilePathKey,
774                                  ((root_path.len() < TT_OLD_DB_MAX_KEY_LENGTH) ?
775                                   root_path.len() : TT_OLD_DB_MAX_KEY_LENGTH),
776                                  record_ptr,
777                                  ISEQUAL);
778     dbLastFileAccessed = fileTable->getName();
779
780     if (results == ENOREC) {
781       dbResults = TT_DB_ERR_NO_SUCH_FILE;
782     }
783     else if (results) {
784       dbResults = TT_DB_ERR_CORRUPT_DB;
785     }
786   }
787
788   if (dbResults == TT_DB_OK) {
789     _Tt_client_isam_record_ptr record_ptr;
790
791     // Loop through the children files
792     results = 0;
793     while (!results) {
794       record_ptr = fileTable->readRecord(ISNEXT);
795       results = fileTable->getErrorStatus();
796
797       if (!results) {
798         _Tt_string child = record_ptr->getBytes(TT_OLD_DB_FILE_PATH_OFFSET, 0);
799
800         // Make sure the record just read contains a child of the root path
801         if (!strncmp((char *)root_path, (char *)child, root_path.len())) {
802           children->append(_Tt_string((char *)child));
803         }
804         // Else, no more children left...
805         else {
806           results = ENOREC;
807         }
808       }
809     }
810
811     if ((results == ENOREC) || (results == EENDFILE)) {
812       dbResults = TT_DB_OK;
813     }
814     else {
815       dbResults = TT_DB_ERR_CORRUPT_DB;
816     }
817   }
818
819   return dbResults;
820 }
821
822 _Tt_db_results
823 _Tt_old_db::setFileAccess (const _Tt_string        &file,
824                                  const _Tt_db_access_ptr &new_access,
825                                  const _Tt_db_access_ptr &access)
826 {
827   _Tt_string file_key;
828   if (getFileKey(file, file_key) != TT_DB_OK) {
829     return dbResults;
830   }
831
832   (void)verifyAccess(file_key, access, TRUE, TRUE);
833   if ((dbResults != TT_DB_OK) && (dbResults != TT_DB_ERR_NO_ACCESS_INFO)) {
834     return dbResults;
835   }
836   
837   return setAccess(file_key, new_access);
838 }
839
840 _Tt_db_results
841 _Tt_old_db::getFileAccess (const _Tt_string        &file,
842                                  const _Tt_db_access_ptr &access,
843                                  _Tt_db_access_ptr       &current_access)
844 {
845   current_access = (_Tt_db_access *)NULL;
846
847   _Tt_string file_key;
848   if (getFileKey(file, file_key) != TT_DB_OK) {
849     return dbResults;
850   }
851
852   if (verifyAccess(file_key, access) != TT_DB_OK) {
853     return dbResults;
854   }
855
856   return getAccess(file_key, current_access);
857 }
858
859 _Tt_db_results
860 _Tt_old_db::setObjectProperty (const _Tt_string          &objid,
861                                      const _Tt_db_property_ptr &property,
862                                      const _Tt_db_access_ptr   &access)
863 {
864   _Tt_string object_key = getObjectKey(objid);
865   if (verifyObjectAccess(object_key, access, TRUE) != TT_DB_OK) {
866     return dbResults;
867   }
868
869   return setProperty(object_key, property);
870 }
871
872 _Tt_db_results _Tt_old_db
873 ::setObjectProperties (const _Tt_string               &objid,
874                        const _Tt_db_property_list_ptr &properties,
875                        const _Tt_db_access_ptr        &access)
876 {
877   _Tt_string object_key = getObjectKey(objid);
878   if (verifyObjectAccess(object_key, access, TRUE) != TT_DB_OK) {
879     return dbResults;
880   }
881
882   return setProperties(object_key, properties);
883 }
884
885 _Tt_db_results
886 _Tt_old_db::addObjectProperty (const _Tt_string          &objid,
887                                      const _Tt_db_property_ptr &property,
888                                      bool_t                     unique,
889                                      const _Tt_db_access_ptr   &access)
890 {
891   _Tt_string object_key = getObjectKey(objid);
892   if (verifyObjectAccess(object_key, access, TRUE) != TT_DB_OK) {
893     return dbResults;
894   }
895
896   return addProperty(object_key, property, unique);
897 }
898
899 _Tt_db_results
900 _Tt_old_db::deleteObjectProperty (const _Tt_string          &objid,
901                                         const _Tt_db_property_ptr &property,
902                                         const _Tt_db_access_ptr   &access)
903 {
904   _Tt_string object_key = getObjectKey(objid);
905   if (verifyObjectAccess(object_key, access, TRUE) != TT_DB_OK) {
906     return dbResults;
907   }
908
909   return deleteProperty(object_key, property);
910 }
911
912 _Tt_db_results
913 _Tt_old_db::deleteObjectProperties (const _Tt_string        &objid,
914                                           const _Tt_db_access_ptr &access)
915 {
916   _Tt_string object_key = getObjectKey(objid);
917   if (verifyObjectAccess(object_key, access, TRUE) != TT_DB_OK) {
918     return dbResults;
919   }
920
921   return deleteProperties(object_key);
922 }
923
924 _Tt_db_results
925 _Tt_old_db::getObjectProperty (const _Tt_string        &objid,
926                                      const _Tt_string        &name,
927                                      const _Tt_db_access_ptr &access,
928                                      _Tt_db_property_ptr     &property)
929 {
930   property = (_Tt_db_property *)NULL;
931
932   _Tt_string object_key = getObjectKey(objid);
933   if (verifyObjectAccess(object_key, access) != TT_DB_OK) {
934     return dbResults;
935   }
936
937   return getProperty(object_key, name, property);
938 }
939
940 _Tt_db_results _Tt_old_db
941 ::getObjectProperties (const _Tt_string         &objid,
942                        const _Tt_db_access_ptr  &access,
943                        _Tt_db_property_list_ptr &properties)
944 {
945   properties = (_Tt_db_property_list *)NULL;
946
947   _Tt_string object_key = getObjectKey(objid);
948   if (verifyObjectAccess(object_key, access) != TT_DB_OK) {
949     return dbResults;
950   }
951
952   return getProperties(object_key, properties);
953 }
954
955 _Tt_db_results
956 _Tt_old_db::setObjectFile (const _Tt_string        &objid,
957                                  const _Tt_string        &file,
958                                  const _Tt_db_access_ptr &access)
959 {
960   _Tt_string object_key = getObjectKey(objid);
961   if (verifyObjectAccess(object_key, access) != TT_DB_OK) {
962     return dbResults;
963   }
964
965   // Use "getFile" to position the current record of the file-object
966   // map on the record to update.  Plus we need to get the old file
967   // name to make sure a move is really needed... 
968   _Tt_string old_file;
969   dbResults = getFile(object_key, old_file);
970
971   if (dbResults == TT_DB_OK) {
972     // If the names are the same, then the move is not needed...
973     if (old_file == file) {
974       dbResults = TT_DB_ERR_SAME_OBJECT;
975     }
976     // Else, the move is needed...
977     else {
978       // Re-read the current file-object map record
979       _Tt_client_isam_record_ptr record_ptr;
980       record_ptr = fileObjectMap->readRecord(ISCURR);
981       int results = fileObjectMap->getErrorStatus();
982
983       if (!results) {
984         // See if the file exists by trying to obtain its key
985         _Tt_string file_key;
986         dbResults = getFileKey(file, file_key);
987
988         // If the file key was found...
989         if (dbResults == TT_DB_OK) {
990           // Put the new file key into the record and update the table
991           record_ptr->setKeyPartValue(1, 0, file_key);
992           long record_number = fileObjectMap->getLastRecordNumber();
993           results = fileObjectMap->updateRecord(record_number, record_ptr);
994
995           if (results) {
996             dbResults = TT_DB_ERR_CORRUPT_DB;
997           }
998         }
999         // Else, the file is not in the DB...
1000         else if (dbResults == TT_DB_ERR_NO_SUCH_FILE) {
1001           // Create a new file using the permissions of the object
1002           _Tt_db_access_ptr object_access;
1003           dbResults = getAccess(object_key, object_access); 
1004
1005           if (dbResults == TT_DB_OK) {
1006             dbResults = createFile (file, object_access);
1007           }
1008
1009           if (dbResults == TT_DB_OK) {
1010             // Get the new file key
1011             if (getFileKey(file, file_key) == TT_DB_OK) {
1012               // Put the new file key into the record and update the table
1013               record_ptr->setKeyPartValue(1, 0, file_key);
1014               long record_number = fileObjectMap->getLastRecordNumber();
1015               results = fileObjectMap->updateRecord(record_number, record_ptr);
1016
1017               if (results) {
1018                 dbResults = TT_DB_ERR_CORRUPT_DB;
1019               }
1020             }
1021           }
1022         }
1023       }
1024       else {
1025         dbResults = TT_DB_ERR_CORRUPT_DB;
1026       }
1027     }
1028   }
1029
1030   return dbResults;
1031 }
1032
1033 _Tt_db_results
1034 _Tt_old_db::getObjectFile (const _Tt_string        &objid,
1035                                  const _Tt_db_access_ptr &access,
1036                                  _Tt_string              &file)
1037 {
1038   file = (char *)NULL;
1039
1040   _Tt_string object_key = getObjectKey(objid);
1041   if (verifyObjectAccess(object_key, access) != TT_DB_OK) {
1042     return dbResults;
1043   }
1044
1045   return getFile(object_key, file);
1046 }
1047
1048 _Tt_db_results
1049 _Tt_old_db::setObjectAccess (const _Tt_string        &objid,
1050                                    const _Tt_db_access_ptr &new_access,
1051                                    const _Tt_db_access_ptr &access)
1052 {
1053   _Tt_string object_key = getObjectKey(objid);
1054   (void)verifyObjectAccess(object_key, access, TRUE, TRUE);
1055   if ((dbResults != TT_DB_OK) && (dbResults != TT_DB_ERR_NO_ACCESS_INFO)) {
1056     return dbResults;
1057   }
1058
1059   return setAccess(object_key, new_access);
1060 }
1061
1062 _Tt_db_results
1063 _Tt_old_db::getObjectAccess (const _Tt_string        &objid,
1064                                    const _Tt_db_access_ptr &access,
1065                                    _Tt_db_access_ptr       &current_access)
1066 {
1067   current_access = (_Tt_db_access *)NULL;
1068
1069   _Tt_string object_key = getObjectKey(objid);
1070   if (verifyObjectAccess(object_key, access) != TT_DB_OK) {
1071     return dbResults;
1072   }
1073
1074   return getAccess(object_key, current_access);
1075 }
1076
1077 _Tt_db_results
1078 _Tt_old_db::verifyObjectAccess (const _Tt_string        &object_key,
1079                                       const _Tt_db_access_ptr &access,
1080                                       bool_t                   write,
1081                                       bool_t                   user_only)
1082 {
1083   dbResults = verifyAccess(object_key, access, write, user_only);
1084
1085   if (dbResults == TT_DB_ERR_NO_ACCESS_INFO) {
1086     _Tt_client_isam_record_ptr record_ptr = fileObjectMap->getEmptyRecord();
1087     record_ptr->setKeyPartValue(0, 0, object_key);
1088
1089     // Position the file just before the object in the file-object map
1090     int results = fileObjectMap->findStartRecord(fileObjectMapObjectKey,
1091                                                  0,
1092                                                  record_ptr,
1093                                                  ISEQUAL);
1094     dbLastFileAccessed = fileObjectMap->getName();
1095
1096     if (results == ENOREC) {
1097       dbResults = TT_DB_ERR_NO_SUCH_OBJECT;
1098     }
1099     else if (results) {
1100       dbResults = TT_DB_ERR_CORRUPT_DB;
1101     }
1102   }
1103
1104   return dbResults;
1105 }
1106
1107 _Tt_db_results _Tt_old_db
1108 ::verifyUserOnlyObjectAccess (const _Tt_string        &object_key,
1109                               const _Tt_db_access_ptr &access)
1110 {
1111   if (verifyAccess(object_key, access, TRUE, TRUE) != TT_DB_OK) {
1112     _Tt_string file;
1113     if (getFile(object_key, file) == TT_DB_OK) {
1114       _Tt_string file_key;
1115       if (getFileKey(file, file_key) == TT_DB_OK) {
1116         dbResults = verifyAccess(file_key, access, TRUE, TRUE);
1117       }
1118     }
1119   }  
1120
1121   return dbResults;
1122 }
1123
1124 _Tt_db_results
1125 _Tt_old_db::verifyAccess (const _Tt_string        &key,
1126                                 const _Tt_db_access_ptr &access,
1127                                 bool_t                   write,
1128                                 bool_t                   user_only)
1129 {
1130   _Tt_client_isam_record_ptr record_ptr = accessTable->getEmptyRecord();
1131   record_ptr->setKeyPartValue(0, 0, key);
1132
1133   // Position the file just before the specified key in the access table
1134   int results = accessTable->findStartRecord(accessTableKey,
1135                                              0,
1136                                              record_ptr,
1137                                              ISEQUAL);
1138   dbLastFileAccessed = accessTable->getName();
1139
1140   if (results == ENOREC) {
1141     dbResults = TT_DB_ERR_NO_ACCESS_INFO;
1142   }
1143   else if (results) {
1144     dbResults = TT_DB_ERR_CORRUPT_DB;
1145   }
1146   else {
1147     // Read the access record
1148     record_ptr = accessTable->readRecord(ISNEXT);
1149     results = accessTable->getErrorStatus();
1150     
1151     if (results) {
1152       dbResults = TT_DB_ERR_CORRUPT_DB;
1153     }
1154     else if (!results) {
1155       short n_user = *(short *)
1156                       ((char *)record_ptr->getRecord()+
1157                                TT_OLD_DB_ACCESS_USER_OFFSET);
1158       uid_t user = (uid_t)ntohs(n_user);
1159
1160       short n_group = *(short *)
1161                        ((char *)record_ptr->getRecord()+
1162                                 TT_OLD_DB_ACCESS_GROUP_OFFSET);
1163       gid_t group = (gid_t)ntohs(n_group);
1164
1165       short n_mode = *(short *)
1166                       ((char *)record_ptr->getRecord()+
1167                                TT_OLD_DB_ACCESS_MODE_OFFSET);
1168       mode_t mode = (mode_t)ntohs(n_mode);
1169
1170       // If the user in the DB is -1, all users match
1171       bool_t user_flag = FALSE;
1172       if (user == -1) {
1173         user_flag = TRUE;
1174       }
1175       else {
1176         if (user == access->user) {
1177           user_flag = TRUE;
1178         }
1179       }
1180
1181       // If the group in the DB is -1, all groups match
1182       bool_t group_flag = FALSE;
1183       if (group == -1) {
1184         group_flag = TRUE;
1185       }
1186       else {
1187         if (group == access->group) {
1188           group_flag = TRUE;
1189         }
1190       }
1191       
1192       dbResults = TT_DB_ERR_ACCESS_DENIED;
1193
1194       // Root can do everything
1195       if (access->user == 0) {
1196         return (dbResults = TT_DB_OK);
1197       }
1198       
1199       // User of object can do anything
1200       if (user_flag) {
1201         return (dbResults = TT_DB_OK);
1202       }
1203
1204       if (!user_only) {
1205         if (mode == (mode_t)-1) {
1206           return (dbResults = TT_DB_OK);
1207         }
1208
1209         if (group_flag && (dbResults != TT_DB_OK)) {
1210           if (write && (mode&S_IWGRP)) {
1211             return (dbResults = TT_DB_OK);
1212           }
1213           else if (mode&S_IRGRP) {
1214             return (dbResults = TT_DB_OK);
1215           }
1216         }
1217       
1218         if (dbResults != TT_DB_OK) {
1219           if (write && (mode&S_IWOTH)) {
1220             return (dbResults = TT_DB_OK);
1221           }
1222           else if (mode&S_IROTH) {
1223             return (dbResults = TT_DB_OK);
1224           }
1225         }
1226       }
1227     }
1228   }
1229
1230   return dbResults;
1231 }
1232
1233 _Tt_db_results _Tt_old_db::getFileKey (const _Tt_string &file,
1234                                              _Tt_string &file_key)
1235 {
1236   dbResults = TT_DB_OK;
1237
1238   _Tt_client_isam_record_ptr record_ptr = fileTable->getEmptyRecord();
1239   record_ptr->setKeyPartValue(1, 0, file);
1240
1241   // Position file just before record with specified file path in the
1242   // file table
1243   int results =
1244     fileTable->findStartRecord(fileTableFilePathKey,
1245                                ((file.len() < TT_OLD_DB_MAX_KEY_LENGTH) ?
1246                                 file.len() : TT_OLD_DB_MAX_KEY_LENGTH),
1247                                record_ptr,
1248                                ISEQUAL);
1249   dbLastFileAccessed = fileTable->getName();
1250
1251   if (results == ENOREC) {
1252     dbResults = TT_DB_ERR_NO_SUCH_FILE;
1253   }
1254   else if (results) {
1255     dbResults = TT_DB_ERR_CORRUPT_DB;
1256   }
1257   else {
1258     for (;;) {
1259       // Read the next record
1260       record_ptr = fileTable->readRecord(ISNEXT);
1261       results = fileTable->getErrorStatus();
1262
1263       if (!results) {
1264         // Extract the full file path from the record
1265         _Tt_string temp_file = (char *)
1266                                record_ptr->getBytes(TT_OLD_DB_FILE_PATH_OFFSET, 0);
1267
1268         // If the record file path matchs the specified file, then
1269         // we found our file, therefore break out of the loop...
1270         if (file == temp_file) {
1271           break;
1272         }
1273       }
1274       // No more records left, our file doesn't exist...
1275       else if ((results == ENOREC) || (results == EENDFILE)) {
1276         dbResults = TT_DB_ERR_NO_SUCH_FILE;
1277         break;
1278       }
1279       else {
1280         dbResults = TT_DB_ERR_CORRUPT_DB;
1281         break;
1282       }
1283     }
1284
1285     if (dbResults == TT_DB_OK) {
1286       // Extract the file key
1287       file_key = record_ptr->getKeyPartValue(0, 0);
1288     }
1289   }
1290
1291   return dbResults;
1292 }
1293
1294 _Tt_string _Tt_old_db::getObjectKey (const _Tt_string &objid)
1295 {
1296   // Create a key object from the specified object ID
1297   _Tt_db_key_ptr object_key = new _Tt_db_key(objid);
1298
1299   // Write the binary key to a return buffer
1300   _Tt_string object_key_bytes(TT_OLD_DB_KEY_LENGTH);
1301   memcpy((char *)object_key_bytes,
1302          (char *)object_key->binary(),
1303          TT_OLD_DB_KEY_LENGTH);
1304
1305   return object_key_bytes;
1306 }
1307
1308 _Tt_db_results _Tt_old_db::addPropertyValue(const _Tt_string &key,
1309                                                   const _Tt_string &name,
1310                                                   const _Tt_string &value)
1311 {
1312   dbResults = TT_DB_OK;
1313
1314   _Tt_client_isam_record_ptr record_ptr = propertyTable->getEmptyRecord();
1315   record_ptr->setKeyPartValue(0, 0, key);
1316   record_ptr->setKeyPartValue(0, 1, name);
1317
1318   record_ptr->setBytes(TT_OLD_DB_PROPERTY_VALUE_OFFSET, value);
1319   record_ptr->setLength(TT_OLD_DB_PROPERTY_VALUE_OFFSET+value.len());
1320
1321   int results = propertyTable->writeRecord(record_ptr);
1322   dbLastFileAccessed = propertyTable->getName();
1323
1324   if (results == ENOSPC) {
1325     dbResults = TT_DB_ERR_DISK_FULL;
1326   }
1327   else if (results == ELOCKED) {
1328     dbResults = TT_DB_ERR_DB_LOCKED;
1329   }
1330   else if (results == (int)TT_OLD_DB_ACCESS_DENIED) {
1331     dbResults = TT_DB_ERR_ACCESS_DENIED;
1332   }
1333   else if (results) {
1334     dbResults = TT_DB_ERR_CORRUPT_DB;
1335   }
1336
1337   return dbResults;
1338 }
1339
1340 _Tt_db_results
1341 _Tt_old_db::setProperty (const _Tt_string          &key,
1342                                const _Tt_db_property_ptr &property)
1343 {
1344   _Tt_db_property_ptr temp_property = new _Tt_db_property;
1345   temp_property->name = property->name;
1346   (void)deleteProperty(key, temp_property);
1347
1348   return addProperty(key, property, FALSE);
1349 }
1350
1351 _Tt_db_results
1352 _Tt_old_db::setProperties (const _Tt_string               &key,
1353                                  const _Tt_db_property_list_ptr &properties)
1354 {
1355   dbResults = deleteProperties(key, TRUE);
1356
1357   _Tt_db_property_list_cursor properties_cursor(properties);
1358   while (properties_cursor.next()) {
1359     dbResults = setProperty(key, *properties_cursor);
1360   }
1361
1362   return dbResults;
1363 }
1364
1365 _Tt_db_results
1366 _Tt_old_db::addProperty (const _Tt_string          &key,
1367                                const _Tt_db_property_ptr &property,
1368                                bool_t                     unique)
1369 {
1370   dbResults = TT_DB_OK;
1371
1372   _Tt_client_isam_record_ptr record_ptr;
1373   _Tt_string          temp_string;
1374
1375   _Tt_string_list_cursor values_cursor(property->values);
1376   while (values_cursor.next() && (dbResults == TT_DB_OK)) {
1377     // If unique... therefore add the value to the property only if
1378     // the key, prop name and prop value combo does not already exist...
1379     if (unique) {
1380       record_ptr = propertyTable->getEmptyRecord();
1381       record_ptr->setKeyPartValue(0, 0, key);
1382       record_ptr->setKeyPartValue(0, 1, property->name);
1383   
1384       // Position the file just before the first record with the specified key
1385       // and property name value in the property table
1386       int results = propertyTable->findStartRecord(propertyTablePropertyKey,
1387                                                    0,
1388                                                    record_ptr,
1389                                                    ISEQUAL);
1390       dbLastFileAccessed = propertyTable->getName();
1391
1392       // No such property, add the value
1393       if (results == ENOREC) {
1394         dbResults = addPropertyValue(key, property->name, *values_cursor);
1395       }
1396       else if (results) {
1397         dbResults = TT_DB_ERR_CORRUPT_DB;
1398       }
1399       // Property exists, let's check on its values...
1400       else {
1401         bool_t found = FALSE;
1402         for (;;) {
1403           // Read the next record
1404           results = propertyTable->readRecord(ISNEXT, record_ptr);
1405
1406           if (!results) {
1407             // Extract the key from the record
1408             temp_string = record_ptr->getKeyPartValue(0, 0);
1409
1410             // If the key doesn't match, we're done looking for values...
1411             if (temp_string != key) {
1412               break;
1413             }
1414
1415             // Extract the property name from the record
1416             temp_string = record_ptr->getKeyPartValue(0, 1);
1417
1418             // If the property name doesn't match, we're done looking
1419             // for values.
1420             if (strcmp((char *)temp_string, (char *)property->name)) {
1421               break;
1422             }
1423
1424             // Extract the property value from the record
1425             temp_string = record_ptr->getBytes(TT_OLD_DB_PROPERTY_VALUE_OFFSET, 0);
1426
1427             // If the values are the same, the new property is not unique,
1428             // so let's leave...
1429             if (temp_string == *values_cursor) {
1430               found = TRUE;
1431               break;
1432             }
1433           }
1434           // No more records, the new value is unique...
1435           else if ((results == ENOREC) || (results == EENDFILE)) {
1436             break;
1437           }
1438           else if (results == (int)TT_OLD_DB_ACCESS_DENIED) {
1439             found = TRUE;
1440             dbResults = TT_DB_ERR_ACCESS_DENIED;
1441             break;
1442           }
1443           else {
1444             found = TRUE;
1445             dbResults = TT_DB_ERR_CORRUPT_DB;
1446             break;
1447           }
1448         }
1449
1450         // If the same value wasn't found, the new value is unique,
1451         // therefore add it...
1452         if (!found) {
1453           dbResults = addPropertyValue(key, property->name, *values_cursor);
1454         }
1455       }
1456     }
1457     // Else, who cares whether it's unique or not, just add it...
1458     else {
1459       dbResults = addPropertyValue(key, property->name, *values_cursor);
1460     }
1461   }
1462
1463   return dbResults;
1464 }
1465
1466 _Tt_db_results
1467 _Tt_old_db::deleteProperty (const _Tt_string          &key,
1468                                   const _Tt_db_property_ptr &property)
1469 {
1470   dbResults = TT_DB_OK;
1471
1472   _Tt_client_isam_record_ptr record_ptr = propertyTable->getEmptyRecord();
1473   record_ptr->setKeyPartValue(0, 0, key);
1474   record_ptr->setKeyPartValue(0, 1, property->name);
1475
1476   // Position the file just before the first record with the specified key
1477   // and property name value in the property table
1478   int results = propertyTable->findStartRecord(propertyTablePropertyKey,
1479                                                0,
1480                                                record_ptr,
1481                                                ISEQUAL);
1482   dbLastFileAccessed = propertyTable->getName();
1483
1484   bool_t found = FALSE;
1485   if (results == ENOREC) {
1486     dbResults = TT_DB_ERR_NO_SUCH_PROPERTY;
1487   }
1488   else if (results) {
1489     dbResults = TT_DB_ERR_CORRUPT_DB;
1490   }
1491   else {
1492     _Tt_string_list_cursor values_cursor(property->values);
1493     for (;;) {
1494       // Read the next record
1495       results = propertyTable->readRecord(ISNEXT, record_ptr);
1496
1497       // No more records, let's get out of here...
1498       if ((results == ENOREC) || (results == EENDFILE)) {
1499         break;
1500       }
1501       else if (results == (int)TT_OLD_DB_ACCESS_DENIED) {
1502         dbResults = TT_DB_ERR_ACCESS_DENIED;
1503         break;
1504       }
1505       else if (results) {
1506         dbResults = TT_DB_ERR_CORRUPT_DB;
1507         break;
1508       }
1509       else {
1510         // Extract the key from the record
1511         _Tt_string temp_string = record_ptr->getKeyPartValue(0, 0);
1512
1513         // If the key doesn't match, we're done looking for values...
1514         if (temp_string != key) {
1515           break;
1516         }
1517
1518         // Extract the property name from the record
1519         temp_string = record_ptr->getKeyPartValue(0, 1);
1520
1521         // If the property name doesn't match, we're done looking
1522         // for values.
1523         if (strcmp((char *)property->name, (char *)temp_string)) {
1524           break;
1525         }
1526         
1527         // If no specific values to delete were specified, delete all of
1528         // the values we find...
1529         if (property->is_empty()) {
1530           found = TRUE;
1531           long record_number = propertyTable->getLastRecordNumber();
1532           results = propertyTable->deleteRecord(record_number, record_ptr);
1533           if (results == (int)TT_OLD_DB_ACCESS_DENIED) {
1534             dbResults = TT_DB_ERR_ACCESS_DENIED;
1535             break;
1536           }
1537           else if (results) {
1538             dbResults = TT_DB_ERR_CORRUPT_DB;
1539             break;
1540           }
1541         }
1542         // Else specific values to delete have been specified...
1543         else {
1544           // Extract the property value from the record
1545           _Tt_string property_value =
1546             record_ptr->getBytes(TT_OLD_DB_PROPERTY_VALUE_OFFSET, 0);
1547
1548           // Loop through the specified values and see if any match
1549           // the value in the record.  If one matches, delete the
1550           // record...
1551           values_cursor.reset();  
1552           while (values_cursor.next()) {
1553             if (property_value == *values_cursor) {
1554               found = TRUE;
1555               long record_number = propertyTable->getLastRecordNumber();
1556               results = propertyTable->deleteRecord(record_number, record_ptr);
1557               break;
1558             }
1559           }
1560
1561           if (results == (int)TT_OLD_DB_ACCESS_DENIED) {
1562             dbResults = TT_DB_ERR_ACCESS_DENIED;
1563             break;
1564           }
1565           else if (results) {
1566             dbResults = TT_DB_ERR_CORRUPT_DB;
1567             break;
1568           }
1569         }
1570       }
1571     }
1572   }
1573
1574   if ((dbResults == TT_DB_OK) && (!found)) {
1575     dbResults = TT_DB_ERR_NO_SUCH_PROPERTY;
1576   }
1577
1578   return dbResults;
1579 }
1580
1581 _Tt_db_results _Tt_old_db
1582 ::deleteProperties (const _Tt_string &key,
1583                     bool_t            preserve_special_properties)
1584 {
1585   dbResults = TT_DB_OK;
1586
1587   _Tt_client_isam_record_ptr record_ptr = propertyTable->getEmptyRecord();
1588   record_ptr->setKeyPartValue(0, 0, key);
1589     
1590   // Position the file just before the record with the specified key in
1591   // the property table
1592   int results = propertyTable->findStartRecord(propertyTablePropertyKey,
1593                                                TT_OLD_DB_KEY_LENGTH,
1594                                                record_ptr,
1595                                                ISEQUAL);
1596   dbLastFileAccessed = propertyTable->getName();
1597
1598   _Tt_string temp_string;
1599   for (;;) {
1600     if (!results) {
1601       // Read the property record
1602       results = propertyTable->readRecord(ISNEXT, record_ptr);
1603
1604       if (!results) {
1605         // Extract the key from the record
1606         temp_string = record_ptr->getKeyPartValue(0, 0);
1607
1608         // If the key doesn't match, we're done looking for properties...
1609         if (temp_string != key) {
1610           break;
1611         }
1612
1613         // If we need to preserve special properties, i.e. object type
1614         // and cache level properties
1615         if (preserve_special_properties) {
1616           temp_string = record_ptr->getKeyPartValue(0, 1);
1617
1618           if (strcmp((char *)temp_string, TT_OLD_DB_PROPS_CACHE_LEVEL_PROPERTY) &&
1619               strcmp((char *)temp_string, TT_OLD_DB_OBJECT_TYPE_PROPERTY)) {
1620             long record_number = propertyTable->getLastRecordNumber();
1621             results = propertyTable->deleteRecord(record_number, record_ptr);
1622             if (results) {
1623               dbResults = TT_DB_ERR_CORRUPT_DB;
1624             }
1625           }
1626         }
1627         else {
1628           long record_number = propertyTable->getLastRecordNumber();
1629           results = propertyTable->deleteRecord(record_number, record_ptr);
1630           if (results == (int)TT_OLD_DB_ACCESS_DENIED) {
1631             dbResults = TT_DB_ERR_ACCESS_DENIED;
1632           }
1633           else if (results) {
1634             dbResults = TT_DB_ERR_CORRUPT_DB;
1635           }
1636         }
1637       }
1638     }
1639     else if ((results == EENDFILE) || (results == ENOREC)) {
1640       break;
1641     }
1642     else if (results == (int)TT_OLD_DB_ACCESS_DENIED) {
1643       dbResults = TT_DB_ERR_ACCESS_DENIED;
1644       break;
1645     }
1646     else {
1647       dbResults = TT_DB_ERR_CORRUPT_DB;
1648       break;
1649     }
1650   }
1651
1652   return dbResults;
1653 }
1654
1655 _Tt_db_results
1656 _Tt_old_db::getProperty (const _Tt_string    &key,
1657                                const _Tt_string    &name,
1658                                _Tt_db_property_ptr &property)
1659 {
1660   dbResults = TT_DB_OK;
1661
1662   _Tt_client_isam_record_ptr record_ptr = propertyTable->getEmptyRecord();
1663   record_ptr->setKeyPartValue(0, 0, key);
1664   record_ptr->setKeyPartValue(0, 1, name);
1665
1666   // Position the file just before the first record with the specified key
1667   // and property name value in the property table
1668   int results = propertyTable->findStartRecord(propertyTablePropertyKey,
1669                                                0,
1670                                                record_ptr,
1671                                                ISEQUAL);
1672   dbLastFileAccessed = (char *)propertyTable->getName();
1673
1674   if (results == ENOREC) {
1675     dbResults = TT_DB_ERR_NO_SUCH_PROPERTY;
1676   }
1677   else if (results) {
1678     dbResults = TT_DB_ERR_CORRUPT_DB;
1679   }
1680   else {
1681     // Create the object to return the property in
1682     property = new _Tt_db_property;
1683     property->name = name;
1684
1685     _Tt_string temp_string;
1686     for (;;) {
1687       // Read the next record
1688       results = propertyTable->readRecord(ISNEXT, record_ptr);
1689
1690       if (!results) {
1691         // Extract the key from the record
1692         temp_string = record_ptr->getKeyPartValue(0, 0);
1693
1694         // If the key does not match, we're done looking for values...
1695         if (temp_string != key) {
1696           break;
1697         }
1698         
1699         // Extract the property name from the record
1700         temp_string = record_ptr->getKeyPartValue(0, 1);
1701
1702         // If the property name doesn't match, we're done looking
1703         // for values.
1704         if (strcmp((char *)name, (char *)temp_string)) {
1705           break;
1706         }
1707         
1708         // Extract the property value from the record and append the
1709         // value to the object being returned
1710         temp_string = record_ptr->getBytes(TT_OLD_DB_PROPERTY_VALUE_OFFSET, 0);
1711         property->values->append(temp_string);
1712       }
1713       // No more records, we're done getting the property...
1714       else if ((results == ENOREC) || (results == EENDFILE)) {
1715         break;
1716       }
1717       else if (results == (int)TT_OLD_DB_ACCESS_DENIED) {
1718         dbResults = TT_DB_ERR_ACCESS_DENIED;
1719         break;
1720       }
1721       else {
1722         dbResults = TT_DB_ERR_CORRUPT_DB;
1723         break;
1724       }
1725     }
1726   }
1727
1728   return dbResults;
1729 }
1730
1731 _Tt_db_results
1732 _Tt_old_db::getProperties (const _Tt_string         &key,
1733                                  _Tt_db_property_list_ptr &properties)
1734 {
1735   dbResults = TT_DB_OK;
1736
1737   _Tt_client_isam_record_ptr record_ptr = propertyTable->getEmptyRecord();
1738   record_ptr->setKeyPartValue(0, 0, key);
1739
1740   // Position the file just before the first record with the specified key
1741   // in the property table
1742   int results = propertyTable->findStartRecord(propertyTablePropertyKey,
1743                                                TT_OLD_DB_KEY_LENGTH,
1744                                                record_ptr,
1745                                                ISEQUAL);
1746   dbLastFileAccessed = propertyTable->getName();
1747
1748   if (results && (results != ENOREC)) {
1749     dbResults = TT_DB_ERR_CORRUPT_DB;
1750   }
1751   else {
1752     _Tt_string name;
1753     _Tt_string value;
1754     _Tt_string temp_string;
1755     for (;;) {
1756       // Read the next record
1757       results = propertyTable->readRecord(ISNEXT, record_ptr);
1758
1759       if ((results == ENOREC) || (results == EENDFILE)) {
1760         break;
1761       }
1762       else if (results == (int)TT_OLD_DB_ACCESS_DENIED) {
1763         dbResults = TT_DB_ERR_ACCESS_DENIED;
1764         break;
1765       }
1766       else if (results) {
1767         dbResults = TT_DB_ERR_CORRUPT_DB;
1768         break;
1769       }
1770       else {
1771         // Extract the key from the record
1772         temp_string = record_ptr->getKeyPartValue(0, 0);
1773
1774         // If the key does not match, we're done looking for properties...
1775         if (temp_string != key) {
1776           break;
1777         }
1778         
1779         // Extract the property name and value from the reocrd
1780         name = record_ptr->getKeyPartValue(0, 1);
1781         value = record_ptr->getBytes(TT_OLD_DB_PROPERTY_VALUE_OFFSET, 0);
1782
1783         if (properties.is_null()) {
1784           properties = new _Tt_db_property_list;
1785         }
1786
1787         bool_t              found = FALSE;
1788         _Tt_db_property_ptr property;
1789
1790         // See if a property with same name is already in our return list...
1791         _Tt_db_property_list_cursor properties_cursor(properties);
1792         while (properties_cursor.next()) {
1793           // If the property exists, get the pointer to it...
1794           if (properties_cursor->name == name) {
1795             property = *properties_cursor;
1796             found = TRUE;
1797             break;
1798           }         
1799         }
1800
1801         // If there is no property with the same name in the list,
1802         // create a new property and it to the list...
1803         if (!found) {
1804           property = new _Tt_db_property;
1805           properties->append(property);
1806         }
1807
1808         // Append the value to the property
1809         property->name = name;
1810         property->values->append(value);
1811       }
1812     }
1813   }
1814
1815   return dbResults;
1816 }
1817
1818 _Tt_db_results _Tt_old_db::setAccess (const _Tt_string        &key,
1819                                             const _Tt_db_access_ptr &access)
1820 {
1821   dbResults = TT_DB_OK;
1822
1823   _Tt_client_isam_record_ptr record_ptr = accessTable->getEmptyRecord();
1824   record_ptr->setKeyPartValue(0, 0, key);
1825
1826   // Position the file just before the access info record for the key
1827   int results = accessTable->findStartRecord(accessTableKey,
1828                                              0,
1829                                              record_ptr,
1830                                              ISEQUAL);
1831   dbLastFileAccessed = accessTable->getName();
1832
1833   if (results == ENOREC) {
1834     *(short *)
1835      ((char *)record_ptr->getRecord()+
1836               TT_OLD_DB_ACCESS_USER_OFFSET) = htons((short)access->user);
1837     *(short *)
1838      ((char *)record_ptr->getRecord()+
1839               TT_OLD_DB_ACCESS_GROUP_OFFSET) = htons((short)access->group);
1840     *(short *)
1841      ((char *)record_ptr->getRecord()+
1842               TT_OLD_DB_ACCESS_MODE_OFFSET) = htons((short)access->mode);
1843  
1844     int results = accessTable->writeRecord(record_ptr);
1845     if (results == ENOSPC) {
1846       dbResults = TT_DB_ERR_DISK_FULL;
1847     }
1848     else if (results) {
1849       dbResults = TT_DB_ERR_CORRUPT_DB;
1850     }
1851   }
1852   else if (results) {
1853     dbResults = TT_DB_ERR_CORRUPT_DB;
1854   }
1855   else {
1856     // Read the access record
1857     record_ptr = accessTable->readRecord(ISNEXT);
1858     results = accessTable->getErrorStatus();
1859       
1860     if (results) {
1861       dbResults = TT_DB_ERR_CORRUPT_DB;
1862     }
1863     else if (!results) {
1864       *(short *)
1865        ((char *)record_ptr->getRecord()+
1866         TT_OLD_DB_ACCESS_USER_OFFSET) = htons((short)access->user);
1867       *(short *)
1868        ((char *)record_ptr->getRecord()+
1869                 TT_OLD_DB_ACCESS_GROUP_OFFSET) = htons((short)access->group);
1870       *(short *)
1871        ((char *)record_ptr->getRecord()+
1872                 TT_OLD_DB_ACCESS_MODE_OFFSET) = htons((short)access->mode);
1873
1874       // Update the record record that was read
1875       long record_number = accessTable->getLastRecordNumber();
1876       results = accessTable->updateRecord(record_number, record_ptr);
1877       dbResults = (results ? TT_DB_ERR_CORRUPT_DB : TT_DB_OK);
1878     }
1879   }
1880
1881   return dbResults;
1882 }
1883
1884 _Tt_db_results _Tt_old_db::getAccess (const _Tt_string  &key,
1885                                             _Tt_db_access_ptr &access)
1886 {
1887   _Tt_client_isam_record_ptr record_ptr = accessTable->getEmptyRecord();
1888   record_ptr->setKeyPartValue(0, 0, key);
1889
1890   // Position the file just before the access info record for the key
1891   int results = accessTable->findStartRecord(accessTableKey,
1892                                              0,
1893                                              record_ptr,
1894                                              ISEQUAL);
1895   dbLastFileAccessed = accessTable->getName();
1896
1897   if (results) {
1898     dbResults = TT_DB_ERR_CORRUPT_DB;
1899   }
1900   else {
1901     // Read the access record
1902     record_ptr = accessTable->readRecord(ISNEXT);
1903     results = accessTable->getErrorStatus();
1904     
1905     if (results) {
1906       dbResults = TT_DB_ERR_CORRUPT_DB;
1907     }
1908     else if (!results) {
1909       access = new _Tt_db_access;
1910
1911       short n_user = *(short *)
1912                       ((char *)record_ptr->getRecord()+
1913                                TT_OLD_DB_ACCESS_USER_OFFSET);
1914       access->user = (uid_t)ntohs(n_user);
1915
1916       short n_group = *(short *)
1917                        ((char *)record_ptr->getRecord()+
1918                                 TT_OLD_DB_ACCESS_GROUP_OFFSET);
1919       access->group = (gid_t)ntohl(n_group);
1920
1921       short n_mode = *(short *)
1922                       ((char *)record_ptr->getRecord()+
1923                                TT_OLD_DB_ACCESS_MODE_OFFSET);
1924       access->mode = (mode_t)ntohs(n_mode);
1925
1926       dbResults = TT_DB_OK;
1927     }
1928   }
1929
1930   return dbResults;
1931 }
1932
1933 _Tt_db_results _Tt_old_db::getFile (const _Tt_string &key,
1934                                     _Tt_string       &file) 
1935
1936   _Tt_client_isam_record_ptr record_ptr = fileObjectMap->getEmptyRecord();
1937   record_ptr->setKeyPartValue(0, 0, key);
1938  
1939   // Position the file just before the object in the file-object map
1940   int results = fileObjectMap->findStartRecord(fileObjectMapObjectKey,
1941                                                0,
1942                                                record_ptr,
1943                                                ISEQUAL);
1944   dbLastFileAccessed = fileObjectMap->getName();
1945  
1946   if (results) { 
1947     dbResults = TT_DB_ERR_CORRUPT_DB;
1948   }
1949   else { 
1950     // Read the object record
1951     record_ptr = fileObjectMap->readRecord(ISNEXT);
1952     results = fileObjectMap->getErrorStatus();
1953  
1954     if (!results) {
1955       // Extract the file key from the record
1956       _Tt_string file_key = record_ptr->getKeyPartValue(1, 0);
1957  
1958       record_ptr = fileTable->getEmptyRecord();
1959       record_ptr->setKeyPartValue(0, 0, file_key);
1960  
1961       // Position the file just before the file in the file table
1962       int results = fileTable->findStartRecord(fileTableFileKey,
1963                                                0,
1964                                                record_ptr,
1965                                                ISEQUAL);
1966       dbLastFileAccessed = fileTable->getName();
1967  
1968       if (results) {
1969         dbResults = TT_DB_ERR_CORRUPT_DB;
1970       }  
1971       else {
1972         // Read the file record
1973         record_ptr = fileTable->readRecord(ISNEXT);
1974         if (results) {    
1975           dbResults = TT_DB_ERR_CORRUPT_DB;
1976         }
1977         else {   
1978           // Extract the file path from the record
1979           file = record_ptr->getBytes(TT_OLD_DB_FILE_PATH_OFFSET, 0);
1980           dbResults = TT_DB_OK;
1981         }
1982       } 
1983     }    
1984     else {
1985       dbResults = TT_DB_ERR_CORRUPT_DB;
1986     }    
1987   }
1988     
1989   return dbResults;
1990 }