source: trunk/athena/bin/syncupdate/syncupdate.c @ 16689

Revision 16689, 4.1 KB checked in by amb, 23 years ago (diff)
Syncupdate should halt on bad input.
Line 
1/* Copyright 1999 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: syncupdate.c,v 1.3 2001-10-23 01:43:24 amb Exp $";
17
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <stdio.h>
21#include <string.h>
22#include <stdlib.h>
23#include <unistd.h>
24#include <fcntl.h>
25#include <errno.h>
26
27#ifndef S_IAMB
28#define S_IAMB 0x1FF    /* Access bits part of struct stat st_mode field */
29#endif
30
31static void copy(const char *source, const char *tempfile);
32static void open_and_sync(const char *filename);
33static void usage(void);
34
35int main(int argc, char **argv)
36{
37  int c;
38  const char *tempfile = NULL, *source, *dest;
39
40  while ((c = getopt(argc, argv, "c:")) != EOF)
41    {
42      switch (c)
43        {
44        case 'c':
45          tempfile = optarg;
46          break;
47        case '?':
48          usage();
49        }
50    }
51  argc -= optind;
52  argv += optind;
53  if (argc != 2)
54    usage();
55  source = argv[0];
56  dest = argv[1];
57
58  /* Set up for the move. */
59  if (tempfile)
60    {
61      copy(source, tempfile);
62      source = tempfile;
63    }
64  else
65    open_and_sync(source);
66
67  if (rename(source, dest) == -1)
68    {
69      fprintf(stderr, "syncupdate: can't rename %s to %s: %s\n",
70              source, dest, strerror(errno));
71      exit(1);
72    }
73
74  exit(0);
75}
76
77static void copy(const char *source, const char *tempfile)
78{
79  int sfd, tfd, count, pos, n;
80  struct stat statbuf;
81  unsigned char buf[8192];
82
83  /* Open the source file and get its status information. */
84  sfd = open(source, O_RDONLY, 0);
85  if (sfd == -1)
86    {   
87      fprintf(stderr, "syncupdate: can't read %s: %s\n", source,
88              strerror(errno));
89      exit(1);
90    }
91  if (fstat(sfd, &statbuf) == -1)
92    {
93      fprintf(stderr, "syncupdate: can't stat %s: %s\n", source,
94              strerror(errno));
95      exit(1);
96    }
97
98  /* Remove, open, and set mode on the temp file. */
99  if (unlink(tempfile) == -1 && errno != ENOENT)
100    {
101      fprintf(stderr, "syncupdate: can't remove %s: %s\n", tempfile,
102              strerror(errno));
103      exit(1);
104    }
105  tfd = open(tempfile, O_RDWR | O_CREAT | O_EXCL, 0);
106  if (tfd == -1)
107    {
108      fprintf(stderr, "syncupdate: can't create %s: %s\n", tempfile,
109              strerror(errno));
110      exit(1);
111    }
112  if (fchmod(tfd, statbuf.st_mode & S_IAMB) == -1)
113    {
114      fprintf(stderr, "syncupdate: can't fchmod %s: %s\n", tempfile,
115              strerror(errno));
116      unlink(tempfile);
117      exit(1);
118    }
119
120  /* Now copy and fsync. */
121  while ((count = read(sfd, buf, sizeof(buf))) > 0)
122    {
123      for (pos = 0; pos < count; pos += n)
124        {
125          n = write(tfd, buf + pos, count - pos);
126          if (n == -1)
127            {
128              fprintf(stderr, "syncupdate: can't write to %s: %s\n", tempfile,
129                      strerror(errno));
130              unlink(tempfile);
131              exit(1);
132            }
133        }
134    }
135  if (count == -1)
136    {
137      fprintf(stderr, "syncupdate: can't read from %s: %s\n", source,
138              strerror(errno));
139    }
140
141  if (fsync(tfd) == -1)
142    {
143      fprintf(stderr, "syncupdate: can't fsync %s: %s\n", tempfile,
144              strerror(errno));
145      unlink(tempfile);
146      exit(1);
147    }
148
149  close(sfd);
150  close(tfd);
151}
152
153static void open_and_sync(const char *filename)
154{
155  int fd;
156
157  fd = open(filename, O_RDWR, 0);
158  if (fd == -1)
159    {
160      fprintf(stderr, "syncupdate: can't open %s: %s\n", filename,
161              strerror(errno));
162      exit(1);
163    }
164
165  if (fsync(fd) == -1)
166    {
167      fprintf(stderr, "syncupdate: can't fsync %s: %s\n", filename,
168              strerror(errno));
169      exit(1);
170    }
171
172  close(fd);
173}
174
175static void usage(void)
176{
177  fprintf(stderr, "Usage: syncupdate [-c tempfile] source dest\n");
178  exit(1);
179}
Note: See TracBrowser for help on using the repository browser.