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: MrmIfile.c /main/13 1996/11/13 13:56:30 drk $"
31 #endif
32 #endif
33 
34 
35 /*
36  *++
37  *  FACILITY:
38  *
39  *      UIL Resource Manager (URM)
40  *
41  *  ABSTRACT:
42  *
43  *	This module contains the low-level file utilities
44  *
45  *--
46  */
47 
48 
49 /*
50  *
51  *  INCLUDE FILES
52  *
53  */
54 
55 #include <Mrm/MrmAppl.h>
56 #include <Mrm/Mrm.h>
57 #include <Mrm/IDB.h>
58 
59 #include <stdio.h>		/* Standard IO definitions		*/
60 #include <errno.h>
61 #include <fcntl.h>
62 
63 #ifndef X_NOT_STDC_ENV
64 #include <unistd.h>
65 #endif
66 
67 
68 /*
69  *
70  *  DEFINE and MACRO DEFINITIONS
71  *
72  */
73 
74 #define	PMODE	0666	/* Default protection mode before umask		*/
75 #define FAILURE	-1	/* creat/stat returns this			*/
76 
77 /*
78  *++
79  *
80  *  PROCEDURE DESCRIPTION:
81  *
82  *	This routine will take the file name specified and
83  *	open or create it depending on the access parameter.
84  *	An attempt is made to save any existing file of the
85  *	same name.
86  *
87  *
88  *  FORMAL PARAMETERS:
89  *
90  * 	name		the system-dependent file spec of the IDB file
91  *			to be opened.
92  *	accss		access type desired, read or write access.
93  *	os_ext		an operating specific structure to take advantage
94  *			of file system features (if any).
95  *	file_id		IDB file id used in all calls to low level routines.
96  *	returned_fname	The resultant file name.
97  *
98  *  IMPLICIT INPUTS:
99  *
100  *      NONE
101  *
102  *  IMPLICIT OUTPUTS:
103  *
104  *      NONE
105  *
106  *  FUNCTION VALUE:
107  *
108  *	Returns an integer:
109  *
110  *	MrmSUCCESS	- When access is read and open works
111  *	MrmCREATE_NEW	- When access is write and open works
112  *	MrmNOT_FOUND	- When access is read and the file isn't present
113  *	MrmFAILURE	- When the open fails for any other reason
114  *
115  *  SIDE EFFECTS:
116  *
117  *      Opens or creates the named file and assigns a channel to it.
118  *
119  *--
120  */
121 
122 Cardinal
123 Idb__FU_OpenFile (char 			*name,
124 		  MrmCode 		access,
125 		  MrmOsOpenParamPtr 	os_ext,
126 		  IDBLowLevelFilePtr 	*file_id,
127 		  char 			*returned_fname)
128 {
129 
130   /*
131    * Local variables
132    */
133   int		file_desc;		/* 'unix' file descriptor */
134   int		length;			/* the length of the above string */
135   IDBLowLevelFile *a_file;		/* pointer to the file_id */
136 
137   /* Fill in the result name with the name specified so far */
138   length = strlen (name);
139   strcpy (returned_fname, name);
140   returned_fname[length] = 0;
141 
142   /* Check if this file is to be opened for read or write access */
143   if (access == URMWriteAccess)
144     {
145       file_desc = open (name, O_RDWR, PMODE);
146       if (file_desc != FAILURE)		/* filename already exists. */
147 	{
148 	  if (os_ext == 0)
149 	    return MrmFAILURE;
150 	  else if (!os_ext->nam_flg.clobber_flg)
151 	    return MrmEXISTS;		/* no clobber. return Exists */
152 	  else if (os_ext->version != MrmOsOpenParamVersion)
153 	    return MrmFAILURE;
154 	  (void) close (file_desc);	/* we care not what close returns*/
155 	}
156 
157       file_desc = creat (name,PMODE);
158       if (file_desc == FAILURE)		/* verify that worked */
159 	return MrmFAILURE;
160 
161       close (file_desc);		/* we care not what close returns */
162       file_desc = open (name, O_RDWR, PMODE);
163 
164       if (file_desc == FAILURE)		/* verify that worked */
165 	return MrmFAILURE;
166     }
167 
168 
169   /* Else this file is to opened for read access */
170   else if (access == URMReadAccess)
171     {
172       file_desc = open (name, O_RDONLY, PMODE);
173 
174       /* verify that worked */
175       if (file_desc == FAILURE)
176 	{
177 	  if ( errno == EACCES )
178 	    return MrmFAILURE;
179 	  else
180 	    return MrmNOT_FOUND;
181 	}
182     }
183 
184   /* Not URMReadAccess or URMWriteAccess, so return invalid access type	    */
185   else
186     return MrmFAILURE;
187 
188 
189   /*
190    * now all we have to do is set up the IDBFile and return the
191    * proper success code.
192    */
193 
194   *file_id = (IDBLowLevelFilePtr)
195     XtMalloc(sizeof (IDBLowLevelFile));
196   if (*file_id==0)
197     return MrmFAILURE;
198 
199   a_file = (IDBLowLevelFile *) *file_id;
200 
201   a_file->name = XtMalloc (length+1);
202   if (a_file->name==0)
203     {
204       XtFree ((char*)*file_id);
205       return (MrmFAILURE);
206     }
207 
208   a_file->file_desc = file_desc;
209   strcpy (a_file->name, name);
210   a_file->name[length] = 0;
211 
212   if (access == URMWriteAccess)
213     return (MrmCREATE_NEW);
214   else
215     return (MrmSUCCESS);
216 
217 }
218 
219 
220 
221 /*
222  *++
223  *
224  *  PROCEDURE DESCRIPTION:
225  *
226  *	This routine will close the file and free any allocated storage
227  *
228  *
229  *  FORMAL PARAMETERS:
230  *
231  *	file_id		IDB file id
232  *	delete		delete the file if == true
233  *
234  *  IMPLICIT INPUTS:
235  *
236  *      the file name and channel from the IDBFile record
237  *
238  *  IMPLICIT OUTPUTS:
239  *
240  *      NONE
241  *
242  *  FUNCTION VALUE:
243  *
244  *	MrmSUCCESS	- When the file is closed [and deleted] successfully
245  *	MrmFAILURE	- When the close fails
246  *
247  *  SIDE EFFECTS:
248  *
249  *      Closes the file, deassigns the channel and possible deletes the file.
250  *
251  *--
252  */
253 
254 Cardinal
Idb__FU_CloseFile(IDBLowLevelFile * file_id,int delete)255 Idb__FU_CloseFile (IDBLowLevelFile	*file_id ,
256 		   int			delete)
257 {
258   /*
259    * Local variables
260    */
261 
262   int	status;				/* ret status for sys services	*/
263 
264   status = close (file_id->file_desc);
265   if (status != 0)
266     return MrmFAILURE;
267 
268   if (delete) {
269     status = unlink (file_id->name);
270   }
271 
272   XtFree (file_id->name);
273   XtFree ((char*)file_id);
274   return MrmSUCCESS;
275 
276 }
277 
278 /*
279  *++
280  *
281  *  PROCEDURE DESCRIPTION:
282  *
283  *	This function reads in the desired record into the given
284  *	buffer.
285  *
286  *  FORMAL PARAMETERS:
287  *
288  *	file_id		the IDB file identifier
289  *	block_num	the record number to retrieve
290  *	buffer		pointer to the buffer to fill in
291  *
292  *  IMPLICIT INPUTS:
293  *
294  *      NONE
295  *
296  *  IMPLICIT OUTPUTS:
297  *
298  *      NONE
299  *
300  *  FUNCTION VALUE:
301  *
302  *	MrmSUCCESS	operation succeeded
303  *	MrmNOT_FOUND	entry not found
304  *	MrmFAILURE	operation failed, no further reason
305  *
306  *  SIDE EFFECTS:
307  *
308  *      The buffer is filled in.  Should the $READ fail the buffer's
309  *	content is not predictable.
310  *
311  *--
312  */
313 
314 Cardinal
Idb__FU_GetBlock(IDBLowLevelFile * file_id,IDBRecordNumber block_num,char * buffer)315 Idb__FU_GetBlock (IDBLowLevelFile	*file_id,
316 		  IDBRecordNumber	block_num,
317 		  char			*buffer)
318 {
319   /*
320    * Local variables
321    */
322   int	number_read;		/* the number of bytes actually read	*/
323   int	fdesc ;			/* file descriptor from lowlevel desc */
324 
325 
326   fdesc = file_id->file_desc ;
327   lseek (fdesc, (block_num-1)*IDBRecordSize, 0);
328   number_read = read (file_id->file_desc, buffer, IDBRecordSize);
329 
330   if (number_read != IDBRecordSize)
331     return MrmFAILURE;
332   else
333     return MrmSUCCESS;
334 }
335 
336 
337 /*
338  *++
339  *
340  *  PROCEDURE DESCRIPTION:
341  *
342  *	This function writes the data in the givin buffer into
343  *	the desired record in the file.
344  *
345  *  FORMAL PARAMETERS:
346  *
347  *	file_id		the IDB file identifier
348  *	block_num	the record number to write
349  *	buffer		pointer to the buffer to read from
350  *
351  *  IMPLICIT INPUTS:
352  *
353  *      NONE
354  *
355  *  IMPLICIT OUTPUTS:
356  *
357  *      NONE
358  *
359  *  FUNCTION VALUE:
360  *
361  *	Returns an integer by value:
362  *
363  *	MrmSUCCESS	operation succeeded
364  *	MrmFAILURE	operation failed, no further reason
365  *
366  *  SIDE EFFECTS:
367  *
368  *	the file is modified.
369  *
370  *--
371  */
372 
373 Cardinal
Idb__FU_PutBlock(IDBLowLevelFile * file_id,IDBRecordNumber block_num,char * buffer)374 Idb__FU_PutBlock (IDBLowLevelFile	*file_id,
375 		  IDBRecordNumber	block_num,
376 		  char			*buffer)
377 {
378   /*
379    * Local variables
380    */
381   int	number_written;		/* the # of bytes acctually written	*/
382   int	fdesc ;			/* file descriptor from lowlevel desc */
383 
384 
385   fdesc = file_id->file_desc ;
386   lseek (fdesc, (block_num-1)*IDBRecordSize, 0);
387   number_written = write (file_id->file_desc, buffer, IDBRecordSize);
388 
389   if (number_written != IDBRecordSize)
390     return MrmFAILURE;
391   else
392     return MrmSUCCESS;
393 }
394 
395