Merge branch 'master' into cde-next
[oweals/cde.git] / cde / lib / tt / mini_isam / iswrrec.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: iswrrec.c /main/3 1995/10/23 11:46:30 rswiston $                                                     */
28 /*
29  * Copyright (c) 1988 by Sun Microsystems, Inc.
30  */
31
32 /*
33  * iswrrec.c
34  *
35  * Description:
36  *      Write a record to ISAM file. 
37  */
38
39 #include "isam_impl.h"
40 #include <sys/time.h>
41
42 static int _amwrrec();
43
44 /*
45  * isfd = iswrrec(isfd, recnum, record)
46  *
47  * Iswrrec() writes a record to ISAM file at specified recno position. 
48  * All indexes of the ISAM file are updated.
49  *
50  * Current record position is not changed.
51  * isrecnum is set to recnum.
52  *
53  * If the ISAM file is for variable length records, the isreclen variable
54  * must be set to indicate the actual length of the record, which must
55  * be between the minimum and maximum length, as specified in isbuild().
56  *
57  * Returns 0 if successful, or -1 of any error.
58  *
59  * Errors:
60  *      EDUPL   The write would result in a duplicate on a key that
61  *              does not allow duplicates.
62  *      ELOCKED The file has been locked by another process.
63  *      ENOTOPEN isfd does not correspond to an open ISAM file, or the
64  *              ISAM file was not opened with ISINOUT mode.
65  *      EKEXISTS Record with recnum already exists.
66  *      EBADARG recnum is negative.
67  */
68
69 int 
70 iswrrec(int isfd, long recnum, char *record)
71 {
72     Fab *fab;
73     int                 reclen;
74     int                 ret;
75
76     /*
77      * Get File Access Block.
78      */
79     if ((fab = _isfd_find(isfd)) == NULL) {
80         _setiserrno2(ENOTOPEN, '9', '0');
81         return (ISERROR);
82     }
83
84     /*
85      * Check that the open mode was  ISINOUT.
86      */
87     if (fab->openmode != OM_INOUT) {
88         _setiserrno2(ENOTOPEN, '9', '0');
89         return (ISERROR);
90     }
91
92     /*
93      * Determine record length. Check it against min and max record length.
94      */
95     reclen = (fab->varlength == TRUE) ? isreclen : fab->minreclen;
96     if (reclen < fab->minreclen || reclen > fab->maxreclen) {
97         _setiserrno2(EBADARG, '9' ,'0');
98         return (ISERROR);
99     }
100    
101     if ((ret = _amwrrec(&fab->isfhandle, record, reclen,
102                         recnum, &fab->errcode)) == ISOK) {
103         isrecnum = recnum;                   /* Set isrecnum */
104     }
105
106     _seterr_errcode(&fab->errcode);
107
108     return (ret);                            /* Successful write */
109 }
110
111 /*
112  * _amwrrec(isfhandle, record, reclen, recnum, errcode)
113  *
114  * _amwrrec() rewrites a record in ISAM file.
115  *
116  * Input params:
117  *      isfhandle       Handle of ISAM file
118  *      record          record
119  *      reclen          length of the record
120  *      recnum          record number of record to be deleted
121  *
122  * Output params:
123  *      errcode         error status of the operation
124  *
125  */
126
127 static int
128 _amwrrec(Bytearray *isfhandle, char *record, int reclen, Recno recnum,
129          struct errcode *errcode)
130 {
131     Fcb                 *fcb = NULL;
132     int                 err;
133     int                 (*rec_wrrec)();
134
135     _isam_entryhook();
136
137     /*
138      * Get FCB corresponding to the isfhandle handle.
139      */
140     if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
141         _isam_exithook();
142         return (ISERROR);
143     }
144
145     rec_wrrec = (fcb->varflag?_vlrec_wrrec:_flrec_wrrec);
146
147     /*
148      * Update information in FCB from CNTL page on the disk
149      */
150     (void)_isfcb_cntlpg_r2(fcb);
151
152     if ((err = rec_wrrec(fcb, record, recnum, reclen)) != ISOK) {
153         _amseterrcode(errcode, err);
154         goto ERROR;
155     }
156
157     /*
158      * Update all keys.
159      */
160     if ((err = _addkeys(fcb, record, recnum)) != ISOK) {
161         _amseterrcode(errcode, err);    
162         goto ERROR;
163     }
164
165     fcb->nrecords++;
166
167     _amseterrcode(errcode, ISOK);
168
169     _issignals_mask();
170     _isdisk_commit();
171     _isdisk_sync();
172     _isdisk_inval();
173
174     /*
175      * Update CNTL Page from the FCB.
176      */
177     (void)_isfcb_cntlpg_w2(fcb);
178     _issignals_unmask();
179
180     _isam_exithook();
181     return (ISOK);
182
183  ERROR:
184     _isdisk_rollback();
185     _isdisk_inval();
186
187     /*
188      * Restore FCB from CNTL page.
189      */
190     if (fcb) (void)_isfcb_cntlpg_r2(fcb);
191
192     _isam_exithook();
193     return (ISERROR);
194 }
195
196