1 /*
2  * Motif
3  *
4  * Copyright (c) 1987-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 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 
28 #ifdef REV_INFO
29 #ifndef lint
30 static char rcsid[] = "$XConsortium: MrmItop.c /main/15 1996/11/13 13:58:55 drk $"
31 #endif
32 #endif
33 
34 
35 /*
36  *++
37  *  FACILITY:
38  *
39  *      UIL Resource Manager (URM): IDB facility
40  *
41  *  ABSTRACT:
42  *
43  *      This module contains the publicly accessible top-level
44  *	IDB read & common (to read and write operations) routines.
45  *
46  *--
47  */
48 
49 
50 /*
51  *
52  *  INCLUDE FILES
53  *
54  */
55 
56 #include <Mrm/MrmAppl.h>
57 #include <Mrm/Mrm.h>
58 #include <Mrm/IDB.h>
59 
60 
61 /*
62  *
63  *  TABLE OF CONTENTS
64  *
65  *	UrmIdbOpenFileRead		Open a file for read access
66  *
67  *	UrmIdbOpenBuffer		Open a file contained in a buffer
68  *
69  *	UrmIdbCloseFile			Close an open file
70  *
71  *	UrmIdbGetIndexedResource	Get indexed resource from file
72  *
73  *	UrmIdbFindIndexedResource	Find indexed resource(s) in file
74  *
75  *	UrmIdbGetRIDResource		Get resource id'ed resource from file
76  *
77  *	UrmIdbGetResourceId		Get next resource id in file
78  *
79  *	Idb__FIL_Valid			Validate file id
80  */
81 
82 
83 /*
84  *++
85  *
86  *  PROCEDURE DESCRIPTION:
87  *
88  *	IdbOpenFile opens the requested IDB database file, and returns a
89  *	handle or id which is used in all subsequent IDB operations.
90  *	IdbOpenFile initializes the file's index structures and sets up
91  *	any buffers it needs. The database file is opened for read access only.
92  *
93  *  FORMAL PARAMETERS:
94  *
95  *	name		A system-dependent string specifying the IDB file
96  *			to be opened.
97  *	os_ext		An operating-system specific structure which
98  *			supports using specific file system features
99  *	file_id_return	returns the IDB file id used in all other IDB routines
100  *	fname_return	returns the name of the file actually opened
101  *			(via strcpy). Should be at least 256 chars.
102  *
103  *  IMPLICIT INPUTS:
104  *
105  *  IMPLICIT OUTPUTS:
106  *
107  *  FUNCTION VALUE:
108  *
109  *	MrmSUCCESS	operation succeeded
110  *	MrmNOT_FOUND	existing file not found
111  *	MrmFAILURE	operation failed, no further reason
112  *
113  *  SIDE EFFECTS:
114  *
115  *      1. Acquires memory for the file descriptor.
116  *
117  *--
118  */
119 
120 Cardinal
121 UrmIdbOpenFileRead (String			name,
122 		    MrmOsOpenParamPtr		os_ext,
123 		    IDBFile			*file_id_return,
124 		    char			*fname_return)
125 {
126 
127   /*
128    *  Local variables
129    */
130   Cardinal		result ;	/* function results */
131   IDBLowLevelFilePtr	fileid ;	/* low-level id for file */
132   IDBFile		filedesc ;	/* new file descriptor */
133   int			ndx ;		/* loop index */
134 
135 
136   /*
137    * Attempt to open the file.
138    */
139   result = Idb__FU_OpenFile
140     (name, URMReadAccess, os_ext,  &fileid, fname_return) ;
141   if ( result != MrmSUCCESS ) return result ;
142 
143   /*
144    * File successfully opened. Acquire a file descriptor and initialize it.
145    */
146   filedesc = (IDBFile) XtMalloc (sizeof(IDBOpenFile)) ;
147   if ( filedesc == NULL )
148     {
149       Idb__FU_CloseFile (fileid, FALSE);
150       return MrmFAILURE ;
151     }
152 
153   filedesc->validation = IDBOpenFileValid ;
154   filedesc->access = URMReadAccess ;
155   filedesc->lowlevel_id = fileid ;
156   filedesc->last_record = 0 ;
157   filedesc->last_data_record = 0 ;
158   filedesc->get_count = 0 ;
159   filedesc->put_count = 0 ;
160   filedesc->class_ctable = NULL;
161   filedesc->resource_ctable = NULL;
162   filedesc->byte_swapped = FALSE ;
163   filedesc->in_memory = FALSE ;
164   filedesc->uid_buffer = NULL ;
165   for ( ndx=IDBrtMin ; ndx<=IDBrtMax ; ndx++ )
166     filedesc->rt_counts[ndx] = 0 ;
167 
168   /*
169    * Read the file header record info into the file descriptor
170    */
171   result = Idb__HDR_GetHeader (filedesc) ;
172   if ( result != MrmSUCCESS )
173     {
174       UrmIdbCloseFile (filedesc, TRUE) ;
175       return result ;
176     }
177 
178   /*
179    * File successfully opened
180    */
181   *file_id_return = filedesc ;
182   return MrmSUCCESS ;
183 
184 }
185 
186 
187 /*
188  *++
189  *
190  *  PROCEDURE DESCRIPTION:
191  *
192  *     	This is a simplified version of UrmIdbOpenFile which opens
193  * 	a buffer contained in memory.
194  *
195  *  FORMAL PARAMETERS:
196  *
197  *	uid_buffer	the buffer containing the uid file
198  *	file_id_return	returns the IDB file id used in all other IDB routines
199  *
200  *  IMPLICIT INPUTS:
201  *
202  *  IMPLICIT OUTPUTS:
203  *
204  *  FUNCTION VALUE:
205  *
206  *	MrmSUCCESS	operation succeeded
207  *	MrmNOT_FOUND	existing file not found
208  *	MrmFAILURE	operation failed, no further reason
209  *
210  *  SIDE EFFECTS:
211  *
212  *      1. Acquires memory for the file descriptor.
213  *
214  *--
215  */
216 
217 Cardinal
UrmIdbOpenBuffer(unsigned char * uid_buffer,IDBFile * file_id_return)218 UrmIdbOpenBuffer (unsigned char 		*uid_buffer,
219 		  IDBFile			*file_id_return)
220 {
221 
222   /*
223    *  Local variables
224    */
225   Cardinal		result ;	/* function results */
226   IDBFile		filedesc ;	/* new file descriptor */
227   int			ndx ;		/* loop index */
228 
229 
230   filedesc = (IDBFile) XtMalloc (sizeof(IDBOpenFile)) ;
231   if ( filedesc == NULL ) return MrmFAILURE ;
232 
233   filedesc->validation = IDBOpenFileValid ;
234   filedesc->access = URMReadAccess ;
235   filedesc->lowlevel_id = NULL ;
236   filedesc->last_record = 0 ;
237   filedesc->last_data_record = 0 ;
238   filedesc->get_count = 0 ;
239   filedesc->put_count = 0 ;
240   filedesc->class_ctable = NULL;
241   filedesc->resource_ctable = NULL;
242   filedesc->byte_swapped = FALSE ;
243   filedesc->in_memory = TRUE ;
244   filedesc->uid_buffer = uid_buffer ;
245   for ( ndx=IDBrtMin ; ndx<=IDBrtMax ; ndx++ )
246     filedesc->rt_counts[ndx] = 0 ;
247 
248   /*
249    * Read the file header record info into the file descriptor
250    */
251   result = Idb__HDR_GetHeader (filedesc) ;
252   if ( result != MrmSUCCESS ) return result ;
253 
254   /*
255    * Buffer ready
256    */
257   *file_id_return = filedesc ;
258   return MrmSUCCESS ;
259 
260 }
261 
262 
263 
264 /*
265  *++
266  *
267  *  PROCEDURE DESCRIPTION:
268  *
269  *	If the file was opened for read access, then UrmIdbCloseFile simply
270  *	closes it. If it was opened for write acccess, then UrmIdbCloseFile
271  *	uses keep_new_file to determine its behavior. If keep_new_file is
272  *	true, then the file's index structures are updated, the file is
273  *	closed, and it becomes the newest version of the database file.
274  *	If keep_new_file is false, then the working copy of the file is closed
275  *	and deleted, retaining the previous version of the file as the latest
276  *	version. In all cases, UrmIdbCloseFile frees all memory structures
277  *	associated with the file.
278  *
279  *  FORMAL PARAMETERS:
280  *
281  *	file_id			The IDB file id returned by IdbOpenFile
282  *	keep_new_file		true if database is to be permanently updated;
283  *				false to quit without changing the database
284  *
285  *  IMPLICIT INPUTS:
286  *
287  *  IMPLICIT OUTPUTS:
288  *
289  *  FUNCTION VALUE:
290  *
291  *	MrmSUCCESS	operation succeeded
292  *	MrmFAILURE	operation failed
293  *
294  *  SIDE EFFECTS:
295  *
296  *--
297  */
298 
299 /*ARGSUSED*/
300 Cardinal
UrmIdbCloseFile(IDBFile file_id,Boolean keep_new_file)301 UrmIdbCloseFile (IDBFile		file_id,
302 		 Boolean		keep_new_file)	  /* unused */
303 {
304 
305   /*
306    *  Local variables
307    */
308   Cardinal	result ;		/* function results */
309 
310   /*
311    * Local macros
312    */
313 #define	_error_close()					\
314   {							\
315     Idb__FU_CloseFile(file_id->lowlevel_id,TRUE) ;	\
316     file_id->validation = 0 ;				\
317     XtFree((char*)file_id) ;				\
318     return MrmFAILURE ;					\
319   }
320 
321   if ( (result=Idb__FIL_Valid(file_id)) != MrmSUCCESS ) return result ;
322 
323   /*
324    * We are serious about closing this file so deallocate the class and resource
325    * tables before we do anything else.
326    */
327 
328   if (file_id->class_ctable != NULL)
329     XtFree ((char*)file_id->class_ctable);
330   if (file_id->resource_ctable != NULL)
331     XtFree ((char*)file_id->resource_ctable);
332 
333   /*
334    * If the file was opened for write, update its header
335    */
336   if ( file_id->access == URMWriteAccess )
337     {
338       result = Idb__HDR_PutHeader ( file_id ) ;
339       if ( result != MrmSUCCESS ) _error_close () ;
340     }
341 
342   /*
343    * Decommit the file's buffers
344    */
345   result = Idb__BM_DecommitAll (file_id) ;
346   if ( result != MrmSUCCESS ) _error_close () ;
347 
348   /*
349    * Close the file and deallocate the file descriptor
350    */
351   result = Idb__FU_CloseFile (file_id->lowlevel_id, FALSE) ;
352   file_id->validation = 0 ;
353   XtFree ((char*)file_id) ;
354 
355   /*
356    * File successfully closed
357    */
358   return MrmSUCCESS ;
359 
360 }
361 
362 
363 
364 /*
365  *++
366  *
367  *  PROCEDURE DESCRIPTION:
368  *
369  *	IdbGetIndexedResource attempts to retrieve a resource record with
370  *	a matching index. The entry's group and type must match the filters
371  *	when these are not null (RMCcNull and RMCtNull respectively). If a
372  *	matching entry is found, its resource group, type, access, and data
373  *	block are returned in the resource context. The resource context
374  *	memory buffer will be reallocated as required to hold the data block.
375  *
376  *  FORMAL PARAMETERS:
377  *
378  *	file_id		The IDB file id returned by IdbOpenFile
379  *	index		case-sensitive index for the entry to match
380  *	group_filter	if not null, entry found must match this group
381  *	type_filter	if not null, entry found must match this type
382  *	context_id	URM resource context to receieve data block
383  *
384  *  IMPLICIT INPUTS:
385  *
386  *  IMPLICIT OUTPUTS:
387  *
388  *  FUNCTION VALUE:
389  *
390  *	MrmSUCCESS	operation succeeded
391  *	MrmNOT_FOUND	entry not found
392  *	MrmWRONG_GROUP	entry didn't match group filter
393  *	MrmWRONG_TYPE	entry didn't match type filter
394  *	MrmFAILURE	operation failed, no further reason
395  *
396  *  SIDE EFFECTS:
397  *
398  *--
399  */
400 
401 Cardinal
UrmIdbGetIndexedResource(IDBFile file_id,String index,MrmGroup group_filter,MrmType type_filter,URMResourceContextPtr context_id)402 UrmIdbGetIndexedResource (IDBFile			file_id,
403 			  String			index,
404 			  MrmGroup			group_filter,
405 			  MrmType			type_filter,
406 			  URMResourceContextPtr		context_id)
407 {
408 
409   /*
410    *  Local variables
411    */
412   Cardinal		result ;	/* function results */
413   IDBDataHandle		data_entry ;	/* return new data entry */
414   MrmCode		group ;		/* data entry's group */
415   MrmCode		type ;		/* data entry's type */
416 
417 
418   if ( (result=Idb__FIL_Valid(file_id)) != MrmSUCCESS ) return result ;
419 
420   /*
421    * Attempt to find the item.
422    */
423   result = Idb__INX_ReturnItem (file_id, index, &data_entry) ;
424   if ( result != MrmSUCCESS ) return result ;
425   result = Idb__DB_GetDataEntry (file_id, data_entry, context_id) ;
426   if ( result != MrmSUCCESS ) return result ;
427 
428   /*
429    * Check group and type against filters.
430    */
431   group = UrmRCGroup (context_id) ;
432   type = UrmRCType (context_id) ;
433   if ( (group_filter!=URMgNul) && (group_filter!=group) )
434     return MrmWRONG_GROUP ;
435   if ( (type_filter!=URMtNul) && (type_filter!=type) )
436     return MrmWRONG_TYPE ;
437 
438   /*
439    * Item successfuly retrieved
440    */
441   return MrmSUCCESS ;
442 
443 }
444 
445 
446 
447 /*
448  *++
449  *
450  *  PROCEDURE DESCRIPTION:
451  *
452  *	IdbFindIndexedResource locates and lists all resources in the
453  *	database which match the given filters. The entries in the
454  *	index list will be in alphabetical order. The index strings must
455  *	be deallocated by the caller using UrmFreePlistContents. This
456  *	routine returns MrmSUCCESS even if no entries (0 entries) are found.
457  *	Failure returns are used only for internal and other errors.
458  *
459  *	The number of entries in index_list is not reset to 0 when
460  *	the search begins; its state is as the caller gives it.
461  *
462  *  FORMAL PARAMETERS:
463  *
464  *	file_id		The IDB file id returned by IdbOpenFile
465  *	group_filter	if not null, entries found must match this group
466  *	type_filter	if not null, entries found must match this type
467  *	index_list	A pointer list in which to return index
468  *			strings for matches. The required strings
469  *			are automatically allocated.
470  *
471  *  IMPLICIT INPUTS:
472  *
473  *  IMPLICIT OUTPUTS:
474  *
475  *  FUNCTION VALUE:
476  *
477  *	MrmSUCCESS	operation succeeded
478  *	MrmFAILURE	operation failed, no further reason
479  *
480  *  SIDE EFFECTS:
481  *
482  *--
483  */
484 
485 Cardinal
UrmIdbFindIndexedResource(IDBFile file_id,MrmGroup group_filter,MrmType type_filter,URMPointerListPtr index_list)486 UrmIdbFindIndexedResource (IDBFile		file_id,
487 			   MrmGroup		group_filter,
488 			   MrmType		type_filter,
489 			   URMPointerListPtr	index_list)
490 {
491 
492   /*
493    *  Local variables
494    */
495   Cardinal		result ;	/* function results */
496 
497 
498   /*
499    * Validate file id, then initiate search with the root node. Return
500    * immediately if there are no indexed resources.
501    */
502   if ( (result=Idb__FIL_Valid(file_id)) != MrmSUCCESS ) return result ;
503 
504   if ( file_id->num_indexed <= 0 ) return MrmSUCCESS ;
505   return Idb__INX_FindResources (file_id, file_id->index_root,
506 				 group_filter, type_filter, index_list) ;
507 
508 }
509 
510 
511 
512 /*
513  *++
514  *
515  *  PROCEDURE DESCRIPTION:
516  *
517  *	IdbGetRIDResource attempts to retrieve a resource record with a
518  *	matching resource id. If there is a resource record associated with
519  *	the resource id, it is returned - the resource group, type, and data
520  *	block are set in the resource context. The memory buffer in the
521  *	resource context is reallocated automatically as require to hold the
522  *	data block.
523  *
524  *  FORMAL PARAMETERS:
525  *
526  *	file_id		The IDB file id returned by IdbOpenFile
527  *	resource_id	resource id matching entry
528  *	group_filter	if not null, entries found must match this group
529  *	type_filter    	if not null, entries found must match this type
530  *	context_id	to return data block
531  *
532  *  IMPLICIT INPUTS:
533  *
534  *  IMPLICIT OUTPUTS:
535  *
536  *  FUNCTION VALUE:
537  *
538  *	MrmSUCCESS	operation succeeded
539  *	MrmNOT_FOUND	entry not found
540  *	MrmWRONG_GROUP	entry didn't match group filter
541  *	MrmWRONG_TYPE	entry didn't match type filter
542  *	MrmFAILURE	operation failed, no further reason
543  *
544  *  SIDE EFFECTS:
545  *
546  *--
547  */
548 
549 Cardinal
UrmIdbGetRIDResource(IDBFile file_id,MrmResource_id resource_id,MrmGroup group_filter,MrmType type_filter,URMResourceContextPtr context_id)550 UrmIdbGetRIDResource (IDBFile			file_id,
551 		      MrmResource_id		resource_id,
552 		      MrmGroup			group_filter,
553 		      MrmType			type_filter,
554 		      URMResourceContextPtr	context_id)
555 {
556 
557   /*
558    *  Local variables
559    */
560   Cardinal		result ;	/* function results */
561   IDBDataHandle		data_entry ;	/* return new data entry */
562   MrmCode		group ;		/* data entry's group */
563   MrmCode		type ;		/* data entry's type */
564 
565 
566   if ( (result=Idb__FIL_Valid(file_id)) != MrmSUCCESS ) return result ;
567 
568   /*
569    * Attempt to find the item.
570    */
571   result = Idb__RID_ReturnItem (file_id, resource_id, TRUE, &data_entry) ;
572   if ( result != MrmSUCCESS ) return result ;
573   result = Idb__DB_GetDataEntry (file_id, data_entry, context_id) ;
574   if ( result != MrmSUCCESS ) return result ;
575 
576   /*
577    * Check group and type against filters.
578    */
579   group = UrmRCGroup (context_id) ;
580   type = UrmRCType (context_id) ;
581   if ( (group_filter!=URMgNul) && (group_filter!=group) )
582     return MrmWRONG_GROUP ;
583   if ( (type_filter!=URMtNul) && (type_filter!=type) )
584     return MrmWRONG_TYPE ;
585 
586   /*
587    * Item successfuly retrieved
588    */
589   return MrmSUCCESS ;
590 
591 }
592 
593 /*
594  *++
595  *
596  *  PROCEDURE DESCRIPTION:
597  *
598  *	IdbGetResourceId returns the next available resource id in the file
599  *
600  *  FORMAL PARAMETERS:
601  *
602  *	file_id			The IDB file id returned by IdbOpenFile
603  *	resource_id_return	To return new resource id
604  *  IMPLICIT INPUTS:
605  *
606  *  IMPLICIT OUTPUTS:
607  *
608  *  FUNCTION VALUE:
609  *
610  *	MrmSUCCESS	operation succeeded
611  *	MrmFAILURE	operation failed, no further reason given
612  *
613  *  SIDE EFFECTS:
614  *
615  *--
616  */
617 
618 Cardinal
UrmIdbGetResourceId(IDBFile file_id,MrmResource_id * resource_id_return)619 UrmIdbGetResourceId (IDBFile			file_id,
620 		     MrmResource_id		*resource_id_return)
621 {
622 
623   /*
624    *  Local variables
625    */
626   Cardinal	result ;		/* function results */
627   IDBResource resource_id;
628 
629   if ( (result=Idb__FIL_Valid((IDBFile)file_id)) != MrmSUCCESS ) return result ;
630   result = Idb__RID_NextRID ((IDBFile)file_id,
631                              &resource_id) ;
632   *resource_id_return = resource_id;
633   return result ;
634 
635 }
636 
637 
638 
639 /*
640  *++
641  *
642  *  PROCEDURE DESCRIPTION:
643  *
644  *	This routine performs a validity check on a (supposed) IDB file
645  *	pointer. It should probably signal errors, but currently just
646  *	returns a code.
647  *
648  *  FORMAL PARAMETERS:
649  *
650  *	file_id		Supposed pointer to file descriptor to validate
651  *
652  *  IMPLICIT INPUTS:
653  *
654  *  IMPLICIT OUTPUTS:
655  *
656  *  FUNCTION VALUE:
657  *
658  *	MrmSUCCESS	operation succeeded
659  *	MrmFAILURE	some other failure
660  *
661  *  SIDE EFFECTS:
662  *
663  *--
664  */
665 
666 Cardinal
Idb__FIL_Valid(IDBFile file_id)667 Idb__FIL_Valid (IDBFile		file_id)
668 {
669 
670   if ( file_id == NULL ) return MrmFAILURE ;
671   if ( file_id->validation != IDBOpenFileValid ) return MrmFAILURE ;
672   return MrmSUCCESS ;
673 
674 }
675 
676