OpenIndiana and Solaris port
[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    base(0), backup_file(0), rw_flag(rw), first_desc_ptr(0),
69    spec_name(spec_path)
70 {
71    g_mode_8_3 = 1;
72    int len;
73
74    f_obj_dict = new object_dict;
75
76    char* path = getenv("DTINFO_USER_DB") ;
77
78    if ( path == 0 ) {
79        char* home = getenv("HOME");
80        char* lang = getenv("LANG");
81
82        if ( home == 0 )
83           throw(stringException("HOME unspecified"));
84        if ( lang == 0 )
85           throw(stringException("LANG unknown"));
86
87        path = form("%s/.dt/dtinfo/%s", home, lang);
88    }
89
90    char* name = getenv("USER");
91
92    if ( name == 0 )
93       name = (char*)"";
94
95    len = MIN(strlen(path), PATHSIZ - 1);
96    *((char *) memcpy(base_path, path, len) + len) = '\0';
97    len = MIN(strlen(name), PATHSIZ - 1);
98    *((char *) memcpy(base_name, name, len) + len) = '\0';
99    len = MIN(strlen(""), PATHSIZ - 1);
100    *((char *) memcpy(base_desc, "", len) + len) = '\0';
101
102    _init();
103
104 }
105
106
107 user_base::user_base( const char* base_dir, 
108                       const char* base_nm,
109                       const char* base_ds,
110                       const char* spec_path,
111                       rw_flag_t rw 
112                     ) : 
113         base(0, 0, 0, base_dir, base_nm, base_ds, ""), backup_file(0),
114         rw_flag(rw), checking_status(SUCC), first_desc_ptr(0),
115         spec_name(spec_path)
116 {
117    g_mode_8_3 = 1;
118
119    f_obj_dict = new object_dict;
120
121    _init();
122 }
123
124 user_base::checking_status_t user_base::check_mode()
125 {
126    mtry {
127
128      switch ( rw_flag ) {
129          case user_base::READ:
130         {
131            if ( exist_dir(base_path) == false ) {
132               return user_base::FAIL;
133            }
134            break;
135         }
136          case user_base::WRITE:
137         {
138            if ( check_and_create_dir(base_path) == false ) {
139               return user_base::FAIL;
140            }
141            break;
142         }
143      }
144    }
145
146    mcatch (systemException&, e)
147       {
148          return user_base::FAIL;
149       }
150    end_try;
151
152    if ( exist_file(SCHEMA_FILE, base_path) == true ) 
153       return user_base::SUCC;
154
155    if ( exist_file(form("%s.%s", base_name, SCHEMA_FILE_SUFFIX), base_path) == true ) 
156       return user_base::SUCC;
157
158    return user_base::NO_BASE;
159 }
160
161 user_base::checking_status_t user_base::check_lock()
162 {
163    char lock_dir[PATHSIZ];
164    int len;
165
166    snprintf(lock_dir, sizeof(lock_dir), "%s/%s", base_path, LOCK_DIR);
167
168    if ( check_and_create_dir(lock_dir) == false ) {
169       MESSAGE(cerr, form("no write permission to %s", lock_dir));
170       return user_base::CREATE_LOCKFILE_FAIL;
171    }
172
173    len = MIN(strlen(atomic_lock_path), strlen(lock_dir) + strlen(AT_LOCK) + 1);
174    *((char *) memcpy(atomic_lock_path,
175                      form("%s/%s", lock_dir, AT_LOCK), len) + len) = '\0';
176    len = MIN(strlen(write_lock_path), strlen(lock_dir) + strlen(W_LOCK) + 1);
177    *((char *) memcpy(write_lock_path,
178                      form("%s/%s", lock_dir, W_LOCK), len) + len) = '\0';
179    len = MIN(strlen(ai_path), strlen(lock_dir) + strlen(ACCESS_INFO) + 1);
180    *((char *) memcpy(ai_path,
181                      form("%s/%s", lock_dir, ACCESS_INFO), len) + len) = '\0';
182
183    char* ai_info = 0;
184
185    switch (rw_flag) {
186      case user_base::READ:
187
188         if (
189          read_lock(atomic_lock_path, write_lock_path, 
190                    ai_path, access_info((char*)"read"), offset, ai_info
191                   ) == false
192            ) {
193             if ( ai_info ) {
194               debug(cerr, ai_info); 
195               delete ai_info;
196             }
197             return user_base::RLOCK_FAIL;
198         } else
199            return user_base::SUCC;
200         break;
201  
202      case user_base::WRITE:
203
204          if (
205           write_lock(atomic_lock_path, write_lock_path, 
206                     ai_path, access_info((char*)"write"), ai_info
207                    ) == false
208          ) {
209              if ( ai_info ) {
210                 debug(cerr, ai_info); 
211              
212 //
213 //                int x = strlen(ai_info);
214 //                if ( x >= 5 && strncmp(ai_info + x - 5, "read", 4) == 0 )
215 //                {
216 //                   rw_flag = user_base::READ;
217 //                   MESSAGE(cerr, "write locking failed, try read mode");
218 //                   int ok = check_lock();
219 //                   delete ai_info;
220 //                   return ok;
221 //                }
222
223                 delete ai_info;
224              }
225              return user_base::WLOCK_FAIL;
226          } else {
227             return user_base::SUCC;
228          }
229         break;
230
231      default:
232          abort();
233    }
234 }
235
236
237 void user_base::_init()
238 {
239   set_mode(HEALTH, true);
240   
241   checking_status = check_mode();
242
243   MESSAGE(cerr, "Initial mode");
244   debug(cerr, checking_status);
245
246   first_desc_ptr = 0;
247
248   switch ( checking_status ) {
249
250     case user_base::NO_BASE:
251
252        if ( disk_space(base_path) < 10*KB ) {
253            checking_status = user_base::FAIL;
254            break;
255        }
256
257        mtry
258          {
259            ubase_trans.begin();
260
261            define();
262
263            ubase_trans.sync();
264            ubase_trans.end();
265    
266          }
267
268        mcatch (beginTransException &,e)
269          {
270 // cases: can't open log or write size info to log
271            checking_status = user_base::FAIL;
272            clean_up();
273            break;
274          }
275        mcatch (commitTransException &,e)
276          {
277 // cases: bad log file, can't write to store, etc.
278            checking_status = user_base::FAIL;
279            clean_up();
280            break;
281          }
282 // cases: can't do define()
283        mcatch (mmdbException &,e)
284          {
285            checking_status = user_base::FAIL;
286            ubase_trans.rollback(); 
287            ubase_trans.abort();
288            clean_up();
289            break;
290
291          }
292        end_try;
293        
294        checking_status = check_mode();
295        break;
296
297     case user_base::SUCC:
298
299        mtry {
300           ubase_trans.begin();
301
302           first_desc_ptr = f_obj_dict -> init_a_base(base_path, base_name);
303
304           ubase_trans.end();
305        }
306
307        mcatch (mmdbException &,e) {
308 #ifdef DEBUG
309           fprintf(stderr, "mmdbException caught @ %s line:%d.\n",
310                                                 __FILE__, __LINE__);
311 #endif
312           ubase_trans.abort();
313
314           set_mode(HEALTH, false);
315           checking_status = user_base::FAIL;
316           break;
317        } end_try;
318
319        break;
320
321     default:
322        set_mode(HEALTH, false);
323        break;
324   }
325   
326 #ifndef NO_DB_LOCK
327   if ( checking_status == user_base::SUCC ) {
328      checking_status = check_lock();
329      debug(cerr, checking_status);
330      if ( checking_status != user_base::SUCC ) {
331        set_mode(HEALTH, false);
332        return;
333      }
334   }
335 #endif
336   
337
338   MESSAGE(cerr, "Final mode"); debug(cerr, checking_status);
339
340   switch ( checking_status ) {
341
342     case user_base::SUCC:
343       set_mode(HEALTH, true);
344       MESSAGE(cerr, form("userbase \"%s\" available", base_name));
345       break;
346
347     default:
348       set_mode(HEALTH, false);
349       break;
350   }
351
352   return;
353 }
354
355 user_base::~user_base()
356 {
357    if ( checking_status == user_base::SUCC &&
358         exist_dir(form("%s/%s", base_path, LOCK_DIR)) == true ) 
359    {
360
361 #ifndef NO_DB_LOCK
362    switch (rw_flag) {
363      case user_base::READ:
364         read_unlock(atomic_lock_path, ai_path, offset);
365         break;
366      case user_base::WRITE:
367         write_unlock(atomic_lock_path, write_lock_path, ai_path);
368              );
369         break;
370    }
371 #endif
372    }
373
374   delete f_obj_dict;
375 }
376
377 void user_base::clean_up()
378 {
379    abs_storage* store_ptr = 0;
380    desc* desc_ptr = first_desc_ptr;
381
382    while ( desc_ptr ) {
383         store_ptr = desc_ptr -> get_store();
384
385         if ( store_ptr ) {
386           mtry {
387 /*
388 MESSAGE(cerr, "removing: ");
389 MESSAGE(cerr, store_ptr -> my_name());
390 */
391                store_ptr->remove();
392           }
393           mcatch (mmdbException &,e)
394           {
395           } end_try;
396         }
397         desc_ptr = desc_ptr -> get_next_desc();
398    }
399
400    if ( exist_file(SCHEMA_FILE, base_path) == true )
401       del_file(SCHEMA_FILE, base_path);
402 }
403
404 Boolean user_base::define()
405 {
406    int len;
407
408    if ( check_and_create_dir(base_path) == false ) {
409       throw(stringException(form("can't create %s", base_path))); 
410    }
411
412    char spec_file_path[PATHSIZ];
413
414    //char* x = getenv("DTINFO_LIB");
415    char* x = getenv("DTINFO_MARKSPECPATH");
416
417    if ( x == 0 ) {
418        len = MIN(strlen(spec_name), PATHSIZ - 1);
419        *((char *) memcpy(spec_file_path, spec_name, len) + len) = '\0';
420    } 
421    else {
422        len = MIN(strlen(x) + strlen(spec_name) + 1, PATHSIZ - 1);
423        *((char *) memcpy(spec_file_path,
424                          form("%s/%s", x, spec_name), len) + len) = '\0';
425    }
426    
427    if (exist_file(spec_file_path) == false) {
428        
429       debug(cerr, spec_file_path);
430
431       throw(stringException(
432           form("missing %s. can't define user_base", spec_file_path)
433                            )
434            );
435    }
436  
437 /*
438    char unique_nm[PATHSIZ];
439    const char* uid;
440    uid = unique_id();
441    len = MIN(strlen(base_name) + strlen(uid) + 1, PATHSIZ - 1);
442    *((char *) memcpy(unique_nm,
443                      form("%s.%s", base_name, uid), len) + len) = '\0';
444 */
445
446    first_desc_ptr = 
447      f_obj_dict -> init_a_base(spec_file_path, base_path, base_name);
448
449    return true;
450 }
451