fixed font swapping to not forget name of font that was in old position
[unix-history] / usr / src / bin / mv / mv.c
CommitLineData
d53fe8dd 1#ifndef lint
98288a4a 2static char *sccsid = "@(#)mv.c 4.13 (Berkeley) 83/06/30";
d53fe8dd 3#endif
2a7e674d 4
3880b4a9
BJ
5/*
6 * mv file1 file2
7 */
d53fe8dd
SL
8#include <sys/param.h>
9#include <sys/stat.h>
3880b4a9
BJ
10
11#include <stdio.h>
98288a4a 12#include <sys/dir.h>
d53fe8dd 13#include <errno.h>
3880b4a9
BJ
14#include <signal.h>
15
3880b4a9 16#define DELIM '/'
3880b4a9 17#define MODEBITS 07777
3880b4a9 18
d53fe8dd
SL
19#define ISDIR(st) (((st).st_mode&S_IFMT) == S_IFDIR)
20#define ISLNK(st) (((st).st_mode&S_IFMT) == S_IFLNK)
21#define ISREG(st) (((st).st_mode&S_IFMT) == S_IFREG)
22#define ISDEV(st) \
23 (((st).st_mode&S_IFMT) == S_IFCHR || ((st).st_mode&S_IFMT) == S_IFBLK)
24
3880b4a9
BJ
25char *sprintf();
26char *dname();
27struct stat s1, s2;
d53fe8dd
SL
28int iflag = 0; /* interactive mode */
29int fflag = 0; /* force overwriting */
30extern unsigned errno;
3880b4a9
BJ
31
32main(argc, argv)
d53fe8dd 33 register char *argv[];
3880b4a9
BJ
34{
35 register i, r;
ca02483b 36 register char *arg;
29ba52aa 37 char *dest;
3880b4a9 38
3880b4a9
BJ
39 if (argc < 2)
40 goto usage;
d53fe8dd 41 while (argc > 1 && *argv[1] == '-') {
3880b4a9 42 argc--;
ca02483b
BJ
43 arg = *++argv;
44
45 /*
d53fe8dd
SL
46 * all files following a null option
47 * are considered file names
ca02483b 48 */
d53fe8dd
SL
49 if (*(arg+1) == '\0')
50 break;
51 while (*++arg != '\0') switch (*arg) {
3880b4a9 52
d53fe8dd
SL
53 case 'i':
54 iflag++;
55 break;
3880b4a9 56
d53fe8dd
SL
57 case 'f':
58 fflag++;
59 break;
3880b4a9 60
d53fe8dd
SL
61 default:
62 goto usage;
63 }
3880b4a9
BJ
64 }
65 if (argc < 3)
66 goto usage;
29ba52aa 67 dest = argv[argc-1];
a7d0170a 68 if (stat(dest, &s2) >= 0 && ISDIR(s2)) {
66a05c49 69 r = 0;
d53fe8dd
SL
70 for (i = 1; i < argc-1; i++)
71 r |= movewithshortname(argv[i], dest);
72 exit(r);
73 }
29ba52aa
KM
74 if (argc > 3)
75 goto usage;
76 r = move(argv[1], argv[2]);
d53fe8dd
SL
77 exit(r);
78 /*NOTREACHED*/
3880b4a9 79usage:
d53fe8dd 80 fprintf(stderr,
a7d0170a 81"usage: mv [-if] f1 f2 or mv [-if] f1 ... fn d1 (`fn' is a file or directory)\n");
d53fe8dd
SL
82 return (1);
83}
84
85movewithshortname(src, dest)
86 char *src, *dest;
87{
88 register char *shortname;
89 char target[MAXPATHLEN + 1];
90
91 shortname = dname(src);
92 if (strlen(dest) + strlen(shortname) > MAXPATHLEN - 1) {
93 error("%s/%s: pathname too long", dest,
94 shortname);
95 return (1);
96 }
97 sprintf(target, "%s/%s", dest, shortname);
98 return (move(src, target));
3880b4a9
BJ
99}
100
101move(source, target)
d53fe8dd 102 char *source, *target;
3880b4a9 103{
b07dfbb8 104 int targetexists;
3880b4a9 105
2a7e674d 106 if (lstat(source, &s1) < 0) {
d53fe8dd
SL
107 error("cannot access %s", source);
108 return (1);
3880b4a9 109 }
d53fe8dd
SL
110 /*
111 * First, try to rename source to destination.
112 * The only reason we continue on failure is if
113 * the move is on a nondirectory and not across
114 * file systems.
115 */
b07dfbb8
SL
116 targetexists = lstat(target, &s2) >= 0;
117 if (targetexists) {
d53fe8dd
SL
118 if (iflag && !fflag && query("remove %s? ", target) == 0)
119 return (1);
120 if (s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino) {
121 error("%s and %s are identical", source, target);
122 return (1);
3880b4a9 123 }
d53fe8dd
SL
124 if (access(target, 2) < 0 && !fflag && isatty(fileno(stdin))) {
125 if (query("override protection %o for %s? ",
126 s2.st_mode & MODEBITS, target) == 0)
127 return (1);
128 }
b07dfbb8
SL
129 }
130 if (rename(source, target) >= 0)
131 return (0);
132 if (errno != EXDEV) {
133 Perror2(source, "rename");
134 return (1);
135 }
136 if (ISDIR(s1)) {
137 error("can't mv directories across file systems");
138 return (1);
139 }
140 if (targetexists && unlink(target) < 0) {
141 error("cannot unlink %s", target);
142 return (1);
3880b4a9 143 }
d53fe8dd
SL
144 /*
145 * File can't be renamed, try to recreate the symbolic
146 * link or special device, or copy the file wholesale
147 * between file systems.
148 */
149 if (ISLNK(s1)) {
2a7e674d 150 register m;
d53fe8dd 151 char symln[MAXPATHLEN];
2a7e674d
KM
152
153 if (readlink(source, symln, sizeof (symln)) < 0) {
d53fe8dd 154 Perror(source);
2a7e674d
KM
155 return (1);
156 }
157 m = umask(~(s1.st_mode & MODEBITS));
158 if (symlink(symln, target) < 0) {
d53fe8dd 159 Perror(target);
2a7e674d
KM
160 return (1);
161 }
d53fe8dd
SL
162 (void) umask(m);
163 goto cleanup;
164 }
165 if (ISDEV(s1)) {
e99dc6b8
SL
166 time_t tv[2];
167
d53fe8dd
SL
168 if (mknod(target, s1.st_mode, s1.st_rdev) < 0) {
169 Perror(target);
170 return (1);
171 }
e99dc6b8
SL
172 /* kludge prior to utimes */
173 tv[0] = s1.st_atime;
174 tv[1] = s1.st_mtime;
175 (void) utime(target, tv);
d53fe8dd
SL
176 goto cleanup;
177 }
178 if (ISREG(s1)) {
179 int i, c, status;
e99dc6b8 180 time_t tv[2];
d53fe8dd 181
3880b4a9
BJ
182 i = fork();
183 if (i == -1) {
d53fe8dd
SL
184 error("try again");
185 return (1);
3880b4a9
BJ
186 }
187 if (i == 0) {
188 execl("/bin/cp", "cp", source, target, 0);
d53fe8dd 189 error("cannot exec /bin/cp");
3880b4a9
BJ
190 exit(1);
191 }
192 while ((c = wait(&status)) != i && c != -1)
193 ;
194 if (status != 0)
d53fe8dd 195 return (1);
e99dc6b8
SL
196 /* kludge prior to utimes */
197 tv[0] = s1.st_atime;
198 tv[1] = s1.st_mtime;
199 (void) utime(target, tv);
d53fe8dd 200 goto cleanup;
3880b4a9 201 }
d53fe8dd
SL
202 error("%s: unknown file type %o", source, s1.st_mode);
203 return (1);
3880b4a9 204
d53fe8dd 205cleanup:
3880b4a9 206 if (unlink(source) < 0) {
d53fe8dd
SL
207 error("cannot unlink %s", source);
208 return (1);
3880b4a9 209 }
d53fe8dd 210 return (0);
3880b4a9
BJ
211}
212
d53fe8dd
SL
213/*VARARGS*/
214query(prompt, a1, a2)
215 char *a1;
3880b4a9 216{
d53fe8dd 217 register char i, c;
3880b4a9 218
d53fe8dd
SL
219 fprintf(stderr, prompt, a1, a2);
220 i = c = getchar();
221 while (c != '\n' && c != EOF)
222 c = getchar();
223 return (i == 'y');
3880b4a9
BJ
224}
225
226char *
227dname(name)
d53fe8dd 228 register char *name;
3880b4a9
BJ
229{
230 register char *p;
231
232 p = name;
233 while (*p)
234 if (*p++ == DELIM && *p)
235 name = p;
236 return name;
237}
238
d53fe8dd
SL
239/*VARARGS*/
240error(fmt, a1, a2)
241 char *fmt;
3880b4a9 242{
3880b4a9 243
d53fe8dd
SL
244 fprintf(stderr, "mv: ");
245 fprintf(stderr, fmt, a1, a2);
246 fprintf(stderr, "\n");
247}
3880b4a9 248
d53fe8dd
SL
249Perror(s)
250 char *s;
251{
252 char buf[MAXPATHLEN + 10];
253
254 sprintf(buf, "mv: %s", s);
255 perror(buf);
3880b4a9
BJ
256}
257
d53fe8dd
SL
258Perror2(s1, s2)
259 char *s1, *s2;
3880b4a9 260{
d53fe8dd
SL
261 char buf[MAXPATHLEN + 20];
262
263 sprintf(buf, "mv: %s: %s", s1, s2);
264 perror(buf);
3880b4a9 265}