f41c844336f1f25ed9d5bf56cf0eb2b067857946
[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(int isfd, char *record)
75 {
76     Fab *fab;
77     int                 reclen;
78     int                 ret;
79     int                 recnum;
80
81     /*
82      * Get File Access Block.
83      */
84     if ((fab = _isfd_find(isfd)) == NULL) {
85         _setiserrno2(ENOTOPEN, '9', '0');
86         return (ISERROR);
87     }
88
89     /*
90      * Check that the open mode was  ISINOUT.
91      */
92     if (fab->openmode != OM_INOUT) {
93         _setiserrno2(ENOTOPEN, '9', '0');
94         return (ISERROR);
95     }
96
97     /*
98      * Determine record length. Check it against min and max record length.
99      */
100     reclen = (fab->varlength == TRUE) ? isreclen : fab->minreclen;
101     if (reclen < fab->minreclen || reclen > fab->maxreclen) {
102         _setiserrno2(EBADARG, '9', '0');
103         return (ISERROR);
104     }
105
106     if ((ret = _amrewcurr(&fab->isfhandle, record, reclen, &fab->curpos,
107                           &recnum, &fab->errcode)) == ISOK) {
108         isrecnum = recnum;                   /* Set isrecnum */
109     }
110
111     _seterr_errcode(&fab->errcode);
112
113     return (ret);                            /* Successful write */
114 }
115
116 /*
117  * _amrewcurr(isfhandle, record, reclen, curpos, recnum, errcode)
118  *
119  * _amrewcurr() rewrites the current record in ISAM file.
120  *
121  * Input params:
122  *      isfhandle       Handle of ISAM file
123  *      record          record
124  *      reclen          length of the record
125  *      curpos          curent record position
126  *
127  * Output params:
128  *      errcode         error status of the operation
129  *      curpos          new current position
130  *      recnum          record number fo current record
131  *
132  */
133
134 static int
135 _amrewcurr(Bytearray *isfhandle, char *record, int reclen,
136            Bytearray *curpos, Recno *recnum, struct errcode *errcode)
137 {
138     Fcb                 *fcb;
139     Crp                 *crp;
140     Bytearray           newcurpos;
141     int                 err;
142     char                oldrecord[ISMAXRECLEN];
143     int                 reclen2;
144     int                 (*rec_read)();
145     int                 (*rec_rewrite)();
146
147     _isam_entryhook();
148
149     /*
150      * Get FCB corresponding to the isfhandle handle.
151      */
152     if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
153         _isam_exithook();
154         return (ISERROR);
155     }
156
157     rec_read = (fcb->varflag?_vlrec_read:_flrec_read);
158     rec_rewrite = (fcb->varflag?_vlrec_rewrite:_flrec_rewrite);
159
160     /*
161      * Get info from current record position structure.
162      */
163     crp = (Crp *) curpos->data;
164
165
166     if (crp->flag != CRP_ON) {
167         _amseterrcode(errcode, ENOCURR);
168         goto ERROR;
169     }
170
171     /*
172      * Update information in FCB from CNTL page on the disk
173      */
174     (void)_isfcb_cntlpg_r2(fcb);
175
176     /*
177      * We must read the record first to be able to delete keys.
178      */
179     if (rec_read(fcb, oldrecord, crp->recno, &reclen2) != ISOK) {
180         _amseterrcode(errcode, ENOCURR);
181         goto ERROR;
182     }
183
184     if (rec_rewrite(fcb, record, crp->recno, reclen) != ISOK) {
185         _amseterrcode(errcode, ENOCURR);
186         goto ERROR;
187     }
188              
189     /*
190      * Update keys, set new key position.
191      */
192     newcurpos = _bytearr_dup(curpos);
193     if ((err = _changekeys2 (fcb, record, oldrecord, crp->recno, &newcurpos)) 
194         != ISOK) {
195         _bytearr_free(&newcurpos);
196         _amseterrcode(errcode, err);    
197         goto ERROR;
198     }
199
200     /* 
201      * This takes care of new record position if the physical order is in use.
202      */
203     *recnum = crp->recno;       
204     
205     _bytearr_free(curpos);
206     crp = NULL;                 /* was aliased to freed curpos->data */
207     *curpos = newcurpos;
208
209     _amseterrcode(errcode, ISOK);
210     _issignals_mask();
211     _isdisk_commit();
212     _isdisk_sync();
213     _isdisk_inval();
214
215     /*
216      * Update control page.
217      */
218     (void)_isfcb_cntlpg_w2(fcb);
219     _issignals_unmask();
220
221     _isam_exithook();
222     return (ISOK);
223
224  ERROR:
225     _isdisk_rollback();
226     _isdisk_inval();
227
228     /*
229      * Restore FCB from CNTL page.
230      */
231     (void)_isfcb_cntlpg_r2(fcb);
232
233     _isam_exithook();
234     return (ISERROR);
235 }
236
237 Static int
238 _changekeys2(Fcb *fcb, char *record, char *oldrecord,
239              Recno recnum, Bytearray *curpos)
240 {
241     int                 nkeys = fcb->nkeys;
242     int        i;
243     int                 err;
244     Crp                 *crp;
245     int                 keyid;
246     Keydesc2            *keydesc2;
247
248     crp = (Crp *)curpos->data;
249     keyid = crp->keyid;
250
251     for (i = 0; i < nkeys; i++) {
252         keydesc2 = fcb->keys + i;
253         if ((err =_change1key(fcb, keydesc2, record, oldrecord, recnum,
254                               (keydesc2->k2_keyid == keyid) ?
255                               crp->key : (char *) NULL)) != ISOK)
256             return (err);
257     }
258
259     return (ISOK);
260 }