4 int copy1(int fdf, int fdt, char *from, char *to);
5 void hardremove(char *);
6 int mv(char *from, char *todir, char *toelem);
7 int mv1(char *from, Dir *dirb, char *todir, char *toelem);
8 int samefile(char *, char *);
9 void split(char *, char **, char **);
12 main(int argc, char *argv[])
19 fprint(2, "usage: mv fromfile tofile\n");
20 fprint(2, " mv fromfile ... todir\n");
24 /* prepass to canonicalise names before splitting, etc. */
25 for(i=1; i < argc; i++)
28 if((dirto = dirstat(argv[argc-1])) != nil && (dirto->mode&DMDIR)){
31 && (dirfrom = dirstat(argv[1])) != nil
32 && (dirfrom->mode & DMDIR))
33 split(argv[argc-1], &todir, &toelem); /* mv dir1 dir2 */
34 else{ /* mv file... dir */
36 toelem = nil; /* toelem will be fromelem */
40 split(argv[argc-1], &todir, &toelem); /* mv file1 file2 */
42 if(argc>3 && toelem != nil){
43 fprint(2, "mv: %s not a directory\n", argv[argc-1]);
48 for(i=1; i < argc-1; i++)
49 if(mv(argv[i], todir, toelem) < 0)
57 mv(char *from, char *todir, char *toelem)
64 fprint(2, "mv: can't stat %s: %r\n", from);
67 stat = mv1(from, dirb, todir, toelem);
73 mv1(char *from, Dir *dirb, char *todir, char *toelem)
75 int fdf, fdt, i, j, stat;
76 char toname[4096], fromname[4096];
77 char *fromdir, *fromelem;
80 strncpy(fromname, from, sizeof fromname);
81 split(from, &fromdir, &fromelem);
86 fprint(2, "mv: null last name element moving %s\n", fromname);
90 if(i + j + 2 > sizeof toname){
91 fprint(2, "mv: path too big (max %d): %s/%s\n",
92 sizeof toname, todir, toelem);
95 memmove(toname, todir, j);
97 memmove(toname+j+1, toelem, i);
100 if(samefile(fromdir, todir)){
101 if(samefile(fromname, toname)){
102 fprint(2, "mv: %s and %s are the same\n",
107 /* remove target if present */
108 dirt = dirstat(toname);
117 if(dirwstat(fromname, &null) >= 0)
119 if(dirb->mode & DMDIR){
120 fprint(2, "mv: can't rename directory %s: %r\n",
126 * Renaming won't work --- must copy
128 if(dirb->mode & DMDIR){
129 fprint(2, "mv: %s is a directory, not copied to %s\n",
133 fdf = open(fromname, OREAD);
135 fprint(2, "mv: can't open %s: %r\n", fromname);
139 dirt = dirstat(toname);
140 if(dirt != nil && (dirt->mode & DMAPPEND))
141 hardremove(toname); /* because create() won't truncate file */
144 fdt = create(toname, OWRITE, dirb->mode);
146 fprint(2, "mv: can't create %s: %r\n", toname);
150 stat = copy1(fdf, fdt, fromname, toname);
155 null.mtime = dirb->mtime;
156 null.mode = dirb->mode;
157 dirfwstat(fdt, &null); /* ignore errors; e.g. user none always fails */
158 if(remove(fromname) < 0){
159 fprint(2, "mv: can't remove %s: %r\n", fromname);
168 copy1(int fdf, int fdt, char *from, char *to)
173 while ((n = read(fdf, buf, sizeof buf)) > 0) {
174 n1 = write(fdt, buf, n);
176 fprint(2, "mv: error writing %s: %r\n", to);
181 fprint(2, "mv: error reading %s: %r\n", from);
188 split(char *name, char **pdir, char **pelem)
192 s = utfrrune(name, '/');
197 }else if(strcmp(name, "..") == 0){
207 samefile(char *a, char *b)
212 if(strcmp(a, b) == 0)
216 ret = (da != nil && db != nil &&
217 da->qid.type==db->qid.type &&
218 da->qid.path==db->qid.path &&
219 da->qid.vers==db->qid.vers &&
231 fprint(2, "mv: can't remove %s: %r\n", a);
234 while(remove(a) != -1)