Fix typo in license headers
[oweals/cde.git] / cde / lib / tt / mini_isam / isrewcurr.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: isrewcurr.c /main/3 1995/10/23 11:44:15 rswiston $                                                   */
28 #ifndef lint
29 static char sccsid[] = "@(#)isrewcurr.c 1.8 89/07/17 Copyr 1988 Sun Micro";
30 #endif
31 /*
32  * Copyright (c) 1988 by Sun Microsystems, Inc.
33  */
34
35 /*
36  * isrewcurr.c
37  *
38  * Description:
39  *      Rewrite current record in ISAM file. 
40  */
41
42
43 #include "isam_impl.h"
44 #include <sys/time.h>
45
46 static int _amrewcurr(), _changekeys2();
47
48 /*
49  * err = isrewcurr(isfd, record)
50  *
51  * Isrewcurr() modifies the current record in ISAM file. 
52  * All indexes of the ISAM file are updated.
53  *
54  * Current record position is changed in relation to the new key value.
55  * isrecnum is set to the changed record.
56  *
57  * If the ISAM file is for variable length records, the isreclen variable
58  * must be set to indicate the actual length of the record, which must
59  * be between the minimum and maximum length, as specified in isbuild().
60  *
61  * Returns 0 if successful, or -1 of any error.
62  *
63  * Errors:
64  *      EDUPL   The write woul result in a duplicate on a key that
65  *              does not allow duplicates.
66  *      ELOCKED The file has been locked by another process.
67  *      ENOTOPEN isfd does not correspond to an open ISAM file, or the
68  *              ISAM file was not opened with ISINOUT mode.
69  *      ENOCURR Record with record number recnum does not exist, or it
70  *              was deleted by another process.
71  */
72
73 int 
74 isrewcurr(isfd, record)
75     int                 isfd;
76     char                *record;
77 {
78     register Fab        *fab;
79     int                 reclen;
80     int                 ret;
81     int                 recnum;
82
83     /*
84      * Get File Access Block.
85      */
86     if ((fab = _isfd_find(isfd)) == NULL) {
87         _setiserrno2(ENOTOPEN, '9', '0');
88         return (ISERROR);
89     }
90
91     /*
92      * Check that the open mode was  ISINOUT.
93      */
94     if (fab->openmode != OM_INOUT) {
95         _setiserrno2(ENOTOPEN, '9', '0');
96         return (ISERROR);
97     }
98
99     /*
100      * Determine record length. Check it against min and max record length.
101      */
102     reclen = (fab->varlength == TRUE) ? isreclen : fab->minreclen;
103     if (reclen < fab->minreclen || reclen > fab->maxreclen) {
104         _setiserrno2(EBADARG, '9', '0');
105         return (ISERROR);
106     }
107
108     if ((ret = _amrewcurr(&fab->isfhandle, record, reclen, &fab->curpos,
109                           &recnum, &fab->errcode)) == ISOK) {
110         isrecnum = recnum;                   /* Set isrecnum */
111     }
112
113     _seterr_errcode(&fab->errcode);
114
115     return (ret);                            /* Successful write */
116 }
117
118 /*
119  * _amrewcurr(isfhandle, record, reclen, curpos, recnum, errcode)
120  *
121  * _amrewcurr() rewrites the current record in ISAM file.
122  *
123  * Input params:
124  *      isfhandle       Handle of ISAM file
125  *      record          record
126  *      reclen          length of the record
127  *      curpos          curent record position
128  *
129  * Output params:
130  *      errcode         error status of the operation
131  *      curpos          new current position
132  *      recnum          record number fo current record
133  *
134  */
135
136 static int
137 _amrewcurr(isfhandle, record, reclen, curpos, recnum, errcode)
138     Bytearray           *isfhandle;
139     char                *record;
140     int                 reclen;
141     Recno               *recnum;
142     Bytearray           *curpos;
143     struct errcode      *errcode;
144 {
145     Fcb                 *fcb;
146     Crp                 *crp;
147     Bytearray           newcurpos;
148     int                 err;
149     char                oldrecord[ISMAXRECLEN];
150     int                 reclen2;
151     int                 (*rec_read)();
152     int                 (*rec_rewrite)();
153
154     _isam_entryhook();
155
156     /*
157      * Get FCB corresponding to the isfhandle handle.
158      */
159     if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
160         _isam_exithook();
161         return (ISERROR);
162     }
163
164     rec_read = (fcb->varflag?_vlrec_read:_flrec_read);
165     rec_rewrite = (fcb->varflag?_vlrec_rewrite:_flrec_rewrite);
166
167     /*
168      * Get info from current record position structure.
169      */
170     crp = (Crp *) curpos->data;
171
172
173     if (crp->flag != CRP_ON) {
174         _amseterrcode(errcode, ENOCURR);
175         goto ERROR;
176     }
177
178     /*
179      * Update information in FCB from CNTL page on the disk
180      */
181     (void)_isfcb_cntlpg_r2(fcb);
182
183     /*
184      * We must read the record first to be able to delete keys.
185      */
186     if (rec_read(fcb, oldrecord, crp->recno, &reclen2) != ISOK) {
187         _amseterrcode(errcode, ENOCURR);
188         goto ERROR;
189     }
190
191     if (rec_rewrite(fcb, record, crp->recno, reclen) != ISOK) {
192         _amseterrcode(errcode, ENOCURR);
193         goto ERROR;
194     }
195              
196     /*
197      * Update keys, set new key position.
198      */
199     newcurpos = _bytearr_dup(curpos);
200     if ((err = _changekeys2 (fcb, record, oldrecord, crp->recno, &newcurpos)) 
201         != ISOK) {
202         _bytearr_free(&newcurpos);
203         _amseterrcode(errcode, err);    
204         goto ERROR;
205     }
206
207     /* 
208      * This takes care of new record position if the physical order is in use.
209      */
210     *recnum = crp->recno;       
211     
212     _bytearr_free(curpos);
213     crp = NULL;                 /* was aliased to freed curpos->data */
214     *curpos = newcurpos;
215
216     _amseterrcode(errcode, ISOK);
217     _issignals_mask();
218     _isdisk_commit();
219     _isdisk_sync();
220     _isdisk_inval();
221
222     /*
223      * Update control page.
224      */
225     (void)_isfcb_cntlpg_w2(fcb);
226     _issignals_unmask();
227
228     _isam_exithook();
229     return (ISOK);
230
231  ERROR:
232     _isdisk_rollback();
233     _isdisk_inval();
234
235     /*
236      * Restore FCB from CNTL page.
237      */
238     (void)_isfcb_cntlpg_r2(fcb);
239
240     _isam_exithook();
241     return (ISERROR);
242 }
243
244 Static int
245 _changekeys2(fcb, record, oldrecord, recnum, curpos)
246     Fcb                 *fcb;
247     char                *record;
248     char                *oldrecord;
249     Recno               recnum;
250     Bytearray           *curpos;
251 {
252     int                 nkeys = fcb->nkeys;
253     register int        i;
254     int                 err;
255     Crp                 *crp;
256     int                 keyid;
257     Keydesc2            *keydesc2;
258
259     crp = (Crp *)curpos->data;
260     keyid = crp->keyid;
261
262     for (i = 0; i < nkeys; i++) {
263         keydesc2 = fcb->keys + i;
264         if ((err =_change1key(fcb, keydesc2, record, oldrecord, recnum,
265                               (keydesc2->k2_keyid == keyid) ?
266                               crp->key : (char *) NULL)) != ISOK)
267             return (err);
268     }
269
270     return (ISOK);
271 }