Subversion Repositories SvarDOS

Rev

Rev 399 | Rev 533 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
421 mateuszvis 1
/* This file is part of the SvarCOM project and is published under the terms
2
 * of the MIT license.
3
 *
4
 * Copyright (C) 2021 Mateusz Viste
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a
7
 * copy of this software and associated documentation files (the "Software"),
8
 * to deal in the Software without restriction, including without limitation
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
11
 * Software is furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
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,
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
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
22
 * DEALINGS IN THE SOFTWARE.
23
 */
24
 
399 mateuszvis 25
/*
26
 * vol [drive:]
27
 */
28
 
29
static void cmd_vol_internal(unsigned char drv, char *buff) {
30
  unsigned short *buff16 = (void *)(buff);
31
  unsigned short err = 0;
32
  struct DTA *dta = (void *)0x80; /* use the default DTA at location 80h in PSP */
33
 
34
  outputnl("");  /* start with an empty line to mimic MS-DOS */
35
 
36
  /* look for volume label in root dir via a FindFirst call */
37
  sprintf(buff, "%c:\\????????.???", drv + 'A');
38
  _asm {
39
    push ax
40
    push cx
41
    push dx
42
    mov [err], 0    /* preset errflag to zero */
43
    mov ah, 0x4e  /* FindFirst */
44
    mov dx, buff
45
    mov cx, 0x08  /* match volume labels only */
46
    int 0x21      /* dta filled or CF set on error */
47
    jnc DONE
48
    mov [err], ax
49
    DONE:
50
    pop dx
51
    pop cx
52
    pop ax
53
  }
54
 
55
  if (err != 0) {
56
    sprintf(buff, "Volume in drive %c has no label", drv + 'A');
57
  } else {
58
    /* if label > 8 chars then drop the dot (DRIVE_LA.BEL -> DRIVE_LABEL) */
59
    if (strlen(dta->fname) > 8) memmove(dta->fname + 8, dta->fname + 9, 4);
60
    sprintf(buff, "Volume in drive %c is %s", drv + 'A', dta->fname);
61
  }
62
  outputnl(buff);
63
 
64
  /* try to fetch the disk's serial number (DOS 4+ internal call) */
65
  err = 0;
66
  _asm {
67
    push ax
68
    push bx
69
    push dx
70
    mov ax, 0x6900
71
    mov bl, drv  /* A=1, B=2, etc */
72
    inc bl       /* adjust BL to +1 since drv is 0-based (A=0, B=1, etc) */
73
    xor bh, bh   /* "info level", must be 0 */
74
    mov dx, buff /* pointer to a location where a DiskInfo struct will be written */
75
    int 0x21
76
    jnc DONE
77
    mov [err], ax  /* err code */
78
    DONE:
79
    pop dx
80
    pop bx
81
    pop ax
82
  }
83
  /* Format of DiskInfo struct (source: RBIL)
84
   Offset  Size    Description (Table 01766)
85
   00h     WORD    0000h (info level)
86
   02h     DWORD   disk serial number (binary)
87
   06h  11 BYTEs   volume label or "NO NAME    " if none present
88
   11h   8 BYTEs   filesystem type */
89
  if ((err == 0) && (buff16[1] | buff16[2])) {
90
    sprintf(buff + 64, "Volume Serial Number is %04X-%04X", buff16[2], buff16[1]);
91
    outputnl(buff + 64);
92
  }
93
}
94
 
95
 
96
static int cmd_vol(struct cmd_funcparam *p) {
97
  char drv = 0;
98
  char curdrv = 0;
99
  unsigned short i;
100
 
101
  if (cmd_ishlp(p)) {
102
    outputnl("Displays the disk volume label and serial number, if they exist.");
103
    outputnl("");
104
    outputnl("VOL [drive:]");
105
    return(-1);
106
  }
107
 
108
  for (i = 0; i < p->argc; i++) {
109
    if (p->argv[i][0] == '/') {
110
      outputnl("Invalid switch");
111
      return(-1);
112
    }
113
    if (drv != 0) {
114
      outputnl("Too many parameters");
115
      return(-1);
116
    }
117
    if ((p->argv[i][0] == 0) || (p->argv[i][1] != ':') || (p->argv[i][2] != 0)) {
118
      outputnl("Invalid parameter format");
119
      return(-1);
120
    }
121
    drv = p->argv[i][0];
122
    /* convert drive letter to a value 1..x (1=A, 2=B, etc) */
123
    if ((drv >= 'a') && (drv <= 'z')) {
124
      drv -= 'a';
125
    } else {
126
      drv -= 'A';
127
    }
128
  }
129
 
130
  /* fetch current drive */
131
  _asm {
132
    push ax
133
    mov ah, 0x19  /* query default (current) disk */
134
    int 0x21      /* drive in AL (0=A, 1=B, etc) */
135
    mov [curdrv], al
136
    pop ax
137
  }
138
 
139
  /* if no drive specified, use the default one */
140
  if (drv == 0) {
141
    drv = curdrv;
142
  } else if (!isdrivevalid(drv)) { /* is specified drive valid? */
143
    outputnl("Invalid drive");
144
    return(-1);
145
  }
146
 
147
  cmd_vol_internal(drv, p->BUFFER);
148
 
149
  return(-1);
150
}