Subversion Repositories SvarDOS

Rev

Rev 421 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
399 mateuszvis 1
/*
2
 * vol [drive:]
3
 */
4
 
5
static void cmd_vol_internal(unsigned char drv, char *buff) {
6
  unsigned short *buff16 = (void *)(buff);
7
  unsigned short err = 0;
8
  struct DTA *dta = (void *)0x80; /* use the default DTA at location 80h in PSP */
9
 
10
  outputnl("");  /* start with an empty line to mimic MS-DOS */
11
 
12
  /* look for volume label in root dir via a FindFirst call */
13
  sprintf(buff, "%c:\\????????.???", drv + 'A');
14
  _asm {
15
    push ax
16
    push cx
17
    push dx
18
    mov [err], 0    /* preset errflag to zero */
19
    mov ah, 0x4e  /* FindFirst */
20
    mov dx, buff
21
    mov cx, 0x08  /* match volume labels only */
22
    int 0x21      /* dta filled or CF set on error */
23
    jnc DONE
24
    mov [err], ax
25
    DONE:
26
    pop dx
27
    pop cx
28
    pop ax
29
  }
30
 
31
  if (err != 0) {
32
    sprintf(buff, "Volume in drive %c has no label", drv + 'A');
33
  } else {
34
    /* if label > 8 chars then drop the dot (DRIVE_LA.BEL -> DRIVE_LABEL) */
35
    if (strlen(dta->fname) > 8) memmove(dta->fname + 8, dta->fname + 9, 4);
36
    sprintf(buff, "Volume in drive %c is %s", drv + 'A', dta->fname);
37
  }
38
  outputnl(buff);
39
 
40
  /* try to fetch the disk's serial number (DOS 4+ internal call) */
41
  err = 0;
42
  _asm {
43
    push ax
44
    push bx
45
    push dx
46
    mov ax, 0x6900
47
    mov bl, drv  /* A=1, B=2, etc */
48
    inc bl       /* adjust BL to +1 since drv is 0-based (A=0, B=1, etc) */
49
    xor bh, bh   /* "info level", must be 0 */
50
    mov dx, buff /* pointer to a location where a DiskInfo struct will be written */
51
    int 0x21
52
    jnc DONE
53
    mov [err], ax  /* err code */
54
    DONE:
55
    pop dx
56
    pop bx
57
    pop ax
58
  }
59
  /* Format of DiskInfo struct (source: RBIL)
60
   Offset  Size    Description (Table 01766)
61
   00h     WORD    0000h (info level)
62
   02h     DWORD   disk serial number (binary)
63
   06h  11 BYTEs   volume label or "NO NAME    " if none present
64
   11h   8 BYTEs   filesystem type */
65
  if ((err == 0) && (buff16[1] | buff16[2])) {
66
    sprintf(buff + 64, "Volume Serial Number is %04X-%04X", buff16[2], buff16[1]);
67
    outputnl(buff + 64);
68
  }
69
}
70
 
71
 
72
static int cmd_vol(struct cmd_funcparam *p) {
73
  char drv = 0;
74
  char curdrv = 0;
75
  unsigned short i;
76
 
77
  if (cmd_ishlp(p)) {
78
    outputnl("Displays the disk volume label and serial number, if they exist.");
79
    outputnl("");
80
    outputnl("VOL [drive:]");
81
    return(-1);
82
  }
83
 
84
  for (i = 0; i < p->argc; i++) {
85
    if (p->argv[i][0] == '/') {
86
      outputnl("Invalid switch");
87
      return(-1);
88
    }
89
    if (drv != 0) {
90
      outputnl("Too many parameters");
91
      return(-1);
92
    }
93
    if ((p->argv[i][0] == 0) || (p->argv[i][1] != ':') || (p->argv[i][2] != 0)) {
94
      outputnl("Invalid parameter format");
95
      return(-1);
96
    }
97
    drv = p->argv[i][0];
98
    /* convert drive letter to a value 1..x (1=A, 2=B, etc) */
99
    if ((drv >= 'a') && (drv <= 'z')) {
100
      drv -= 'a';
101
    } else {
102
      drv -= 'A';
103
    }
104
  }
105
 
106
  /* fetch current drive */
107
  _asm {
108
    push ax
109
    mov ah, 0x19  /* query default (current) disk */
110
    int 0x21      /* drive in AL (0=A, 1=B, etc) */
111
    mov [curdrv], al
112
    pop ax
113
  }
114
 
115
  /* if no drive specified, use the default one */
116
  if (drv == 0) {
117
    drv = curdrv;
118
  } else if (!isdrivevalid(drv)) { /* is specified drive valid? */
119
    outputnl("Invalid drive");
120
    return(-1);
121
  }
122
 
123
  cmd_vol_internal(drv, p->BUFFER);
124
 
125
  return(-1);
126
}