source: trunk/athena/bin/get_message/put_fallback_file.c @ 14063

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