How do I query information for a link?

This forum is for general developer support questions.

How do I query information for a link?

Postby colinward » Mon Aug 01, 2016 7:47 am

Hello.

I have a C++ support class that can be used for querying directory contents on multiple platforms. You call it and it returns a list of objects with information about the files present in the directory. It is cross platform and works on Amiga OS, Linux and Windows. Each entry returned will be in a structure like the following:

struct TEntry
{
char *Name;
char *Link;
bool IsLink;
...
};

If a file is not a link then Name will point to its name, Link will be NULL and IsLink will be false.

If a file *is* a link then Name will point to the name of the source link, Link will point to the name of the file the link points to and IsLink will be true.

On Linux and Windows you can control whether a link is dereferenced or not when you query a file. On Linux, lstat() queries info about the link and stat() resolves the link and queries info about the file the link points to. On Windows you can control this behaviour passing the FILE_FLAG_OPEN_REPARSE_POINT to CreateFile().

On Amiga OS I cannot find any such mechanism. IDOS->ExamineObjectTags() always dereferences the link and does not fill out the Link member of the ExamineData structure. Ok, I could use IDOS->ExamineDir() to iterate through all entries in the directory but this is an ugly workaround and has performance implications.

Any ideas?
colinward
Beta Tester
Beta Tester
 
Posts: 8
Joined: Sun Jan 06, 2013 10:29 am

Re: How do I query information for a link?

Postby chris » Mon Aug 01, 2016 4:23 pm

apparently LockTagList() might help: http://www.amigans.net/modules/xforum/v ... e=0&mode=0

I don't know if we have access to that yet, I don't have the SDK to hand although I'm sure it has been updated since 2012.
chris
 
Posts: 545
Joined: Sat Jun 18, 2011 12:05 pm

Re: How do I query information for a link?

Postby xenic » Mon Aug 01, 2016 6:14 pm

colinward wrote:On Amiga OS I cannot find any such mechanism. IDOS->ExamineObjectTags() always dereferences the link and does not fill out the Link member of the ExamineData structure. Ok, I could use IDOS->ExamineDir() to iterate through all entries in the directory but this is an ugly workaround and has performance implications.

Here's some code I used last year to test LockTags():
Code: Select all
/* Compile: gcc -O2 checklinks.c -o checklinks -Wall -lauto */

#include <proto/exec.h>
#include <proto/dos.h>

struct RDArgs *argsdata;

enum
{
   ARG_PATH, ARG_MAX
};

int main(int argc, char **argv)
{
   uint32 imask = 0;
   BPTR lock = 0;
   STRPTR fpath = NULL;
   int32 args[ARG_MAX] = {0};

   if (argc == 0)
   {
      IDOS->PutErrStr("Error: Shell program\n");
      return(RETURN_ERROR);
   }

   argsdata = IDOS->ReadArgs("PATH/A", args, NULL);
   if (!argsdata)
   {
      IDOS->PrintFault(IDOS->IoErr(), "Error:");
      return(RETURN_ERROR);
   }

   fpath = (char *)args[ARG_PATH];
   lock = IDOS->LockTags(LK_Name, fpath, LK_InfoMask, &imask, TAG_DONE);
   if (lock)
   {
      if (imask & LOCKF_SOFTLINK_MIDPART)
      {
         IDOS->Printf("There is a link in the given path\n");
      }

      if (imask & LOCKF_SOFTLINK_ENDPART)
      {
         IDOS->Printf("The last component of the path is a link\n");
      }
      else
      {
         IDOS->Printf("The path contains NO links\n");
      }

      IDOS->UnLock(lock);
   }
   else
   {
      IDOS->PrintFault(IDOS->IoErr(), "Error:");
      IDOS->FreeArgs(argsdata);
      return(RETURN_ERROR);
   }

   IDOS->FreeArgs(argsdata);
   return(RETURN_OK);
}


When I read the autodoc I wasn't sure if the LOCKF_SOFTLINK_MIDPART and LOCKF_SOFTLINK_ENDPART flags were mutually exclusive. Apparently they are not.
AmigaOne X1000 with 2GB memory - OS4.1 FE
xenic
 
Posts: 978
Joined: Sun Jun 19, 2011 1:06 am

Re: How do I query information for a link?

Postby colinw » Tue Aug 02, 2016 1:49 am

colinward wrote:Hello.
...
On Amiga OS I cannot find any such mechanism. IDOS->ExamineObjectTags() always dereferences the link
and does not fill out the Link member of the ExamineData structure.
Ok, I could use IDOS->ExamineDir() to iterate through all entries in the directory but this is an ugly workaround
and has performance implications.

Any ideas?

Yes...

Firstly, an operation on a link is equivalent to the same operation on the target object.

There are only three DOS functions that directly affect links themselves, those being;
IDOS->Delete(), IDOS->MakeLink() and conditionally IDOS->Rename().

The reason IDOS->ExamineObjectTags() returns information only on the target object of the link
is because the IDOS->Lock() function itself resolved the link when you called it, or called internally
when using the EX_StringInputName tag, so, you are getting information on what you asked for.

ExamineDir() returns information about links in a directlory because the reference lock was on
the parent directory, not on the link reference itself.

LockTags() is the only function that allows you to reliably differentiate a soft link name from a real object name.
Differentiating hardlinks is a little more complex because they are done inside the filesystem itself and are
transparent to the dos.library layer. (I have code to do this if you need it.)

Links are not "objects" in themselves, even if they may be treated as such inside a filesystem for
implementation purposes, outside of a filesystem context they are simply references to "real" objects
and as such, they have no auxilliary meta information other than target data and maybe a creation date.

There is no way to change meta-data on a link itself because all the IDOS->SetXXX() functions work
only on the target object.
User avatar
colinw
AmigaOS Core Developer
AmigaOS Core Developer
 
Posts: 156
Joined: Mon Aug 15, 2011 10:20 am
Location: Brisbane, QLD. Australia.

Re: How do I query information for a link?

Postby colinw » Thu Aug 04, 2016 4:53 am

xenic wrote:Here's some code I used last year to test LockTags():
[...]
When I read the autodoc I wasn't sure if the LOCKF_SOFTLINK_MIDPART and LOCKF_SOFTLINK_ENDPART flags
were mutually exclusive. Apparently they are not.


You are correct, they are not, because you can have up to 15 softlinks in a path, eg: "vol:dirlink/filelink"
In this case both flags would be set.

You also have two additional tags to use with Locktags() for softlinks besides the lk_infomask, here's the autodoc;

LK_ResolveSL (int32) -- Optional switch to control automatic softlink
resolution, when this tag is set to FALSE, if the object
the LK_Name references is a softlink, this function will
return failure with IoErr() set to ERROR_IS_SOFT_LINK,
rather than performing the normal automatic resolution.
(Default; TRUE when tag is not specified) (Added 53.117)

LK_SoftLinks (uint32 *) -- Optional pointer to a storage area that is
the sizeof(uint32).
On success, the value pointed to, will contain the number
of softlinks resolved in the supplied path/name string.
0 will be returned when there are no softlinks.
(Currently 15 softlinks are the maximum for a path.)
(Default; NULL)
User avatar
colinw
AmigaOS Core Developer
AmigaOS Core Developer
 
Posts: 156
Joined: Mon Aug 15, 2011 10:20 am
Location: Brisbane, QLD. Australia.

Re: How do I query information for a link?

Postby tesla » Sat Aug 06, 2016 9:41 am

Clib2 implements a couple of functions you might want to have a look at. I think the files stat_lock.c and unistd_readlink.c might be the most interesting to start with.
tesla
 
Posts: 1
Joined: Fri Jul 01, 2011 3:35 pm


Return to General Developer Support

Who is online

Users browsing this forum: No registered users and 1 guest