source: trunk/athena/etc/synctree/switch.c @ 8564

Revision 8564, 7.3 KB checked in by cfields, 28 years ago (diff)
Do the right thing with the owner when copying new symlinks -p.
  • Property svn:executable set to *
Line 
1/*
2 * Copyright (C) 1988  Tim Shepard              All rights reserved.
3 * Copyright (C) 1989  MIT/Project Athena       All rights reserved.
4 */
5
6#if defined(_AIX) && defined(i386)
7#define unlink(a) (rmslink(a) && unlink(a))
8#endif
9
10#define noupdate(problem) printf("Not %sing %s because %s\n",action,targname,problem)
11#define update_error(problem) printf("Error %sing %s: %s: %s\n",action,targname,problem,strerror(errno))
12
13        switch (typeofaction) {
14            int status;
15#define action "copy"
16        case ACTION_COPY:
17        case ACTION_LOCAL:
18            /* We want to ignore "virtual" files */
19            if (srctype == TYPE_V)
20                break;
21           
22            if (exists) {
23                if ((verbosef || nflag) && (typeofaction == ACTION_LOCAL)) {
24                    noupdate("the target is a local version.");
25                    break;
26                }
27                if (srctype != targtype && (srctype & TYPE_V) == 0) {
28                    if (!fflag && (targtype != TYPE_L)) {
29                        noupdate("the file types diff.  Use -f to override.");
30                        break;
31                    }
32                    if (verbosef || nflag)
33                        printf("Removing %s (file types differ).\n", targname);
34                    if (!nflag) {
35                        if (targtype == TYPE_D) {
36                            if (recursive_rmdir(targname)) {
37                                update_error("recursive rmdir failed");
38                                break;
39                            }
40                        } else                     
41                        if (unlink(targname)) {
42                            update_error("unlink failed");
43                            break;
44                        }
45                    }
46                    exists = FALSE;
47                }
48            }
49            switch (srctype) {
50            case TYPE_R:
51                if (!exists) {
52                    if (nflag) {
53                        printf("Copying %s (mode is %5.5o).\n",
54                               srcname,targname,srcmode);
55                        break;
56                    }
57                    if (copyfile(srcname,targname,srcmode))
58                        update_error("copy failed");
59                    setdates();
60                    if (pflag &&
61                        (chown(targname, -1, srcgid) ||
62                         chown(targname, srcuid, -1)))
63                        update_error("chown failed");
64                    break;
65                }
66                switch(status = filecheck3()) {
67                case UPTODATE:
68                    break;
69                case NEWERDATE:
70                    if (!fflag) {
71                        noupdate("the target is a more recent copy.");
72                        break;
73                    }
74                    /* fall through */
75                case OUTOFDATE:
76                    if ((verbosef || nflag) && (typeofaction == ACTION_LOCAL)){
77                        noupdate("the target is a local version (the target is old).");
78                        break;
79                    }
80                    if (verbosef || nflag)
81                        printf("Updating out of date %s .\n", targname);
82                    if (!nflag) {
83                        if (unlink(targname)) {
84                            update_error("unlink failed");
85                            break;
86                        } else if (copyfile(srcname,targname,srcmode)) {
87                            update_error("copy failed");
88                            break;
89                        }
90                        setdates();
91                    }
92                    /* fall through */
93                case FIXOWNANDMODE:
94                case FIXMODE:
95                    if ((verbosef || nflag) && (typeofaction == ACTION_LOCAL)){
96                        noupdate("the target is a local version (the ownership is different).");
97                        break;
98                    }
99                    if ((verbosef || nflag) && (status == FIXOWNANDMODE))
100                        printf("Fixing ownership and modes of %s .\n",
101                               targname);
102                    if ((verbosef || nflag) && (status == FIXMODE))
103                        printf("Fixing modes of %s .\n", targname);
104
105                    if (!nflag && chmod(targname, srcmode))
106                        update_error("chmod() failed");
107                    if (!nflag && pflag && (status != FIXMODE) &&
108                        (chown(targname, -1, srcgid) ||
109                         chown(targname, srcuid, -1)))
110                        update_error("chown failed");
111                    break;                 
112                default:
113                    noupdate("of an internal error: filecheck3() returned an unknown value.");
114                }
115                break;
116                 
117            case TYPE_L:
118                if (exists) {
119                    char buf1[BUFSIZ], buf2[BUFSIZ];
120                    int buf1_len, buf2_len;
121                   
122                    if (((buf1_len = readlink(srcname, buf1, BUFSIZ)) ==
123                         (buf2_len = readlink(targname, buf2, BUFSIZ))) &&
124                        !strncmp(buf1,buf2,buf1_len))
125                        break;
126                    if ((verbosef || nflag) && (typeofaction == ACTION_LOCAL)){
127                        noupdate("the target is a local link (the links are different).");
128                        break;
129                    }
130                    if (verbosef || nflag)
131                        printf("Updating symbolic link %s .\n", targname);
132                    if (!nflag && unlink(targname))
133                        update_error("unlink failed");
134                } else
135                    if (verbosef || nflag)
136                        printf("Copying symbolic link %s .\n",srcname);
137                if (nflag)
138                    break;
139                if (copylink(srcname,targname,srcmode))
140                    update_error("copy of symbolic link failed.");
141#ifdef ultrix
142                else if (pflag && chown(targname,srcuid,srcgid))
143                    update_error("chown() failed.");
144#endif
145#ifdef SYSV
146                else if (pflag && lchown(targname,srcuid,srcgid))
147                    update_error("lchown() failed.");
148#endif
149                break;
150             
151            case TYPE_D:
152                if (!exists) {
153                    if (verbosef || nflag)
154                        printf("Creating directory %s .\n", targname);
155                    if (nflag)
156                        break;
157                    if (mkdir(targname,0777)) {
158                        update_error("mkdir() failed");
159                        break;          /* No point continuing... */
160                    }
161                    else if (chmod(targname, srcmode))
162                        update_error("chmod() failed");
163                    else if (pflag && chown(targname, srcuid, srcgid))
164                        update_error("chown() failed");
165                } else {
166                    switch(status = dircheck()) {
167                    case FIXMODE:
168                    case FIXOWNANDMODE:
169                        if ((verbosef || nflag) &&
170                            (typeofaction == ACTION_LOCAL)) {
171                            noupdate("the target is a local version");
172                            break;
173                        }
174                        if ((verbosef || nflag) && (status == FIXMODE))
175                            printf("Fixing modes of %s .\n", targname);
176                        else if (verbosef || nflag)
177                            printf("Fixing ownership and modes of %s .\n",
178                                   targname);
179                        if (!nflag && chmod(targname, srcmode))
180                            update_error("chmod() failed");
181                        if (!nflag && pflag &&
182                            (chown(targname, -1, srcgid) ||
183                             chown(targname, srcuid, -1))) {
184                            update_error("chown() failed");
185                            break;
186                        }
187                        break;             
188                    }
189                }
190                if (dodir(srcname, targname, part))
191                    printf("The update of %s from %s aborted prematurely.\n",
192                           targname, srcname);
193                break;
194
195            case TYPE_C:
196            case TYPE_B:
197                noupdate("copying of devices is not yet supported.");
198                break;
199            }
200            break;
201           
202#undef  action
203#define action "link"
204        case ACTION_LINK:
205            if (exists) {
206                char linkbuf[MAXPATHLEN];
207                int linklen;
208               
209                switch(targtype) {
210                case TYPE_V:
211                    /* This is a virtual file... so we should ignore it */
212                    break;
213                case TYPE_L:
214                    linklen = readlink(targname, linkbuf, MAXPATHLEN);
215                    if ((!strncmp(linkbuf, srcname, linklen)) &&
216                        (*((char *)srcname + linklen) == 0))
217                        break;
218                    /* fall through */
219                default:
220                    if (!fflag && targtype != TYPE_L) {
221                        noupdate("the target was not a symlink.  Use -f to override.\n");
222                        break;
223                    }
224                    if (verbosef || nflag) printf("Removing %s .\n",targname);
225                    if (!nflag)
226                        if (targtype == TYPE_D) {
227                            if (recursive_rmdir(targname)) {
228                                update_error("recursive rmdir failed");
229                                break;
230                            }
231                        } else                     
232                        if (unlink(targname)) {
233                            update_error("unlink failed");
234                            break;
235                        }
236                    exists = FALSE;
237                    break;
238                }
239            }
240            if (exists) break;
241            if (verbosef || nflag)
242                printf("Creating symbolic link from %s to %s .\n", targname, srcname);
243            if (!nflag && symlink(srcname,targname))
244                update_error("symlink failed");
245            break;
246
247/*
248 * The action words are intentionally mispelled to
249 * get the correct spelling during message displays
250 */
251#undef  action
252#define action "ignor"
253        case ACTION_IGNORE:
254            break;
255
256#undef update_error
257#define update_error(problem) printf("Error %sing %s: %s: %s\n",action,targname,problem,strerror(errno))
258
259#undef action
260#define action "delet"
261        case ACTION_DELETE:
262            if (!exists)
263                break;
264            if (verbosef || nflag)
265                printf("Removing %s.\n", targname);
266            if (!nflag) {
267                if (targtype & TYPE_D) {
268                    if (recursive_rmdir(targname))
269                        update_error("recursive rmdir failed");
270                }
271                else if (unlink(targname))
272                    update_error("unlink failed");
273            }
274            break;
275        }
Note: See TracBrowser for help on using the repository browser.