Subversion Repositories SvarDOS

Rev

Rev 403 | Rev 412 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 403 Rev 409
Line 14... Line 14...
14
 * is not placed at the end of the copied file.
14
 * is not placed at the end of the copied file.
15
 *
15
 *
16
 * /V - Checks after the copy to assure that a file was copied correctly. If
16
 * /V - Checks after the copy to assure that a file was copied correctly. If
17
 * the copy cannot be verified, the program will display an error message.
17
 * the copy cannot be verified, the program will display an error message.
18
 * Using this option will result in a slower copying process.
18
 * Using this option will result in a slower copying process.
-
 
19
 *
-
 
20
 * special case: "COPY A+B+C+D" means "append B, C and D files to the A file"
-
 
21
 * if A does not exist, then "append C and D to B", etc.
19
 */
22
 */
20
 
23
 
21
struct copy_setup {
24
struct copy_setup {
22
  const char *src[64];
25
  const char *src[64];
23
  unsigned short src_count; /* how many sources are declared */
26
  unsigned short src_count; /* how many sources are declared */
-
 
27
  char dst[256];
24
  const char *dst;
28
  unsigned short dstlen;
25
  char src_asciimode[64];
29
  char src_asciimode[64];
26
  char dst_asciimode;
30
  char dst_asciimode;
27
  char last_asciimode; /* /A or /B impacts the file preceding it and becomes the new default for all files that follow */
31
  char last_asciimode; /* /A or /B impacts the file preceding it and becomes the new default for all files that follow */
28
  char verifyflag;
32
  char verifyflag;
29
  char lastitemwasplus;
33
  char lastitemwasplus;
30
  char databuf[BUFFER_SIZE - 512];
34
  char databuf[BUFFER_SIZE - 1024];
31
};
35
};
32
 
36
 
-
 
37
 
-
 
38
/* appends a backslash if path is a directory
-
 
39
 * returns the (possibly updated) length of path */
-
 
40
static unsigned short cmd_copy_addbkslash_if_dir(char *path) {
-
 
41
  unsigned short len;
-
 
42
  int attr;
-
 
43
  for (len = 0; path[len] != 0; len++);
-
 
44
  if (len == 0) return(0);
-
 
45
  if (path[len - 1] == '\\') return(len);
-
 
46
  /* */
-
 
47
  attr = file_getattr(path);
-
 
48
  if ((attr > 0) && (attr & DOS_ATTR_DIR)) {
-
 
49
    path[len++] = '\\';
-
 
50
    path[len] = 0;
-
 
51
  }
-
 
52
  return(len);
-
 
53
}
-
 
54
 
-
 
55
 
33
static int cmd_copy(struct cmd_funcparam *p) {
56
static int cmd_copy(struct cmd_funcparam *p) {
34
  struct copy_setup *setup = (void *)(p->BUFFER);
57
  struct copy_setup *setup = (void *)(p->BUFFER);
35
  unsigned short i;
58
  unsigned short i;
-
 
59
  unsigned short copiedcount_in = 0, copiedcount_out = 0; /* number of input/output copied files */
-
 
60
  struct DTA *dta = (void *)0x80; /* use DTA at default location in PSP */
36
 
61
 
37
  if (cmd_ishlp(p)) {
62
  if (cmd_ishlp(p)) {
38
    outputnl("Copies one or more files to another location.");
63
    outputnl("Copies one or more files to another location.");
39
    outputnl("");
64
    outputnl("");
40
    outputnl("COPY [/A|/B] source [/A|/B] [+source [/A|/B] [+...]] [destination [/A|/B]] [/V]");
65
    outputnl("COPY [/A|/B] source [/A|/B] [+source [/A|/B] [+...]] [destination [/A|/B]] [/V]");
Line 60... Line 85...
60
    if (p->argv[i][0] == '/') {
85
    if (p->argv[i][0] == '/') {
61
      if ((imatch(p->argv[i], "/a")) || (imatch(p->argv[i], "/b"))) {
86
      if ((imatch(p->argv[i], "/a")) || (imatch(p->argv[i], "/b"))) {
62
        setup->last_asciimode = 'b';
87
        setup->last_asciimode = 'b';
63
        if (imatch(p->argv[i], "/a")) setup->last_asciimode = 'a';
88
        if (imatch(p->argv[i], "/a")) setup->last_asciimode = 'a';
64
        /* */
89
        /* */
65
        if (setup->dst != NULL) {
90
        if (setup->dst[0] != 0) {
66
          setup->dst_asciimode = setup->last_asciimode;
91
          setup->dst_asciimode = setup->last_asciimode;
67
        } else if (setup->src_count != 0) {
92
        } else if (setup->src_count != 0) {
68
          setup->src_asciimode[setup->src_count - 1] = setup->last_asciimode;
93
          setup->src_asciimode[setup->src_count - 1] = setup->last_asciimode;
69
        }
94
        }
70
      } else if (imatch(p->argv[i], "/v")) {
95
      } else if (imatch(p->argv[i], "/v")) {
Line 77... Line 102...
77
    }
102
    }
78
 
103
 
79
    /* not a switch - must be either a source, a destination or a + */
104
    /* not a switch - must be either a source, a destination or a + */
80
    if (p->argv[i][0] == '+') {
105
    if (p->argv[i][0] == '+') {
81
      /* a plus cannot appear after destination or before first source */
106
      /* a plus cannot appear after destination or before first source */
82
      if ((setup->dst != NULL) || (setup->src_count == 0)) {
107
      if ((setup->dst[0] != 0) || (setup->src_count == 0)) {
83
        outputnl("Invalid syntax");
108
        outputnl("Invalid syntax");
84
        return(-1);
109
        return(-1);
85
      }
110
      }
86
      setup->lastitemwasplus = 1;
111
      setup->lastitemwasplus = 1;
87
      /* a plus may be immediately followed by a filename - if so, emulate
112
      /* a plus may be immediately followed by a filename - if so, emulate
Line 101... Line 126...
101
      setup->lastitemwasplus = 0;
126
      setup->lastitemwasplus = 0;
102
      continue;
127
      continue;
103
    }
128
    }
104
 
129
 
105
    /* must be a dst then */
130
    /* must be a dst then */
106
    if (setup->dst != NULL) {
131
    if (setup->dst[0] != 0) {
107
      outputnl("Invalid syntax");
132
      outputnl("Invalid syntax");
108
      return(-1);
133
      return(-1);
109
    }
134
    }
-
 
135
    if (file_truename(p->argv[i], setup->dst) != 0) {
-
 
136
      outputnl("Invalid destination");
110
    setup->dst = p->argv[i];
137
      return(-1);
-
 
138
    }
111
    setup->dst_asciimode = setup->last_asciimode;
139
    setup->dst_asciimode = setup->last_asciimode;
-
 
140
    /* if dst is a directory then append a backslash */
-
 
141
    setup->dstlen = cmd_copy_addbkslash_if_dir(setup->dst);
112
  }
142
  }
113
 
143
 
114
  /* DEBUG: output setup content ("if 1" to enable) */
144
  /* DEBUG: output setup content ("if 1" to enable) */
115
  #if 1
145
  #if 1
116
  printf("src: ");
146
  printf("src: ");
Line 121... Line 151...
121
  printf("\r\n");
151
  printf("\r\n");
122
  printf("dst: %s [%c]\r\n", setup->dst, setup->dst_asciimode);
152
  printf("dst: %s [%c]\r\n", setup->dst, setup->dst_asciimode);
123
  printf("verify: %s\r\n", (setup->verifyflag)?"ON":"OFF");
153
  printf("verify: %s\r\n", (setup->verifyflag)?"ON":"OFF");
124
  #endif
154
  #endif
125
 
155
 
-
 
156
  /* must have at least one source */
-
 
157
  if (setup->src_count == 0) {
-
 
158
    outputnl("Required parameter missing");
-
 
159
    return(-1);
-
 
160
  }
-
 
161
 
126
  /* TODO perform the operation based on setup directives */
162
  /* perform the operation based on setup directives:
-
 
163
   * iterate over every source and copy it to dest */
-
 
164
 
-
 
165
  for (i = 0; i < setup->src_count; i++) {
-
 
166
    unsigned short t;
-
 
167
    unsigned short databuflen;
-
 
168
    unsigned short pathendoffset;
-
 
169
 
-
 
170
    /* resolve truename of src and write it to buffer */
-
 
171
    t = file_truename(setup->src[i], setup->databuf);
-
 
172
    if (t != 0) {
-
 
173
      output(setup->src[i]);
-
 
174
      output(" - ");
-
 
175
      outputnl(doserr(t));
-
 
176
      continue;
-
 
177
    }
-
 
178
    databuflen = strlen(setup->databuf); /* remember databuf length */
-
 
179
 
-
 
180
    /* if length zero, skip (not sure why this would be possible, though) */
-
 
181
    if (databuflen == 0) continue;
-
 
182
 
-
 
183
    /* if src does not end with a backslash AND it is a directory then append a backslash */
-
 
184
    databuflen = cmd_copy_addbkslash_if_dir(setup->databuf);
-
 
185
 
-
 
186
    /* if src ends with a '\' then append *.* */
-
 
187
    if (setup->databuf[databuflen - 1] == '\\') {
-
 
188
      strcat(setup->databuf, "*.*");
-
 
189
    }
-
 
190
 
-
 
191
    /* remember where the path in databuf ends */
-
 
192
    for (t = 0; setup->databuf[t] != 0; t++) {
-
 
193
      if (setup->databuf[t] == '\\') pathendoffset = t + 1;
-
 
194
    }
-
 
195
 
-
 
196
    /* */
-
 
197
    if (findfirst(dta, setup->databuf, 0) != 0) {
-
 
198
      continue;
-
 
199
    }
-
 
200
 
-
 
201
    do {
-
 
202
      if (dta->attr & DOS_ATTR_DIR) continue; /* skip directories */
-
 
203
 
-
 
204
      /* compute full path/name of the file */
-
 
205
      strcpy(setup->databuf + pathendoffset, dta->fname);
-
 
206
 
-
 
207
      /* if there was no destination, then YOU are the destination now!
-
 
208
       * this handles situations like COPY a.txt+b.txt+c.txt */
-
 
209
      if (setup->dst[0] == NULL) {
-
 
210
        strcpy(setup->dst, setup->databuf);
-
 
211
        setup->dstlen = strlen(setup->dst);
-
 
212
        copiedcount_in++;
-
 
213
        copiedcount_out++;
-
 
214
        continue;
-
 
215
      }
-
 
216
 
-
 
217
      /* is dst ending with a backslash? then append fname to it */
-
 
218
      if (setup->dst[setup->dstlen - 1] == '\\') strcpy(setup->dst + setup->dstlen, dta->fname);
-
 
219
 
-
 
220
      /* now databuf contains the full source and dst contains the full dest... COPY TIME! */
-
 
221
 
-
 
222
      /* if dst file exists already -> overwrite it or append?
-
 
223
          - if dst is a dir (dstlen-1 points at a \\) -> overwrite
-
 
224
          - otherwise: if copiedcount_in==0 overwrite, else append */
-
 
225
      output(setup->databuf);
-
 
226
      if ((setup->dst[setup->dstlen - 1] == '\\') || (copiedcount_in == 0)) {
-
 
227
        output(" > ");
-
 
228
        copiedcount_out++;
-
 
229
      } else {
-
 
230
        output(" >> ");
-
 
231
      }
-
 
232
      outputnl(setup->dst);
-
 
233
 
-
 
234
      copiedcount_in++;
-
 
235
    } while (findnext(dta) == 0);
-
 
236
 
-
 
237
  }
-
 
238
 
-
 
239
  sprintf(setup->databuf, "%u file(s) copied", copiedcount_out);
-
 
240
  outputnl(setup->databuf);
127
 
241
 
128
  return(-1);
242
  return(-1);
129
}
243
}