dtcm: Resolve CID 87713
[oweals/cde.git] / cde / programs / dtcm / server / garbage.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 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 /* $XConsortium: garbage.c /main/6 1996/11/21 19:44:58 drk $ */
24 /*
25  *  (c) Copyright 1993, 1994 Hewlett-Packard Company
26  *  (c) Copyright 1993, 1994 International Business Machines Corp.
27  *  (c) Copyright 1993, 1994 Novell, Inc.
28  *  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
29  */
30
31 #include        <EUSCompat.h>
32 #include        <stdio.h>
33 #include        <fcntl.h>
34 #include        <unistd.h>
35 #include        <stdlib.h>
36 #define XOS_USE_NO_LOCKING
37 #define X_INCLUDE_TIME_H
38 #if defined(linux)
39 #undef SVR4
40 #endif
41 #include <X11/Xos_r.h>
42 #include        "log.h"
43 #include        "rtable4.h"
44 #include        "cm.h"
45 #include        "cmscalendar.h"
46 #include        "tree.h"
47 #include        "garbage.h"
48
49 extern char *pgname;
50
51 static CSA_return_code dump_error;
52 static int fd;
53
54 /*
55  * forward declaration of functions used within this file
56  */
57 static boolean_t magic_time(time_t t);
58 static boolean_t visit1(caddr_t node, caddr_t d);
59 static boolean_t visit2(caddr_t node, caddr_t d);
60 static void print_file_error(char *file, char *msg);
61
62 extern void
63 _DtCmsCollectOne(_DtCmsCalendar *cal)
64 {
65         Rb_Status       status;
66         CSA_return_code         stat;
67         char *bak, *temp, *clog;
68
69         if (cal == NULL)
70                 return;
71
72         status  = rb_check_tree(APPT_TREE(cal));
73         clog    = _DtCmsGetLogFN(cal->calendar);
74         temp    = _DtCmsGetTmpFN(cal->calendar);
75         bak     = _DtCmsGetBakFN(cal->calendar);
76
77         if (status != rb_ok || clog==NULL || temp==NULL || bak==NULL) {
78                 fprintf(stderr, "%s: cannot acquire files to execute garbage collection.\n", pgname);
79                 fprintf(stderr, "possible causes: cannot find home directory.\n");
80                 fprintf(stderr, "\tNIS or your host server might be down.\n");
81                 fprintf(stderr, "damage: none\n\n");
82                 goto cleanup;
83         }
84
85         /* Make sure that the temp file does not exist before garbage collect */
86         unlink (temp);
87         if (cal->fversion == _DtCMS_VERSION1)
88                 stat = _DtCmsCreateLogV1(cal->owner, temp);
89         else
90                 stat = _DtCmsCreateLogV2(cal->owner, temp);
91
92         if (stat != CSA_SUCCESS) {
93                 if (stat == (CSA_X_DT_E_BACKING_STORE_PROBLEM))
94                         print_file_error(temp,
95                                 "file error during garbage collection");
96                 else {
97                         fprintf(stderr, "%s: file error on %s during garbage collection\n",
98                                 pgname, temp);
99                         fprintf(stderr, "Reason: getpwnam() failed. %s%s\n",
100                                 "No passwd entry for owner of ",
101                                 cal->calendar);
102
103                         fprintf(stderr, "damage: none\n\n");
104                 }
105                 goto cleanup;
106         }
107
108         if (cal->fversion == _DtCMS_VERSION1)
109                 stat = _DtCmsDumpDataV1(temp, cal);
110         else
111                 stat = _DtCmsDumpDataV2(temp, cal);
112
113         if (stat != CSA_SUCCESS) {
114                 print_file_error(temp,
115                         (stat == (CSA_X_DT_E_BACKING_STORE_PROBLEM) ?
116                          "file error during garbage collection" :
117                          "can't dump data structure to file during garbage collection"));
118                 goto cleanup;
119         }
120
121         /* mv -f .callog .calbak; mv -f temp .callog */
122         if (rename (clog, bak) < 0) {
123                 perror ("rpc.cmsd: Can't backup callog to .calbak.\nreason:");
124                 goto cleanup;
125         }
126
127         if (rename (temp, clog) < 0) {
128                 perror("rpc.cmsd: Can't move .caltemp to callog.\nreason:");
129                 fprintf(stderr, "%s: you may recover %s from %s.\n", pgname,
130                         clog, bak);
131         }
132
133 cleanup:
134         if (bak != NULL) {
135                 free(bak);
136                 bak = NULL;
137         }
138         if (temp != NULL) {
139                 free(temp);
140                 temp = NULL;
141         }
142         if (clog != NULL) {
143                 free(clog);
144                 clog = NULL;
145         }
146 }
147
148 extern CSA_return_code
149 _DtCmsDumpDataV1(char *file, _DtCmsCalendar *cal)
150 {
151         CSA_return_code stat;
152
153         dump_error = CSA_SUCCESS;
154
155         /* Keep the temp log file open during garbage collection. */
156         if ((fd = open(file, O_WRONLY | O_APPEND | O_SYNC)) < 0)
157         {
158                 return (CSA_X_DT_E_BACKING_STORE_PROBLEM);
159         }
160
161         if ((stat = _DtCmsAppendAccessByFD(fd, access_read_4,
162             GET_R_ACCESS(cal))) != CSA_SUCCESS)
163                 return (stat);
164
165         if ((stat = _DtCmsAppendAccessByFD(fd, access_write_4,
166             GET_W_ACCESS(cal))) != CSA_SUCCESS)
167                 return (stat);
168
169         if ((stat = _DtCmsAppendAccessByFD (fd, access_delete_4,
170             GET_D_ACCESS(cal))) != CSA_SUCCESS)
171                 return (stat);
172
173         if ((stat = _DtCmsAppendAccessByFD (fd, access_exec_4,
174             GET_X_ACCESS(cal))) != CSA_SUCCESS)
175                 return (stat);
176
177         _DtCmsEnumerateUp(cal, visit1); /* dump the tree */
178
179         if (close(fd) == EOF)
180                 return (CSA_X_DT_E_BACKING_STORE_PROBLEM);
181
182         return (dump_error);
183 }
184
185 extern CSA_return_code
186 _DtCmsDumpDataV2(char *file, _DtCmsCalendar *cal)
187 {
188         CSA_return_code stat;
189
190         dump_error = CSA_SUCCESS;
191
192         /* Keep the temp log file open during garbage collection. */
193         if ((fd = open(file, O_WRONLY | O_APPEND | O_SYNC)) < 0)
194         {
195                 return (CSA_X_DT_E_BACKING_STORE_PROBLEM);
196         }
197
198         /* dump calendar attributes */
199         if (cal->num_attrs > 0) {
200                 if ((stat = _DtCmsAppendCalAttrsByFD(fd, cal->num_attrs,
201                     cal->attrs)) != CSA_SUCCESS)
202                         return (stat);
203         }
204
205         if ((stat = _DtCmsAppendHTableByFD(fd, cal->entry_tbl->size,
206             cal->entry_tbl->names, cal->types)) != CSA_SUCCESS)
207                 return (stat);
208
209         _DtCmsEnumerateUp(cal, visit2); /* dump the tree */
210
211         if (close(fd) == EOF)
212                 return (CSA_X_DT_E_BACKING_STORE_PROBLEM);
213
214         return (dump_error);
215 }
216
217 static boolean_t
218 magic_time(time_t t)
219 {
220         boolean_t magic = B_FALSE;
221         struct tm *tm;
222         _Xltimeparams localtime_buf;
223
224         tm = _XLocaltime(&t, localtime_buf);
225
226         if (tm->tm_hour == 3 && tm->tm_min == 41)
227                  magic = B_TRUE;
228
229         return(magic);
230 }
231
232 static boolean_t
233 visit1(caddr_t node, caddr_t d)
234 {
235         boolean_t stop = B_FALSE;
236
237         switch (((Appt_4 *) d)->tag->tag)
238         {
239         case otherTag_4:
240                 /*
241                  * otherTags = events read in from files.
242                  * Don't write to log.
243                  */
244                 return(stop);
245
246         case appointment_4:
247                 /*
248                  * a little hack to get us off the
249                  * totally hokey magic-time business.
250                  */
251                 if (magic_time(((Appt_4 *)d)->appt_id.tick)) {
252                         ((Appt_4 *)d)->tag->showtime = 0;
253                 }
254                 break;
255         }
256
257         if ((dump_error = _DtCmsAppendAppt4ByFD(fd, (Appt_4 *)d, _DtCmsLogAdd)) != CSA_SUCCESS)
258                 stop = B_TRUE;
259
260         return(stop);
261 }
262
263 static boolean_t
264 visit2(caddr_t node, caddr_t d)
265 {
266         boolean_t stop = B_FALSE;
267
268         if ((dump_error = _DtCmsAppendEntryByFD(fd, (cms_entry *)d,
269             _DtCmsLogAdd)) != CSA_SUCCESS)
270                 stop = B_TRUE;
271
272         return(stop);
273 }
274
275 static void
276 print_file_error(char *file, char *msg)
277 {
278         if (file)
279                 fprintf(stderr, "%s: (%s)%s\n", pgname, file, msg);
280         else
281                 fprintf(stderr, "%s: %s\n", pgname, msg);
282         fprintf(stderr, "possible causes: %s, %s, %s, %s\n",
283                 "host server is down", "disk is full", "out of memory",
284                 "file protections have changed.");
285         fprintf(stderr, "damage: none\n\n");
286 }
287
288