Subversion Repositories SvarDOS

Rev

Rev 989 | Rev 1050 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 989 Rev 990
1
/* This file is part of the SvarCOM project and is published under the terms
1
/* This file is part of the SvarCOM project and is published under the terms
2
 * of the MIT license.
2
 * of the MIT license.
3
 *
3
 *
4
 * Copyright (C) 2021-2022 Mateusz Viste
4
 * Copyright (C) 2021-2022 Mateusz Viste
5
 *
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
8
 * to deal in the Software without restriction, including without limitation
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
 * and/or sell copies of the Software, and to permit persons to whom the
10
 * and/or sell copies of the Software, and to permit persons to whom the
11
 * Software is furnished to do so, subject to the following conditions:
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
12
 *
13
 * The above copyright notice and this permission notice shall be included in
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
14
 * all copies or substantial portions of the Software.
15
 *
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
22
 * DEALINGS IN THE SOFTWARE.
23
 */
23
 */
24
 
24
 
25
/*
25
/*
26
 * rename/ren
26
 * rename/ren
27
 */
27
 */
28
 
28
 
29
static enum cmd_result cmd_rename(struct cmd_funcparam *p) {
29
static enum cmd_result cmd_rename(struct cmd_funcparam *p) {
30
  char *src = p->BUFFER;
30
  char *src = p->BUFFER;
31
  char *dst = p->BUFFER + 256;
31
  char *dst = p->BUFFER + 256;
32
  char *buff1 = p->BUFFER + 512;
32
  char *buff1 = p->BUFFER + 512;
33
  char *buff2 = p->BUFFER + 1024;
33
  char *buff2 = p->BUFFER + 1024;
34
  unsigned short i, fnameoffset;
34
  unsigned short i, fnameoffset;
35
  struct DTA *dta = (void *)0x80; /* use default DTA in PSP */
35
  struct DTA *dta = (void *)0x80; /* use default DTA in PSP */
36
 
36
 
37
  if (cmd_ishlp(p)) {
37
  if (cmd_ishlp(p)) {
38
    nls_outputnl(25,0); /* "Renames a file" */
38
    nls_outputnl(25,0); /* "Renames a file" */
39
    outputnl("");
39
    outputnl("");
40
    nls_outputnl(25,1); /* "RENAME [drive:][path]filename1 filename2" */
40
    nls_outputnl(25,1); /* "RENAME [drive:][path]filename1 filename2" */
41
    nls_outputnl(25,2); /* "REN [drive:][path]filename1 filename2" */
41
    nls_outputnl(25,2); /* "REN [drive:][path]filename1 filename2" */
42
    outputnl("");
42
    outputnl("");
43
    nls_outputnl(25,3); /* "Note that you cannot specify a new drive or (...)" */
43
    nls_outputnl(25,3); /* "Note that you cannot specify a new drive or (...)" */
44
    return(CMD_OK);
44
    return(CMD_OK);
45
  }
45
  }
46
 
46
 
47
  /* I expect exactly two arguments */
47
  /* I expect exactly two arguments */
48
  if (p->argc != 2) {
48
  if (p->argc != 2) {
49
    nls_outputnl(0,1); /* "Invalid syntax" */
49
    nls_outputnl(0,1); /* "Invalid syntax" */
50
    return(CMD_FAIL);
50
    return(CMD_FAIL);
51
  }
51
  }
52
 
52
 
53
  /* convert src to truename format */
53
  /* convert src to truename format */
54
  i = file_truename(p->argv[0], src);
54
  i = file_truename(p->argv[0], src);
55
  if (i != 0) {
55
  if (i != 0) {
56
    nls_outputnl_doserr(i);
56
    nls_outputnl_doserr(i);
57
    return(CMD_FAIL);
57
    return(CMD_FAIL);
58
  }
58
  }
59
 
59
 
60
  /* copy src path to buffers and remember where the filename starts */
60
  /* copy src path to buffers and remember where the filename starts */
61
  fnameoffset = 0;
61
  fnameoffset = 0;
62
  for (i = 0;; i++) {
62
  for (i = 0;; i++) {
63
    buff1[i] = src[i];
63
    buff1[i] = src[i];
64
    buff2[i] = src[i];
64
    buff2[i] = src[i];
65
    if (buff1[i] == '\\') fnameoffset = i + 1;
65
    if (buff1[i] == '\\') fnameoffset = i + 1;
66
    if (buff1[i] == 0) break;
66
    if (buff1[i] == 0) break;
67
  }
67
  }
68
 
68
 
69
  /* now append dst filename to the buffer and validate it: cannot contain backslash, slash or ':' */
69
  /* now append dst filename to the buffer and validate it: cannot contain backslash, slash or ':' */
70
  for (i = 0;; i++) {
70
  for (i = 0;; i++) {
71
    switch (p->argv[1][i]) {
71
    switch (p->argv[1][i]) {
72
      case ':':
72
      case ':':
73
      case '\\':
73
      case '\\':
74
      case '/':
74
      case '/':
75
        nls_outputnl(25,4); /* "Invalid destination" */
75
        nls_outputnl(0,8); /* "Invalid destination" */
76
        return(CMD_FAIL);
76
        return(CMD_FAIL);
77
    }
77
    }
78
    buff1[fnameoffset + i] = p->argv[1][i];
78
    buff1[fnameoffset + i] = p->argv[1][i];
79
    if (buff1[fnameoffset + i] == 0) break;
79
    if (buff1[fnameoffset + i] == 0) break;
80
  }
80
  }
81
 
81
 
82
  /* apply truename to dest to normalize wildcards into ? chars */
82
  /* apply truename to dest to normalize wildcards into ? chars */
83
  i = file_truename(buff1, dst);
83
  i = file_truename(buff1, dst);
84
  if (i != 0) {
84
  if (i != 0) {
85
    nls_outputnl_doserr(i);
85
    nls_outputnl_doserr(i);
86
    return(CMD_FAIL);
86
    return(CMD_FAIL);
87
  }
87
  }
88
 
88
 
89
  /* we're good to go, src and dst should look somehow like that now:
89
  /* we're good to go, src and dst should look somehow like that now:
90
   * src   =   C:\TEMP\PATH\FILE????.TXT
90
   * src   =   C:\TEMP\PATH\FILE????.TXT
91
   * dst   =   C:\TEMP\PATH\FILE????.DOC
91
   * dst   =   C:\TEMP\PATH\FILE????.DOC
92
   * buff1 =   C:\TEMP\PATH\
92
   * buff1 =   C:\TEMP\PATH\
93
   * buff2 =   C:\TEMP\PATH\
93
   * buff2 =   C:\TEMP\PATH\
94
   * fnameoffset = 13
94
   * fnameoffset = 13
95
   *
95
   *
96
   * src is used for FindFirst/FindNext iterations, then buff1 is filled with
96
   * src is used for FindFirst/FindNext iterations, then buff1 is filled with
97
   * the source filename found by FindFirst/FindNext and buff2 is filled with
97
   * the source filename found by FindFirst/FindNext and buff2 is filled with
98
   * the destination file (with ?'s replaced by whatever is found at the same
98
   * the destination file (with ?'s replaced by whatever is found at the same
99
   * location in buff1).
99
   * location in buff1).
100
   */
100
   */
101
 
101
 
102
  i = findfirst(dta, src, 0);
102
  i = findfirst(dta, src, 0);
103
  if (i != 0) nls_outputnl_doserr(i);
103
  if (i != 0) nls_outputnl_doserr(i);
104
 
104
 
105
  while (i == 0) {
105
  while (i == 0) {
106
    /* write found fname into buff1 and dst fname into buff2 - both in FCB
106
    /* write found fname into buff1 and dst fname into buff2 - both in FCB
107
     * format (MYFILE  EXT) so it is easy to compare them */
107
     * format (MYFILE  EXT) so it is easy to compare them */
108
    file_fname2fcb(buff1 + fnameoffset, dta->fname);
108
    file_fname2fcb(buff1 + fnameoffset, dta->fname);
109
    file_fname2fcb(buff2 + fnameoffset, dst + fnameoffset);
109
    file_fname2fcb(buff2 + fnameoffset, dst + fnameoffset);
110
 
110
 
111
    /* scan buff2 fname for '?' and replace them with whatever is in buff1 */
111
    /* scan buff2 fname for '?' and replace them with whatever is in buff1 */
112
    for (i = fnameoffset; buff2[i] != 0; i++) {
112
    for (i = fnameoffset; buff2[i] != 0; i++) {
113
      if (buff2[i] == '?') buff2[i] = buff1[i];
113
      if (buff2[i] == '?') buff2[i] = buff1[i];
114
    }
114
    }
115
 
115
 
116
    /* fill buff1 with the 8+3 found file and convert the one in buff2 to 8+3 as well */
116
    /* fill buff1 with the 8+3 found file and convert the one in buff2 to 8+3 as well */
117
    file_fcb2fname(buff1 + fnameoffset, buff2 + fnameoffset);
117
    file_fcb2fname(buff1 + fnameoffset, buff2 + fnameoffset);
118
    strcpy(buff2 + fnameoffset, buff1 + fnameoffset);
118
    strcpy(buff2 + fnameoffset, buff1 + fnameoffset);
119
    strcpy(buff1 + fnameoffset, dta->fname);
119
    strcpy(buff1 + fnameoffset, dta->fname);
120
 
120
 
121
    /* buff1 contains now a fully resolved source and buff2 a proper destination */
121
    /* buff1 contains now a fully resolved source and buff2 a proper destination */
122
    #if 0  /* DEBUG ("if 1" to enable) */
122
    #if 0  /* DEBUG ("if 1" to enable) */
123
    output(buff1);
123
    output(buff1);
124
    output(" -> ");
124
    output(" -> ");
125
    outputnl(buff2);
125
    outputnl(buff2);
126
    #endif
126
    #endif
127
    /* call DOS to do the actual job */
127
    /* call DOS to do the actual job */
128
    i = 0;
128
    i = 0;
129
    _asm {
129
    _asm {
130
      push ax
130
      push ax
131
      push di
131
      push di
132
      push dx
132
      push dx
133
      push es
133
      push es
134
 
134
 
135
      mov ah, 0x56  /* rename file: DS:DX=ASCIIZ of src  ES:DI=ASCIIZ of dst */
135
      mov ah, 0x56  /* rename file: DS:DX=ASCIIZ of src  ES:DI=ASCIIZ of dst */
136
      push ds
136
      push ds
137
      pop es
137
      pop es
138
      mov dx, buff1
138
      mov dx, buff1
139
      mov di, buff2
139
      mov di, buff2
140
      int 0x21      /* CF clear on success, otherwise err code in AX */
140
      int 0x21      /* CF clear on success, otherwise err code in AX */
141
      jnc DONE
141
      jnc DONE
142
      mov [i], ax   /* copy error code to i */
142
      mov [i], ax   /* copy error code to i */
143
      DONE:
143
      DONE:
144
 
144
 
145
      pop es
145
      pop es
146
      pop dx
146
      pop dx
147
      pop di
147
      pop di
148
      pop ax
148
      pop ax
149
    }
149
    }
150
    if (i != 0) {
150
    if (i != 0) {
151
      output(buff1 + fnameoffset);
151
      output(buff1 + fnameoffset);
152
      output(" -> ");
152
      output(" -> ");
153
      output(buff2 + fnameoffset);
153
      output(buff2 + fnameoffset);
154
      output("  ");
154
      output("  ");
155
      nls_outputnl_doserr(i);
155
      nls_outputnl_doserr(i);
156
    }
156
    }
157
    /* next please */
157
    /* next please */
158
    i = findnext(dta);
158
    i = findnext(dta);
159
  }
159
  }
160
 
160
 
161
  return(CMD_OK);
161
  return(CMD_OK);
162
}
162
}
163
 
163