source: trunk/athena/bin/gms/put_fallback_file.c @ 5092

Revision 5092, 4.7 KB checked in by probe, 33 years ago (diff)
<sys/types.h> was originally in the wrong place... last edit accidentally created two inclusions (cleaning up my mistake).
Line 
1/* This file is part of the Project Athena Global Message System.
2 * Created by: Mark W. Eichin <eichin@athena.mit.edu>
3 *
4 * $Id: put_fallback_file.c,v 1.6 1991-06-19 15:40:49 probe Exp $
5 *
6 *      Copyright (c) 1988 by the Massachusetts Institute of Technology.
7 *      For copying and distribution information, see the file
8 *      "mit-copyright.h".
9 */
10#include <mit-copyright.h>
11#ifndef lint
12static char rcsid_put_fallback_file_c[] = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/gms/put_fallback_file.c,v 1.6 1991-06-19 15:40:49 probe Exp $";
13#endif lint
14
15#include "globalmessage.h"
16#include <sys/types.h>
17#include <sys/file.h>
18#include <sys/time.h>
19
20Code_t put_fallback_file(message_data, message_size, message_filename)
21     char *message_data;
22     int message_size;
23     char *message_filename;
24{
25  int errstat;
26  int message_filedesc;
27  time_t ftime;
28  struct timeval tvp[2];
29  int oumask;
30 
31  /* in case we try to NULL out the file... */
32  tvp[0].tv_sec = tvp[1].tv_sec = 0;
33  tvp[0].tv_usec = tvp[1].tv_usec = 0;
34 
35  /* guard against bogus arguments */
36  if((!message_data)||(!message_size)||(!message_filename)) {
37    return(GMS_NULL_ARG_ERR);
38  }
39  if((message_size<0)) {
40    return(GMS_BAD_ARG_ERR);
41  }
42 
43  /*
44   * First, check the time stamp in the file, to see if we should mark
45   * it for deletion (if it exists) and warp the timestamp back or
46   * just avoid creating it if it doesn't.
47   */
48  ftime = atol(&message_data[GMS_VERSION_STRING_LEN+1]);
49  {
50    /* We want to set the time back if the file does exist; if it
51     * doesn't, we want to leave it missing.
52     */
53    errstat = open(message_filename, O_RDONLY, 0);
54    if((errstat != -1)&&(ftime>0)) {
55      char dummy[1];
56      /* We read one byte so that the =access= time gets set; utimes
57       * doesn't work if you don't own the file.
58       * We can ignore any error return, since if the read fails the
59       * file will later be cleared and it will work anyhow.
60       */
61      read(errstat, dummy, 1);
62      /* we never care about the old contents if we have new contents to
63       * install, so just close this and reopen it later for writing.
64       */
65      close(errstat);
66    } else if((errstat == -1)&&(ftime == 0)) {
67      if(errno == ENOENT) {
68        /* it didn't exist, so we want to leave it that way. */
69        return(0);
70      } else {
71        /* something went wrong, but we can't do much about it.
72         * We just have to hope the cron job clears it.
73         */
74        return(errno);
75      }
76    }
77    /*
78     * Don't bother worrying about an open error here, the failure
79     * modes are such that either it will work later (ie. it was just
80     * a missing file, which we are about to create anyway) or the
81     * cron job will clean it up. Neither should be reported, as they
82     * do not affect the user.  If the file was indeed there, we want
83     * to put the empty data into it, so that when someone requests
84     * it, they don't get a stale message; however, we still want to
85     * try to warp the clock.
86     */
87  }
88
89  /*
90   * We could use an open and then a chmod to set the permissions of
91   * the file, rather than using umask, but if we do things that way,
92   * there is a window of time during which the file has the wrong permissions.
93   */
94  oumask = umask(0);            /* we really want these open */
95  /* write the file so that it is world writeable. Note that since
96   * usr/tmp is sticky-bitted by default, we can't remove the file
97   * directly, even with this openness; that is dealt with by warping
98   * the clock backwards on the file and letting the daily find job do
99   * the work.
100   */
101  message_filedesc = open(message_filename,
102                          O_CREAT|O_WRONLY|O_TRUNC, 0666);
103  (void) umask(oumask);
104 
105  /* Just return the error if something fails. This will be later
106   * ignored, since this is a non critical stage...
107   */
108  if(message_filedesc == -1) {
109    return(errno);
110  }
111
112  /*
113   * The timestamps are already in the message image, so just save
114   * them.
115   */
116  errstat = write(message_filedesc, message_data, message_size);
117  close(message_filedesc);
118  /*
119   * if we don't want to force the timestamps, we can exit now on an
120   * error instead of waiting.
121   */
122  if((ftime>0) && errstat == -1) {
123    return(errno);
124  }
125
126  /*
127   * if the file should really go away, warp the clock back as well,
128   * so the cron job can nuke it....
129   */
130  if(ftime>0) {
131    /* the read we did earlier should have set the access time, so we
132     * don't need to do anything else here.
133     */
134    return(0);
135  }
136  /*
137   * We can reuse errstat (having not checked it), since if the write
138   * fails, we still want to try the utimes in the hope that the
139   * timestamp will get set and the cron job will really delete the
140   * file.
141   */
142  errstat = utimes(message_filename, tvp);
143  if(errstat == -1) {
144    return(errno);
145  }
146  /* everything worked. */
147  return(0);
148}
Note: See TracBrowser for help on using the repository browser.