4f00fde36c2502a8d53b2b1d394e8528c2b78a0e
[oweals/cde.git] / cde / lib / tt / mini_isam / isrewrec.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: isrewrec.c /main/3 1995/10/23 11:44:28 rswiston $                                                    */
28 #ifndef lint
29 static char sccsid[] = "@(#)isrewrec.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  * isrewrec.c
37  *
38  * Description:
39  *      Rewrite a record in ISAM file. 
40  */
41
42
43 #include "isam_impl.h"
44 #include <sys/time.h>
45
46 static int _amrewrec(), _changekeys();
47
48 /*
49  * err = isrewrec(isfd, recnum, record)
50  *
51  * Isrewrec() modifies a record in ISAM file. The record is identified 
52  * by its record number. All indexes of the ISAM file are updated.
53  *
54  * Current record position is not changed.
55  * isrecnum is set to recnum.
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  *      ENOREC  Record with record number recnum does not exist.
70  */
71
72 int 
73 isrewrec(int isfd, long recnum, char *record)
74 {
75     Fab *fab;
76     int                 reclen;
77     int                 ret;
78
79     /*
80      * Get File Access Block.
81      */
82     if ((fab = _isfd_find(isfd)) == NULL) {
83         _setiserrno2(ENOTOPEN, '9', '0');
84         return (ISERROR);
85     }
86
87     /*
88      * Check that the open mode was  ISINOUT.
89      */
90     if (fab->openmode != OM_INOUT) {
91         _setiserrno2(ENOTOPEN, '9', '0');
92         return (ISERROR);
93     }
94
95     /*
96      * Determine record length. Check it against min and max record length.
97      */
98     reclen = (fab->varlength == TRUE) ? isreclen : fab->minreclen;
99     if (reclen < fab->minreclen || reclen > fab->maxreclen) {
100         _setiserrno2(EBADARG, '9', '0');
101         return (ISERROR);
102     }
103
104     if ((ret = _amrewrec(&fab->isfhandle,  record,
105                          reclen, recnum, &fab->errcode)) == ISOK) {
106         isrecnum = recnum;                   /* Set isrecnum */
107     }
108
109     _seterr_errcode(&fab->errcode);
110
111     return (ret);                            /* Successful write */
112 }
113
114 /*
115  * _amrewrec(isfhandle, record, reclen, recnum, errcode)
116  *
117  * _amrewrec() rewrites a record in ISAM file.
118  *
119  * Input params:
120  *      isfhandle       Handle of ISAM file
121  *      record          record
122  *      reclen          length of the record
123  *      recnum          record number of record to be deleted
124  *
125  * Output params:
126  *      errcode         error status of the operation
127  *
128  */
129
130 static int
131 _amrewrec(Bytearray *isfhandle, char *record, int reclen, Recno recnum,
132           struct errcode *errcode)
133 {
134     Fcb                 *fcb;
135     char                oldrecbuf[ISMAXRECLEN];
136     int                 err;
137     int                 reclen2;
138     int                 (*rec_read)();
139     int                 (*rec_rewrite)();
140
141     _isam_entryhook();
142
143     /*
144      * Get FCB corresponding to the isfhandle handle.
145      */
146     if ((fcb = _openfcb(isfhandle, errcode)) == NULL) {
147         _isam_exithook();
148         return (ISERROR);
149     }
150
151     rec_read = (fcb->varflag?_vlrec_read:_flrec_read);
152     rec_rewrite = (fcb->varflag?_vlrec_rewrite:_flrec_rewrite);
153
154     /*
155      * Update information in FCB from CNTL page on the disk
156      */
157     (void)_isfcb_cntlpg_r2(fcb);
158
159     /*
160      * We must read the record first to be able to delete keys.
161      */
162     if (rec_read(fcb, oldrecbuf, recnum, &reclen2) != ISOK) {
163         _amseterrcode(errcode, ENOREC);
164         goto ERROR;
165     }
166
167     if (rec_rewrite(fcb, record, recnum, reclen) != ISOK) {
168         _amseterrcode(errcode, ENOREC);
169         goto ERROR;
170     }
171
172     /*
173      * Update all keys.
174      */
175     if ((err = _changekeys(fcb, record, oldrecbuf, recnum)) != ISOK) {
176         _amseterrcode(errcode, err);    
177         goto ERROR;
178     }
179
180     _amseterrcode(errcode, ISOK);
181
182     _issignals_mask();
183     _isdisk_commit();
184     _isdisk_sync();
185     _isdisk_inval();
186
187     /*
188      * Update control page.
189      */
190     (void)_isfcb_cntlpg_w2(fcb);
191     _issignals_unmask();
192
193     _isam_exithook();
194     return (ISOK);
195
196  ERROR:
197     _isdisk_rollback();
198     _isdisk_inval();
199
200     /*
201      * Restore FCB from CNTL page.
202      */
203      (void)_isfcb_cntlpg_r2(fcb);   
204
205     _isam_exithook();
206     return (ISERROR);
207 }
208
209 static int
210 _changekeys (Fcb *fcb, char *record, char *oldrecord, Recno recnum)
211 {
212     int                 nkeys = fcb->nkeys;
213     int        i;
214     int                 err;
215
216     for (i = 0; i < nkeys; i++) {
217         if ((err =_change1key(fcb, fcb->keys + i, record, oldrecord, recnum,
218                               (char *)NULL)) 
219             != ISOK)
220             return (err);
221     }
222
223     return (ISOK);
224 }