How do I detect if a file is symbolic link?

Linux specific questions.
Post Reply
lassar
Posts: 306
Joined: Jan 17, 2006 1:35

How do I detect if a file is symbolic link?

Post by lassar »

How do I detect if a file is symbolic link?

Can you detect a symbolic link using DIR()?
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: How do I detect if a file is symbolic link?

Post by caseih »

No I don't believe so. What you need to do is call stat() on the filename. Everything you need is defined in the crt/sys/stat.bi include. See the C man page for stat for information on how to use it.
lassar
Posts: 306
Joined: Jan 17, 2006 1:35

Re: How do I detect if a file is symbolic link?

Post by lassar »

I was going the .bi files, and found readlink function.

Code: Select all

#LANG "fblite"

#include "file.bi"
#include "dir.bi"
#include "crt/linux/unistd.bi"

DECLARE FUNCTION GetRealink$(FilePath$)

PRINT "Get real path of /lib/libm.so.6"
DirName$ = GetRealink$("/lib/libm.so.6")
PRINT "DirName$ = ";DirName$

SLEEP
END

FUNCTION GetRealink$(FilePath$)
DIM Path AS ZSTRING * 1024
DIM Buffer AS ZSTRING * 1024
DIM PathPtr AS ZSTRING PTR
DIM BufferPtr AS ZSTRING PTR

PathPtr = @Path
BufferPtr = @Buffer
Path = FilePath$

Result% = Readlink(PathPtr, BufferPtr, 1023)
IF Result% > 0 THEN FUNCTION = Buffer
END FUNCTION
badidea
Posts: 2586
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: How do I detect if a file is symbolic link?

Post by badidea »

Code: Select all

#Include "crt/sys/types.bi"

#define whatever ulong 'BUG WITH dev_t ?

extern "C"
	type _stat
		st_dev as dev_t
		dummy1 as whatever
		st_ino as ino_t
		st_mode as mode_t
		st_nlink as nlink_t
		st_uid as uid_t
		st_gid as gid_t
		st_rdev as dev_t
		dummy2 as whatever
		st_size as off_t
		st_blksize as uinteger 'blksize_t
		st_blocks as blkcnt_t
		st_atime as time_t
		st_atime_usec as time_t
		st_mtime as time_t
		st_mtime_usec as time_t
		st_ctime as time_t
		st_ctime_usec as time_t
	end type
	declare function stat (byval as zstring ptr, byval as _stat ptr) as long
	declare function lstat (byval as zstring ptr, byval as _stat ptr) as long
end extern

sub show_stats(pBuf as _stat ptr)
	print "st_dev     "; hex(pBuf->st_dev); " (hex)"
	print "st_ino     "; pBuf->st_ino
	print "st_mode    "; oct(pBuf->st_mode); " (oct)"
	print "st_nlink   "; pBuf->st_nlink
	print "st_uid     "; pBuf->st_uid
	print "st_gid     "; pBuf->st_gid
	print "st_rdev    "; pBuf->st_rdev
	print "st_size    "; pBuf->st_size
	print "st_blksize "; pBuf->st_blksize
	print "st_blocks  "; pBuf->st_blocks
	print "st_atime   "; pBuf->st_atime
	print "st_mtime   "; pBuf->st_mtime
	print "st_ctime   "; pBuf->st_ctime
	if (pBuf->st_mode and cint("&0770000")) = cint("&0120000") then print "Symbolic link"
	if (pBuf->st_mode and cint("&0770000")) = cint("&0100000") then print "Regular file"
end sub

dim buf as _stat
dim filename as string

print
filename = "test.bin"
print "file:"; filename
if lstat(filename, @buf) = 0 then
	show_stats(@buf)
else
	print "error"
endif

print
filename = "link.bin"
print "file:"; filename
if lstat(filename, @buf) = 0 then
	show_stats(@buf)
else
	print "error"
endif

end
Output:

Code: Select all

file:test.bin
st_dev     807 (hex)
st_ino     1573163
st_mode    100664 (oct)
st_nlink   1
st_uid     1000
st_gid     1000
st_rdev    0
st_size     11
st_blksize 4096
st_blocks   8
st_atime    1518727730
st_mtime    1518726505
st_ctime    1518726514
Regular file

file:link.bin
st_dev     807 (hex)
st_ino     1573158
st_mode    120777 (oct)
st_nlink   1
st_uid     1000
st_gid     1000
st_rdev    0
st_size     30
st_blksize 4096
st_blocks   0
st_atime    1518727556
st_mtime    1518727550
st_ctime    1518727556
Symbolic link
Terminal:

Code: Select all

badidea@xxx:~/Desktop$ stat test.bin 
  File: 'test.bin'
  Size: 11        	Blocks: 8          IO Block: 4096   regular file
Device: 807h/2055d	Inode: 1573163     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/ badidea)   Gid: ( 1000/ badidea)
Access: 2018-02-15 21:48:50.977077840 +0100
Modify: 2018-02-15 21:28:25.213432847 +0100
Change: 2018-02-15 21:28:34.565542171 +0100
 Birth: -
badidea@xxx:~/Desktop$ stat link.bin 
  File: 'link.bin' -> '/home/badidea/Desktop/test.bin'
  Size: 30        	Blocks: 0          IO Block: 4096   symbolic link
Device: 807h/2055d	Inode: 1573158     Links: 1
Access: (0777/lrwxrwxrwx)  Uid: ( 1000/ badidea)   Gid: ( 1000/ badidea)
Access: 2018-02-15 21:45:56.884179837 +0100
Modify: 2018-02-15 21:45:50.436316407 +0100
Change: 2018-02-15 21:45:56.860180345 +0100
 Birth: -
ls -l *.bin:

Code: Select all

lrwxrwxrwx 1 badidea badidea 30 Feb 15 21:45 link.bin -> /home/badidea/Desktop/test.bin
-rw-rw-r-- 1 badidea badidea 11 Feb 15 21:28 test.bin
Last edited by badidea on Feb 15, 2018 23:25, edited 1 time in total.
badidea
Posts: 2586
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: How do I detect if a file is symbolic link?

Post by badidea »

crt/sys/stat.bi does work for linux

edit: does not work, i meant

Does anyone understand why the 2 dummy variables are needed in the code above?
Last edited by badidea on Mar 27, 2018 22:58, edited 1 time in total.
edwin
Posts: 2
Joined: Mar 23, 2018 2:07

Re: How do I detect if a file is symbolic link?

Post by edwin »

I have problems to use the stat/lstat in sub.

Code: Select all

dim buf as _stat
dim filename as string
filename = "/bin/bash"
print "file:"; filename
print lstat(filename, @buf) 
print "all lines are ok"
end
These are ok. But the program crashed, when using the stat/lstat in sub.

Code: Select all

sub test_stat(filename as string)
	dim buf as _stat
	print "file:"; filename
	print lstat(filename, @buf) 
	print "end test_stat"
end sub
test_stat("/bin/bash")
print "can you see this line?"
end
Is it my system's problem?
edwin
Posts: 2
Joined: Mar 23, 2018 2:07

Re: How do I detect if a file is symbolic link?

Post by edwin »

Change the type _stat to the following, and put stat.bi in "crt/linux/stat.bi"

Code: Select all

#Include "crt.bi"
#include "datetime.bi"

'please update the type _stat from /usr/include/bits/stat.h, if it can not work well.
#ifdef __FB_64BIT__
# define __syscall_slong_t longint
#endif
type _stat
	st_dev as dev_t
	#ifndef __FB_64BIT__
	    __pad1 as UShort
	#endif
	st_ino as ino_t
	#ifndef __FB_64BIT__
		st_mode as mode_t
		st_nlink as nlink_t
	#else
		st_nlink as nlink_t
		st_mode as mode_t
	#endif
	
	st_uid as uid_t
	st_gid as gid_t
	
	#ifdef __FB_64BIT__
		__pad0 as long
	#endif
	st_rdev as dev_t
	#ifndef __FB_64BIT__
		__pad2 as UShort
	#endif
	
	st_size as off_t
	st_blksize as uinteger
	st_blocks as blkcnt_t
	
	st_atime as time_t
	st_atime_usec as time_t
	st_mtime as time_t
	st_mtime_usec as time_t
	st_ctime as time_t
	st_ctime_usec as time_t
	#ifdef __FB_64BIT__
		__glibc_reserved(3) as __syscall_slong_t
	#else
		__st_ino as __ino64_t
	#endif
end type

extern "C"
   declare function stat (byval as zstring ptr, byval as _stat ptr) as long
   declare function lstat (byval as zstring ptr, byval as _stat ptr) as long
   'declare function localtime (byval as time_t ptr) as tm ptr
end extern
Then all lines are ok now.

Code: Select all

#include "crt/linux/stat.bi"
sub test_stat(filename as string)
   dim buf as _stat
   print "file:"; filename
   print lstat(filename, @buf)
   print "end test_stat"
end sub
test_stat("/bin/bash")
print "yes, you can see this line now."
end
Post Reply