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