Welcome, Guest. Please login or register.
Amiga Kit Amiga Store Iridium Banner AMIStore App Store A600 Memory

AuthorTopic: [C] Convert from volume name to device  (Read 962 times)

0 Members and 1 Guest are viewing this topic.

Offline nyteschayde

  • VIP / Donor - Lifetime Member
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 635
  • Total likes: 0
    • http://www.nyteshade.com
[C] Convert from volume name to device
« on: February 04, 2018, 05:53:54 AM »
So I am trying to figure out how to get the device name from a volume name in 1.3 (v34) friendly fashion. I know I can get the current directory using something like this:

Code: [Select]


/* Open libs above */
if (ExecBase && DOSBase) {
  struct CommandLineInterface *cli = Cli();
  /* also obtainable from BADDR(((struct Process *)FindTask(NULL))->pr_CLI); */
 

  printf("Current dir: %s\n", BSTRtoSTR(cli->cli_SetName))
}



Where fetching the volume name would involve everything up to the ":" in the current directory string. But I still cannot seem to find a V34 way to translate this into a device name.

Ideally, I'd like a CLI command that reports the device name of the disk it is run from.

Ideas? I'm tired and have been combing through the autodocs and headers and blindly testing stuff with GCC but haven't had much luck with this last hurdle.
Senior MTS Software Engineer with PayPal
Amigas: A1200T 060/603e PPC • A1200T 060 • A4000D 040 • A3000 (x2) • A2000 Vamp/V2 • A1200 (x4) • A1000 (x3) • A600 Vamp/V1 • A500
 

Offline Thomas Richter

Re: [C] Convert from volume name to device
« Reply #1 on: February 04, 2018, 11:22:52 AM »
Quote from: nyteschayde;835744
So I am trying to figure out how to get the device name from a volume name in 1.3 (v34) friendly fashion.
From a volume name or from a lock? From a volume name, you need to iterate through the DosList twice (struct DosInfo *)(BADDR((DOSBase->dl_Root->rn_Info)))->di_DevInfo, documented in dos/dosextens.h (or libraries/dosextens.h in 1.3), then search for the entry whose dol_Name is identical to that of the volume you are looking for and whose type is doslist->dol_Type == DLT_VOLUME.  From there, get doslist->dol_Task. Then iterate through the same list again, but this time check for doslist->dol_Type == DLT_DEVICE and whose doslist->dol_Task is identical to the pointer you found during the first scan. doslist->dol_Name is then the device name you are looking for, without a trailing colon.

Under 1.3, this list is Forbid()-locked. Under 2.0 and above, it is LockDosList(). You wand a read-lock on devices and volumes.

Cli()->cli_SetName is only what is used for the prompt by the shell, but does not necessarily reflect the CurrentDir() of the process right now, nor does the process has to have a CLI. If started from workbench, Cli() (or proc->pr_CommandLineInterface) is 0.
 

Offline olsen

Re: [C] Convert from volume name to device
« Reply #2 on: February 04, 2018, 11:29:06 AM »
Quote from: nyteschayde;835744
So I am trying to figure out how to get the device name from a volume name in 1.3 (v34) friendly fashion. I know I can get the current directory using something like this:

Code: [Select]

/* Open libs above */
if (ExecBase && DOSBase) {
  struct CommandLineInterface *cli = Cli();
  /* also obtainable from BADDR(((struct Process *)FindTask(NULL))->pr_CLI); */
 

  printf("Current dir: %s\n", BSTRtoSTR(cli->cli_SetName))
}


Where fetching the volume name would involve everything up to the ":" in the current directory string. But I still cannot seem to find a V34 way to translate this into a device name.

Ideally, I'd like a CLI command that reports the device name of the disk it is run from.

Ideas? I'm tired and have been combing through the autodocs and headers and blindly testing stuff with GCC but haven't had much luck with this last hurdle.

Careful, volume names are not necessarily unique. Your best bet here is to get a lock on the volume you are interested in and use that information to find the device which that specific volume is associated with (device names are unique).

Careful about cli_SetName, too, because the contents of that string may not be sound. The CD command may update it, but the name of the current directory is not reliably tied to the current directory of the shell. For example, if you run a program in the shell, it could by accident or design change the current directory when exiting. The cli_SetName contents will then no longer reflect the state of things.

As for some handy code to help you along, I think I can knock something together which should be useful to you :)  The reason why you drew a blank when checking up the autodocs and headers is likely due to the fact that the relevant information is deeply buried within dos.library, and they do things differently there, if at all. The 1.3 autodocs do not cover the relevant dos.library data structures, and the dos.library header files assume familiarity with the data structure contents rather than provide guidance for becoming familiar with them.
 

Offline olsen

Re: [C] Convert from volume name to device
« Reply #3 on: February 04, 2018, 11:47:15 AM »
Quote from: nyteschayde;835744
So I am trying to figure out how to get the device name from a volume name in 1.3 (v34) friendly fashion. I know I can get the current directory using something like this:

Here you go, this should get the job done:

Code: [Select]
#include <libraries/dos.h>
#include <libraries/dosextens.h>

#include <string.h>
#include <stdio.h>

extern struct DosLibrary * DOSBase;

#define ZERO ((BPTR)NULL)

int
main(argc,argv)
int argc;
char **argv;
{
   if(argc > 1)
   {
      BPTR lock;

      lock = Lock(argv[1], SHARED_LOCK);
      if(lock != ZERO)
      {
         struct DosInfo * di = (struct DosInfo *)BADDR(DOSBase->dl_Root->rn_Info);
         struct FileLock * fl = (struct FileLock *)BADDR(lock);
         struct DevInfo * dvi;
         char device_name[256];
         BOOL found_device = FALSE;

         Forbid();

         for(dvi = (struct DevInfo *)BADDR(di->di_DevInfo) ;
             dvi != NULL ;
             dvi = (struct DevInfo *)BADDR(dvi->dvi_Next))
         {
            if(dvi->dvi_Type == DLT_DEVICE && dvi->dvi_Task == fl->fl_Task)
            {
               UBYTE * name = BADDR(dvi->dvi_Name);
               int name_len;

               name_len = name[0];
               memcpy(device_name,&name[1],name_len);
               device_name[name_len] = '\0';

               found_device = TRUE;
               break;
            }
         }

         Permit();

         UnLock(lock);

         if(found_device)
            printf(&quot;\&quot;%s\&quot; -> %s\n&quot;,argv[1],device_name);
         else
            printf(&quot;\&quot;%s\&quot; not associated with a file system device\n&quot;,argv[1]);
      }
      else
      {
         printf(&quot;Cannot lock \&quot;%s\&quot; (error code = %d).\n&quot;, argv[1], IoErr());
      }
   }

   return(0);
}

This should be about as "old school" as it can get, although I have not tried to compile it with Aztec 'C' 3.6a yet...

Here is a complete example which does exactly what you requested, and which only uses the name of the volume to find a matching device name (there may be more than one):

Code: [Select]
#include
#include

#include
#include
#include

extern struct DosLibrary * DOSBase;

#define ZERO ((BPTR)NULL)
#define SAME (0)

int
strncmp_i(s1, s2, n)
char *s1;
char *s2;
int n;
{
   int result = 0;

   if(s1 != s2)
   {
      int c1,c2;

      while(n-- > 0)
      {
         c1 = toupper(*(unsigned char *)s1);
         c2 = toupper(*(unsigned char *)s2);

         if(c1 == c2)
         {
            if(c1 == '\0')
               break;

            s1++;
            s2++;
         }
         else
         {
            result = c1 - c2;
            break;
         }
      }
   }

   return(result);
}

int
main(argc,argv)
int argc;
char **argv;
{
   if(argc > 1)
   {
      char volume_name[256];
      int volume_name_len;
      char * colon_character;
      struct DosInfo * di = (struct DosInfo *)BADDR(DOSBase->dl_Root->rn_Info);
      struct DeviceList * first_volume = NULL;
      struct DeviceList * dl;
      char device_name[256];
      BOOL found_device = FALSE;
      int num_matching_volumes = 0;

      volume_name_len = strlen(argv[1]);
      if(volume_name_len >= sizeof(volume_name))
         volume_name_len = sizeof(volume_name)-1;

      memcpy(volume_name,argv[1],volume_name_len);
      volume_name[volume_name_len] = '\0';

      colon_character = strchr(volume_name,':');
      if(colon_character != NULL)
      {
         (*colon_character) = '\0';
         volume_name_len = strlen(volume_name);
      }

      Forbid();

      for(dl = (struct DeviceList *)BADDR(di->di_DevInfo) ;
          dl != NULL ;
          dl = (struct DeviceList *)BADDR(dl->dl_Next))
      {
         if(dl->dl_Type == DLT_VOLUME)
         {
            UBYTE * name = BADDR(dl->dl_Name);
            int name_len;

            name_len = name[0];

            if(name_len != volume_name_len)
               continue;

            if(strncmp_i(volume_name,&name[1],name_len) != SAME)
               continue;

            if(first_volume == NULL)
               first_volume = dl;

            num_matching_volumes++;
         }
      }

      if(num_matching_volumes > 0)
      {
         struct DevInfo * dvi;

         for(dvi = (struct DevInfo *)BADDR(di->di_DevInfo) ;
             dvi != NULL ;
             dvi = (struct DevInfo *)BADDR(dvi->dvi_Next))
         {
            if(dvi->dvi_Type == DLT_DEVICE && dvi->dvi_Task == first_volume->dl_Task)
            {
               UBYTE * name = BADDR(dvi->dvi_Name);
               int name_len;

               name_len = name[0];
               memcpy(device_name,&name[1],name_len);
               device_name[name_len] = '\0';

               found_device = TRUE;
               break;
            }
         }
      }

      Permit();

      if(num_matching_volumes > 0)
      {
         if(found_device)
         {
            if(num_matching_volumes == 1)
            {
               printf("\"%s\" -> %s\n",volume_name,device_name);
            }
            else
            {
               printf("\"%s\" -> %s; %d volumes are named \"%s\"\n",volume_name,
                   device_name,num_matching_volumes,volume_name);
            }
         }
         else
         {
            printf("\"%s\" not associated with a system device\n", volume_name);
         }
      }
      else
      {
         printf("Cannot find volume named \"%s\".\n", volume_name);
      }
   }

   return(0);
}
« Last Edit: February 04, 2018, 05:18:02 PM by olsen »
 

Offline nyteschayde

  • VIP / Donor - Lifetime Member
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 635
  • Total likes: 0
    • http://www.nyteshade.com
Re: [C] Convert from volume name to device
« Reply #4 on: February 04, 2018, 06:27:45 PM »
Quote from: olsen;835755
Here you go, this should get the job done:


Thanks! I'll play with these today!!
Senior MTS Software Engineer with PayPal
Amigas: A1200T 060/603e PPC • A1200T 060 • A4000D 040 • A3000 (x2) • A2000 Vamp/V2 • A1200 (x4) • A1000 (x3) • A600 Vamp/V1 • A500
 

Offline nyteschayde

  • VIP / Donor - Lifetime Member
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 635
  • Total likes: 0
    • http://www.nyteshade.com
Re: [C] Convert from volume name to device
« Reply #5 on: February 04, 2018, 06:29:52 PM »
Quote from: olsen;835754
Careful, volume names are not necessarily unique. Your best bet here is to get a lock on the volume you are interested in and use that information to find the device which that specific volume is associated with (device names are unique).

Careful about cli_SetName, too, because the contents of that string may not be sound. The CD command may update it, but the name of the current directory is not reliably tied to the current directory of the shell. For example, if you run a program in the shell, it could by accident or design change the current directory when exiting. The cli_SetName contents will then no longer reflect the state of things.

As for some handy code to help you along, I think I can knock something together which should be useful to you :)  The reason why you drew a blank when checking up the autodocs and headers is likely due to the fact that the relevant information is deeply buried within dos.library, and they do things differently there, if at all. The 1.3 autodocs do not cover the relevant dos.library data structures, and the dos.library header files assume familiarity with the data structure contents rather than provide guidance for becoming familiar with them.


Sheesh, tell me about it! Thanks. I'd love finding more about this stuff. I have Amigas ranging from base A1000s to fully modded A3/4000s and A1200s. I'm making a dev environment to my liking for the A1000 hence the 1.3 related stuff (not saying an A1000 can't run >=2.0)
Senior MTS Software Engineer with PayPal
Amigas: A1200T 060/603e PPC • A1200T 060 • A4000D 040 • A3000 (x2) • A2000 Vamp/V2 • A1200 (x4) • A1000 (x3) • A600 Vamp/V1 • A500
 

Offline psxphill

Re: [C] Convert from volume name to device
« Reply #6 on: February 04, 2018, 10:12:37 PM »
Quote from: nyteschayde;835772
I'm making a dev environment to my liking for the A1000 hence the 1.3 related stuff (not saying an A1000 can't run >=2.0)


I agree, if you can make software that runs on all versions then it's kinda cool to do so. Bonus points if it can also make use of later OS features.

Personally I'd even try to support the alpha versions.
 

Offline olsen

Re: [C] Convert from volume name to device
« Reply #7 on: February 05, 2018, 09:54:02 AM »
Quote from: psxphill;835781
I agree, if you can make software that runs on all versions then it's kinda cool to do so. Bonus points if it can also make use of later OS features.

Personally I'd even try to support the alpha versions.


Be careful of what you wish for. The Kickstart 1.x APIs were pretty rough going, which is particularly evident for the dos.library. The dos.library (and its associated disk-based software, such as the shell commands) kept evolving through Kickstart 1.3. Not many people know how much work went into dos.library post-Kickstart 1.2, but it's among the few areas of Kickstart 1.3 which saw the largest number of changes. From what I can tell the changes are mostly bug fixes.

By the time Kickstart 1.3 came around documentation for dos.library had improved considerably, but there were still major gaps (e.g. how did the shell interface work, how did the file system interface work, etc.). As an application software developer you could finally get by, knowing why certain data structures had to be aligned to long-word memory boundaries, why strings passed to dos.library could not be longer than 255 characters, why dos.library internal pointers had to be translated, why you needed at least 4000 bytes of stack space to be safe when calling dos.library functions and how the most important "documented" data structures would hang together.

Still, I suspect that the further back in time you go, the more surprises will be waiting for you in the dos.library data structures and its inner workings. The same would of course be true for all the operating system components, but dos.library is the most obscure among its peers. Not by design, but more or less by accident. If memory serves, integrating what became dos.library and the shell commands into the Amiga operating system was one of the significant reasons why Kickstart 1.2 took so long to come around.
 

Offline nyteschayde

  • VIP / Donor - Lifetime Member
  • Hero Member
  • *****
  • Join Date: Mar 2002
  • Posts: 635
  • Total likes: 0
    • http://www.nyteshade.com
Re: [C] Convert from volume name to device
« Reply #8 on: February 05, 2018, 03:21:56 PM »
This is fascinating, but all the traces to what I have seen thus far point to every bit of truth you have spoken about above. I do not need to do a lot in 1.3 and I do not need to go further back than 1.3, though I do have an A500 with 1.2 ROMs, but understanding why things work the way they do is both fun and enlightening. In fact the main reason why I requested volume name to device name conversion was that I could only seem to find docs on getting the volume name. V36 up has so many more calls available for accessing things like this.

I will start a thread about message ports soon too and some of the weirdness I am seeing there. Thanks for such comprehensive answers.
« Last Edit: February 05, 2018, 03:24:25 PM by nyteschayde »
Senior MTS Software Engineer with PayPal
Amigas: A1200T 060/603e PPC • A1200T 060 • A4000D 040 • A3000 (x2) • A2000 Vamp/V2 • A1200 (x4) • A1000 (x3) • A600 Vamp/V1 • A500
 

Offline psxphill

Re: [C] Convert from volume name to device
« Reply #9 on: February 05, 2018, 11:09:37 PM »
Quote from: olsen;835792
If memory serves, integrating what became dos.library and the shell commands into the Amiga operating system was one of the significant reasons why Kickstart 1.2 took so long to come around.


dos.library was in all the kickstarts.

Kickstart 1.2 had to wait for the A500/A2000 launch
 

Offline Thomas Richter

Re: [C] Convert from volume name to device
« Reply #10 on: February 06, 2018, 06:27:39 AM »
Quote from: psxphill;835804
dos.library was in all the kickstarts.

Kickstart 1.2 had to wait for the A500/A2000 launch

Yes, but not in the shape we have it today. In 1.3, a couple of internals changed: We got resident commands (NetHand in DosInfo was changed, the shell was changed) and the boot process changed. In 2.04, the whole thing was rewritten in Assembly and C, and dos moved away from bcpl. What happened from 1.1 to 1.2 I do not know.
 

Offline olsen

Re: [C] Convert from volume name to device
« Reply #11 on: February 06, 2018, 09:39:11 AM »
Quote from: psxphill;835804
dos.library was in all the kickstarts.

Kickstart 1.2 had to wait for the A500/A2000 launch

The flip side is that Commodore needed to ship these machines with ROMs, and Kickstart 1.2 had to be sufficiently robust to permit this. The dos.library was the "youngest" large and complex operating system component, and making it work sufficiently well took longer and involved more developers than expected (if memory serves). Work on dos.library specifically still took place until August/September 1986, with Dr. Tim King still being involved in the process.