A few other code suggestions:

I prefer putting "fail" statements first, so the program can safely
exit early. This also keeps the "failure" message next to the test,
which I find easier to read.

For example, on line 107, you do a 'malloc' then test if you have a
value in line 109, but the "failure" message happens after all that
code, on lines 177-180:

    107             pcBuffer = malloc(SHRT_MAX + 1);
    108             /* If we have allocated memory */
    109             if (pcBuffer != NULL)
    110             {
[...]
    176             }
    177             else
    178             {
    179                 cprintf("Error. Cannot allocate memory.\r\n");
    180             }


I think it's better to write it like this:

pcBuffer = malloc(SHRT_MAX + 1);
if (pcBuffer == NULL)
{
  cprintf("Error. Cannot allocate memory.\r\n");
  return 1;
}

..then continue with the "success" code (currently lines 110-176).


Similarly, you do a test for disk free space on line 104, but the
"failure" message happens on lines 182-185:

    104                 if (_dos_getdiskfree_ext(cDrive - 'A' + 1,
&udtDiskFreeExt) == 0)
    105         {
[...]
    181         }
    182         else
    183         {
    184                 cprintf("Error. Cannot get free disk space for
%c:.\r\n", cDrive);
    185         }

I think it's more clear to write it the other way:

if (_dos_getdiskfree_ext(cDrive - 'A' + 1, &udtDiskFreeExt) != 0) {
  cprintf("Error. Cannot get free disk space for %c:.\r\n", cDrive);
  return 1;
}

..then continue with the "success" code (currently lines 105-181).



Writing code this way is basically a series of tests, followed by the
code that you can safely run, like this sample "do-nothing" program:

int main()
{
  if (argc != 2) {
    puts("bad command line usage");
    return 1;
  }

  if (failtest1) {
    puts("argv[1] is not a drive letter");
    return 2;
  }

  if (failtest2) {
    puts("drive does not exist");
    return 3;
  }

  if (failtest3) {
    puts("not enough free disk space");
    return 4;
  }

  if (failtest4) {
    puts("not enough memory");
    return 5;
  }

  /* things should be ok from here */

  ...

  return 0;
}


On Thu, Jan 30, 2025 at 9:08 AM Jim Hall <jh...@freedos.org> wrote:
>
> On Thu, Jan 30, 2025 at 6:01 AM Bitácora de Javier Gutiérrez Chamorro
> (Guti) via Freedos-devel <freedos-devel@lists.sourceforge.net> wrote:
> >
> > And now we have 2.01 too:
> >
> >
> > - Changed temporary file naming convention from ZEROFILL.XXX to 
> > ZEROXXXX.FIL in order to support up to 9999 files instead of 999 (Fritz 
> > Mueller).
> >
> > - Added a question at the end of the process to confirm deletion of 
> > temporary files  (Fritz Mueller).
> >
> > - Upgraded to UPX 4.2.4.
> >
> > - Minor code optimizations and cleanup.
>
>
> For the next update you make to Zerofill, I have a few suggestions:
>
> (1)
> At line 98, you do a test of 'argc' to see if 'main' has command line
> arguments. The 'else' for this is at the bottom, in lines 187-201.
> This code would be easier to read if you instead did a test for "not
> enough command line arguments" at top, and exit if not enough, like
> this:
>
> if (argc < 2) {
>         cprintf("ZEROFILL [drive:]\r\n\r\n");
>         cprintf("ZEROFILL writes zeros on the empty disk space for the
> selected drive. It helps\r\n");
>         cprintf("virtual machine, and disk compression softwares to
> compact the volume, and so\r\n");
>         cprintf("on reducing its disk usage.\r\n\r\n");
>         cprintf("Examples:\r\n\r\n");
>         cprintf("       ZEROFILL C:\r\n");
>         cprintf("       Will fill with zeros all available space in
> drive C.\r\n\r\n");
>         cprintf("More information at:\r\n\r\n");
>         cprintf("
> http://nikkhokkho.sourceforge.net/static.php?page=ZEROFILL\r\n";);
>         cprintf("Press ENTER to continue...");
>         getch();
>         cprintf("\r\n");
>         return 1;
> }
>
> ..then the rest of 'main' continues normally:
>
>         cDrive = toupper(argv[1][0]);
>         cprintf("Filling with zero empty space on drive %c:...\r\n", cDrive);
>         lTotalMb = 0;
> [..]
>
>
> Although the program doesn't actually use the arguments after the
> first one. The usage really is "zerofill d:" where "d:" is a drive
> letter like C: or D: or A:
>
> So I'd recommend 'if (argc != 2)'  instead.
>
>
> That code brings another suggestion:
>
> (2)
> I noticed on line 100 that you get the drive letter as toupper(argv[1][0])
>
> But this needs a few more checks before getting the drive letter. In
> one example, the user might have passed '/?' assuming they could get
> help, but this will instead get used as "drive" letter '/'. And that
> will break your math (currently at line 104) to get the drive by
> number, because you use 'cDrive - 'A' + 1' (which works correctly if
> argv[1][0] is a letter, because 'toupper(argv[1][0])' will return
> values like 'A' and 'B' and 'C' and so on).
>
> So I think you should make a test before you get there to see if the
> first argument looks like a drive letter. A simple test looks like
> this:
>
> int isdriveletter(const char *s)
> {
>     if (!isalpha(s[0])) {
>         return 0;                      /* not letter, or empty */
>     }
>
>     if (s[1] != ':') {
>         return 0;                      /* no trailing colon */
>     }
>
>     if (s[2] != 0) {
>         return 0;                      /* trailing data */
>     }
>
>     return 1;                          /* looks ok */
> }
>
> That doesn't test if a drive letter is valid (i.e. exists) but will
> tell you if a string looks like a drive letter ("A:" is okay, "c:" is
> okay, but "/?" will fail .. so will "-h" and "*:" and "[:" .. an empty
> string also fails).
>
> I'd insert this test after the 'if (argc != 2) { .. }' block I
> suggested above, and before the rest of the 'main' function:
>
> if (!isdriveletter(argv[1])) {
>   cprintf("%s not a drive letter\r\n", argv[1]);
>   return 1;
> }
>
> That way, "zerofill" (no args) will fail before you test the first
> arg, guaranteeing that 'argc' is 2, so there is an argv[1] to examine.
> Then the rest of your code (starting at current line 100) should be
> okay.


_______________________________________________
Freedos-devel mailing list
Freedos-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/freedos-devel

Reply via email to