Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtinfo / DtMmdb / oliasdb / user_base.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 librararies 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 /*
24  * $XConsortium: user_base.cc /main/8 1996/08/15 14:13:12 cde-hal $
25  *
26  * Copyright (c) 1992 HAL Computer Systems International, Ltd.
27  * All rights reserved.  Unpublished -- rights reserved under
28  * the Copyright Laws of the United States.  USE OF A COPYRIGHT
29  * NOTICE IS PRECAUTIONARY ONLY AND DOES NOT IMPLY PUBLICATION
30  * OR DISCLOSURE.
31  * 
32  * THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE
33  * SECRETS OF HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.  USE,
34  * DISCLOSURE, OR REPRODUCTION IS PROHIBITED WITHOUT THE
35  * PRIOR EXPRESS WRITTEN PERMISSION OF HAL COMPUTER SYSTEMS
36  * INTERNATIONAL, LTD.
37  * 
38  *                         RESTRICTED RIGHTS LEGEND
39  * Use, duplication, or disclosure by the Government is subject
40  * to the restrictions as set forth in subparagraph (c)(l)(ii)
41  * of the Rights in Technical Data and Computer Software clause
42  * at DFARS 252.227-7013.
43  *
44  *          HAL COMPUTER SYSTEMS INTERNATIONAL, LTD.
45  *                  1315 Dell Avenue
46  *                  Campbell, CA  95008
47  * 
48  */
49
50
51
52 #include "oliasdb/user_base.h"
53 #include "oliasdb/mark.h"
54 #include "utility/debug.h"
55 #include "misc/unique_id.h"
56
57 #define LOCK_DIR "lock"
58 #define AT_LOCK "at_lock"
59 #define W_LOCK "w_lock"
60 #define ACCESS_INFO "access_info"
61
62 extern void_ptr_array g_store_array;
63 extern Boolean g_transaction_on;
64
65 extern int g_mode_8_3;
66
67 user_base::user_base( const char* spec_path, rw_flag_t rw) : 
68    spec_name(spec_path), backup_file(0), rw_flag(rw), first_desc_ptr(0),
69    base(0)
70 {
71    g_mode_8_3 = 1;
72
73    f_obj_dict = new object_dict;
74
75    char* path = getenv("DTINFO_USER_DB") ;
76
77    if ( path == 0 ) {
78        char* home = getenv("HOME");
79        char* lang = getenv("LANG");
80
81        if ( home == 0 )
82           throw(stringException("HOME unspecified"));
83        if ( lang == 0 )
84           throw(stringException("LANG unknown"));
85
86        path = form("%s/.dt/dtinfo/%s", home, lang);
87    }
88
89    char* name = getenv("USER");
90
91    if ( name == 0 )
92       name = "";
93
94    strcpy(base_path, path);
95    strcpy(base_name, name);
96    strcpy(base_desc, "");
97
98    _init();
99
100 }
101
102
103 user_base::user_base( const char* base_dir, 
104                       const char* base_nm,
105                       const char* base_ds,
106                       const char* spec_path,
107                       rw_flag_t rw 
108                     ) : 
109         base(0, 0, 0, base_dir, base_nm, base_ds, ""), first_desc_ptr(0),
110         backup_file(0), rw_flag(rw), checking_status(SUCC),
111         spec_name(spec_path)
112 {
113    g_mode_8_3 = 1;
114
115    f_obj_dict = new object_dict;
116
117    _init();
118 }
119
120 user_base::checking_status_t user_base::check_mode()
121 {
122    try {
123
124      switch ( rw_flag ) {
125          case user_base::READ:
126         {
127            if ( exist_dir(base_path) == false ) {
128               return user_base::FAIL;
129            }
130            break;
131         }
132          case user_base::WRITE:
133         {
134            if ( check_and_create_dir(base_path) == false ) {
135               return user_base::FAIL;
136            }
137            break;
138         }
139      }
140    }
141
142    catch (systemException&, e)
143       {
144          return user_base::FAIL;
145       }
146    end_try;
147
148    if ( exist_file(SCHEMA_FILE, base_path) == true ) 
149       return user_base::SUCC;
150
151    if ( exist_file(form("%s.%s", base_name, SCHEMA_FILE_SUFFIX), base_path) == true ) 
152       return user_base::SUCC;
153
154    return user_base::NO_BASE;
155 }
156
157 user_base::checking_status_t user_base::check_lock()
158 {
159    char lock_dir[PATHSIZ];
160
161    sprintf(lock_dir, "%s/%s", base_path, LOCK_DIR);
162
163    if ( check_and_create_dir(lock_dir) == false ) {
164       MESSAGE(cerr, form("no write permission to %s", lock_dir));
165       return user_base::CREATE_LOCKFILE_FAIL;
166    }
167
168    strcpy(atomic_lock_path, form("%s/%s", lock_dir, AT_LOCK));
169    strcpy(write_lock_path, form("%s/%s", lock_dir, W_LOCK));
170    strcpy(ai_path, form("%s/%s", lock_dir, ACCESS_INFO));
171
172    char* ai_info = 0;
173
174    switch (rw_flag) {
175      case user_base::READ:
176
177         if (
178          read_lock(atomic_lock_path, write_lock_path, 
179                    ai_path, access_info("read"), offset, ai_info
180                   ) == false
181            ) {
182             if ( ai_info ) {
183               debug(cerr, ai_info); 
184               delete ai_info;
185             }
186             return user_base::RLOCK_FAIL;
187         } else
188            return user_base::SUCC;
189         break;
190  
191      case user_base::WRITE:
192
193          if (
194           write_lock(atomic_lock_path, write_lock_path, 
195                     ai_path, access_info("write"), ai_info
196                    ) == false
197          ) {
198              if ( ai_info ) {
199                 debug(cerr, ai_info); 
200              
201 //
202 //                int x = strlen(ai_info);
203 //                if ( x >= 5 && strncmp(ai_info + x - 5, "read", 4) == 0 )
204 //                {
205 //                   rw_flag = user_base::READ;
206 //                   MESSAGE(cerr, "write locking failed, try read mode");
207 //                   int ok = check_lock();
208 //                   delete ai_info;
209 //                   return ok;
210 //                }
211
212                 delete ai_info;
213              }
214              return user_base::WLOCK_FAIL;
215          } else {
216             return user_base::SUCC;
217          }
218         break;
219
220      default:
221          abort();
222    }
223 }
224
225
226 void user_base::_init()
227 {
228   set_mode(HEALTH, true);
229   
230   checking_status = check_mode();
231
232   MESSAGE(cerr, "Initial mode");
233   debug(cerr, checking_status);
234
235   first_desc_ptr = 0;
236
237   switch ( checking_status ) {
238
239     case user_base::NO_BASE:
240
241        if ( disk_space(base_path) < 10*KB ) {
242            checking_status = user_base::FAIL;
243            break;
244        }
245
246        try
247          {
248            ubase_trans.begin();
249
250            define();
251
252            ubase_trans.sync();
253            ubase_trans.end();
254    
255          }
256
257        catch (beginTransException &,e)
258          {
259 // cases: can't open log or write size info to log
260            checking_status = user_base::FAIL;
261            clean_up();
262            break;
263          }
264        catch (commitTransException &,e)
265          {
266 // cases: bad log file, can't write to store, etc.
267            checking_status = user_base::FAIL;
268            clean_up();
269            break;
270          }
271 // cases: can't do define()
272        catch (mmdbException &,e)
273          {
274            checking_status = user_base::FAIL;
275            ubase_trans.rollback(); 
276            ubase_trans.abort();
277            clean_up();
278            break;
279
280          }
281        end_try;
282        
283        checking_status = check_mode();
284        break;
285
286     case user_base::SUCC:
287
288        try {
289           ubase_trans.begin();
290
291           first_desc_ptr = f_obj_dict -> init_a_base(base_path, base_name);
292
293           ubase_trans.end();
294        }
295
296        catch (mmdbException &,e) {
297 #ifdef DEBUG
298           fprintf(stderr, "mmdbException caught @ %s line:%d.\n",
299                                                 __FILE__, __LINE__);
300 #endif
301           ubase_trans.abort();
302
303           set_mode(HEALTH, false);
304           checking_status = user_base::FAIL;
305           break;
306        } end_try;
307
308        break;
309
310     default:
311        set_mode(HEALTH, false);
312        break;
313   }
314   
315 #ifndef NO_DB_LOCK
316   if ( checking_status == user_base::SUCC ) {
317      checking_status = check_lock();
318      debug(cerr, checking_status);
319      if ( checking_status != user_base::SUCC ) {
320        set_mode(HEALTH, false);
321        return;
322      }
323   }
324 #endif
325   
326
327   MESSAGE(cerr, "Final mode"); debug(cerr, checking_status);
328
329   switch ( checking_status ) {
330
331     case user_base::SUCC:
332       set_mode(HEALTH, true);
333       MESSAGE(cerr, form("userbase \"%s\" available", base_name));
334       break;
335
336     default:
337       set_mode(HEALTH, false);
338       break;
339   }
340
341   return;
342 }
343
344 user_base::~user_base()
345 {
346    if ( checking_status == user_base::SUCC &&
347         exist_dir(form("%s/%s", base_path, LOCK_DIR)) == true ) 
348    {
349
350 #ifndef NO_DB_LOCK
351    switch (rw_flag) {
352      case user_base::READ:
353         read_unlock(atomic_lock_path, ai_path, offset);
354         break;
355      case user_base::WRITE:
356         write_unlock(atomic_lock_path, write_lock_path, ai_path);
357              );
358         break;
359    }
360 #endif
361    }
362
363   delete f_obj_dict;
364 }
365
366 void user_base::clean_up()
367 {
368    abs_storage* store_ptr = 0;
369    desc* desc_ptr = first_desc_ptr;
370
371    while ( desc_ptr ) {
372         store_ptr = desc_ptr -> get_store();
373
374         if ( store_ptr ) {
375           try {
376 /*
377 MESSAGE(cerr, "removing: ");
378 MESSAGE(cerr, store_ptr -> my_name());
379 */
380                store_ptr->remove();
381           }
382           catch (mmdbException &,e)
383           {
384           } end_try;
385         }
386         desc_ptr = desc_ptr -> get_next_desc();
387    }
388
389    if ( exist_file(SCHEMA_FILE, base_path) == true )
390       del_file(SCHEMA_FILE, base_path);
391 }
392
393 Boolean user_base::define()
394 {
395    if ( check_and_create_dir(base_path) == false ) {
396       throw(stringException(form("can't create %s", base_path))); 
397    }
398
399    char spec_file_path[PATHSIZ];
400
401    //char* x = getenv("DTINFO_LIB");
402    char* x = getenv("DTINFO_MARKSPECPATH");
403
404    if ( x == 0 ) {
405        strcpy(spec_file_path, spec_name);
406    } 
407    else
408        strcpy(spec_file_path, form("%s/%s", x, spec_name));
409    
410    if (exist_file(spec_file_path) == false) {
411        
412       debug(cerr, spec_file_path);
413
414       throw(stringException(
415           form("missing %s. can't define user_base", spec_file_path)
416                            )
417            );
418    }
419  
420 /*
421    char unique_nm[PATHSIZ];
422    strcpy(unique_nm, form("%s.%s", base_name, unique_id()));
423 */
424
425    first_desc_ptr = 
426      f_obj_dict -> init_a_base(spec_file_path, base_path, base_name);
427
428    return true;
429 }
430