ich wollte mich heute mal ein bisschen mit dem Übersetzen von C-Header-Dateien auseinander setzen. Und dabei ist folgender Quellcode heraus gekommen. Wenn ich alles richtig gemacht habe, sollte er problemlos auf jedem 64-Bit-Linux laufen. Bei 32-Bit bin ich mir sehr unsicher, könnte aber trotzdem klappen.
Für das bessere Verständnis habe ich bei allen Imports, Strukturen, Konstanten und Macros, die ich brauche, genau gekennzeichnet aus welcher Include diese kommen, damit man das nachvollziehen kann. Eigentlich war das alles auch um mal ein bisschen einen Überblick darüber zu bekommen, was man so alles anstellen muss um ordentlich mit externen Bibliotheken unter Linux zu kommunizieren. Vielleicht wird daraus auch noch ein Video. Aber ich habe dennoch jetzt fast 4 Stunden dran gesessen.
Viel Spaß!
Code: Alles auswählen
EnableExplicit
;{ from /usr/include/x86_64-linux-gnu/bits/types.h and /usr/include/x86_64-linux-gnu/bits/typesizes.h
Macro dev_t : q : EndMacro
Macro ino_t : i : EndMacro
Macro mode_t : l : EndMacro
Macro nlink_t : q : EndMacro
Macro uid_t : l : EndMacro
Macro gid_t : l : EndMacro
Macro off_t : i : EndMacro
Macro blksize_t : i : EndMacro
Macro blkcnt_t : i : EndMacro
Macro time_t : i : EndMacro
Macro size_t : i : EndMacro
;}
;{ from /usr/include/x86_64-linux-gnu/bits/confname.h
#_SC_GETPW_R_SIZE_MAX = 70
;}
;{ from /usr/include/unistd.h
ImportC ""
; /* Get the value of the system variable NAME. */
; extern long int sysconf (int __name) __THROW;
sysconf.i(__name.l)
EndImport
;}
;{ from /usr/include/x86_64-linux-gnu/sys/sysmacros.h
; __NTH (gnu_dev_major (unsigned long long int __dev))
; {
; Return ((__dev >> 8) & 0xfff) | ((unsigned int) (__dev >> 32) & ~0xfff);
; }
;
; __extension__ __extern_inline __attribute_const__ unsigned int
; __NTH (gnu_dev_minor (unsigned long long int __dev))
; {
; Return (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff);
; }
; /* Access the functions With their traditional names. */
; # Define major(dev) gnu_dev_major (dev)
; # Define minor(dev) gnu_dev_minor (dev)
Macro major(dev)
(((dev >> 8) & $fff) | ((dev >> 32) & ~$fff))
EndMacro
Macro minor(dev)
((dev & $ff) | ((dev >> 12) & ~$ff))
EndMacro
;}
;{ from /usr/include/stat.h
Structure stat64
st_dev.dev_t ; ID of device containing file
st_ino.ino_t ; inode number
st_nlink.nlink_t ; number of hard links
st_mode.mode_t ; protection
st_uid.uid_t ; user ID of owner
st_gid.gid_t ; group ID of owner
pad0.l
st_rdev.dev_t ; device ID (if special file)
st_size.off_t ; total size, in bytes
st_blksize.blksize_t ; blocksize for file system I/O
st_blocks.blkcnt_t ; number of 512B blocks allocated
st_atime.time_t ; time of last access
st_atimensec.i
st_mtime.time_t ; time of last modification
st_mtimensec.i
st_ctime.time_t ; time of last status change
st_ctimensec.i
__unused.i[3]
EndStructure
; Encoding of the file mode.
#__S_IFMT = $F000 ; These bits determine file type.
; File types.
#__S_IFDIR = $4000 ; Directory. (d)
#__S_IFCHR = $2000 ; Character device. (c)
#__S_IFBLK = $6000 ; Block device. (b)
#__S_IFREG = $8000 ; Regular file. (-)
#__S_IFIFO = $1000 ; FIFO. (p)
#__S_IFLNK = $A000 ; Symbolic link. (l)
#__S_IFSOCK = $C000 ; Socket. (s)
; Protection bits.
#__S_ISUID = $800 ; Set user ID on execution.
#__S_ISGID = $400 ; Set group ID on execution.
#__S_ISVTX = $200 ; Save swapped text after use (sticky).
#__S_IREAD = $100 ; Read by owner. (r)
#__S_IWRITE = $80 ; Write by owner. (w)
#__S_IEXEC = $40 ; Execute by owner. (x)
ImportC ""
link.l(oldname.p-utf8, newname.p-utf8)
; extern int lstat64 (const char *__restrict __file,
; struct stat64 *__restrict __buf)
; __THROW __nonnull ((1, 2));
lstat64.l(__file.p-utf8, *__buf.stat64)
EndImport
;}
;{ from /usr/include/asm-generic/errno-base.h
#ENOENT = 2 ; No such file Or directory
#ESRCH = 3 ; No such process
#EBADF = 9 ; Bad file number
#EPERM = 1 ; Operation Not permitted
#EINTR = 4 ; Interrupted system call
#EIO = 5 ; I/O error
#EMFILE = 24 ; Too many open files
#ENFILE = 23 ; File table overflow
#ENOMEM = 12 ; Out of memory
#ERANGE = 34 ; Math result Not representable
;}
;{ from /usr/include/pwd.h
Structure passwd
*pw_name ; Username.
*pw_passwd ; Password.
pw_uid.uid_t ; User ID.
pw_gid.gid_t ; Group ID.
*pw_gecos ; Real name.
*pw_dir ; Home directory.
*pw_shell ; Shell program.
EndStructure
ImportC ""
; /* Search For an entry With a matching user ID.
;
; This function is a possible cancellation point And therefore Not
; marked With __THROW. */
; extern struct passwd *getpwuid (__uid_t __uid);
getpwuid.i(__uid.uid_t)
; extern int getpwuid_r (__uid_t __uid,
; struct passwd *__restrict __resultbuf,
; char *__restrict __buffer, size_t __buflen,
; struct passwd **__restrict __result);
getpwuid_r.l(__uid.uid_t, *__resultbuf.passwd, *__buffer, __buflen.size_t, *p__result)
EndImport
;}
;{ from /usr/include/grp.h
Structure group
*gr_name ; Group name.
*gr_passwd ; Password.
gr_gid.gid_t ; Group ID.
*p_gr_mem ; Member list.
EndStructure
ImportC ""
; /* Search For an entry With a matching group ID.
;
; This function is a possible cancellation point And therefore Not
; marked With __THROW. */
; extern struct group *getgrgid (__gid_t __gid);
getgrgid.i(__gid.gid_t)
EndImport
;}
;{ Helper functions
Procedure.s Oct(number.i)
Protected oct.s = ""
If (number = 0)
ProcedureReturn "0"
EndIf
While number
oct = Str(number % 8) + oct
number / 8
Wend
ProcedureReturn oct
EndProcedure
Procedure.s getModeString(mode.mode_t)
Protected perm.s, prot.i, t.s, o.i = mode
prot = #__S_ISVTX
Repeat
If (o & 4) : t = "r" : Else : t = "-" : EndIf
If (o & 2) : t + "w" : Else : t + "-" : EndIf
If (mode & prot)
If (prot = #__S_ISVTX)
If (o & 1) : t + "t" : Else : t + "T" : EndIf
Else
If (o & 1) : t + "s" : Else : t + "S" : EndIf
EndIf
Else
If (o & 1) : t + "x" : Else : t + "-" : EndIf
EndIf
o / 8
perm = t + perm
prot * 2
Until prot > #__S_ISUID
Select mode & #__S_IFMT
Case #__S_IFDIR: t = "d"
Case #__S_IFCHR: t = "c"
Case #__S_IFBLK: t = "b"
Case #__S_IFREG: t = "-"
Case #__S_IFIFO: t = "p"
Case #__S_IFLNK: t = "l"
Case #__S_IFSOCK: t = "s"
EndSelect
ProcedureReturn t + perm
EndProcedure
Procedure.s getUserName(userId.i)
Protected buflen.size_t = sysconf(#_SC_GETPW_R_SIZE_MAX)
If (buflen = -1)
buflen = 256
EndIf
Protected pwd.passwd
Protected *buffer = AllocateMemory(buflen)
Protected *presult
If (Not *buffer)
ProcedureReturn "[ENOMEM]"
EndIf
Protected errno.i, result.s
Repeat
errno = getpwuid_r(userId, @pwd, *buffer, buflen, @*presult)
If (errno = 0)
If (*presult = 0)
result = "[NOTFOUND]"
Else
result = PeekS(pwd\pw_name, -1, #PB_UTF8)
EndIf
Break
ElseIf (errno = #ERANGE)
buflen * 2
Protected *t
*t = ReAllocateMemory(*buffer, buflen)
If (Not *t)
result = "[ENOMEM]"
Break
EndIf
*buffer = *t
Else
result = "[ERR:" + errno + "]"
Break
EndIf
ForEver
FreeMemory(*buffer)
ProcedureReturn result
EndProcedure
Procedure.s getGroupName(groupId.i)
Protected *grp.group = getgrgid(groupId)
If (Not *grp)
ProcedureReturn ""
EndIf
ProcedureReturn PeekS(*grp\gr_name, -1, #PB_Ascii)
EndProcedure
Procedure.s getFileType(mode.mode_t)
Select mode & #__S_IFMT
Case #__S_IFDIR: ProcedureReturn "Verzeichnis"
Case #__S_IFCHR: ProcedureReturn "Zeichenorientierte Spezialdatei"
Case #__S_IFBLK: ProcedureReturn "Blockorientierte Spezialdatei"
Case #__S_IFREG: ProcedureReturn "Normale Datei"
Case #__S_IFIFO: ProcedureReturn "FIFO"
Case #__S_IFLNK: ProcedureReturn "symbolische Verknüpfung"
Case #__S_IFSOCK: ProcedureReturn "Socket"
EndSelect
EndProcedure
Procedure.i isSpecialFile(mode.mode_t)
ProcedureReturn Bool(mode & #__S_IFMT & (~#__S_IFREG & ~#__S_IFLNK & ~#__S_IFDIR))
EndProcedure
;}
Define s.stat64, file.s = "/dev/sda"
lstat64(file, @s)
OpenConsole()
PrintN(" Datei: '" + file + "'")
PrintN(" Größe: " + s\st_size + Chr(9) + "Blöcke: " + s\st_blocks + Chr(9) + "EA Block: " + s\st_blksize + " " + getFileType(s\st_mode))
Print("Gerät: " + Hex(s\st_dev) + "h/" + s\st_dev + "d" + Chr(9) + "Inode: " + s\st_ino + Chr(9) + "Verknüpfungen: " + s\st_nlink)
If (isSpecialFile(s\st_mode))
PrintN(Chr(9) + "Gerätetyp: " + Str(major(s\st_rdev)) + "," + Str(minor(s\st_rdev)))
Else
PrintN("")
EndIf
PrintN("Zugriff: (" + RSet(Oct(s\st_mode & $fff), 4, "0") + "/" + getModeString(s\st_mode) + ")" +
" Uid: (" + RSet(Str(s\st_uid), 5) + "/" + RSet(getUserName(s\st_uid), 8) + ")" +
" Gid: (" + RSet(Str(s\st_gid), 5) + "/" + RSet(getGroupName(s\st_gid), 8) + ")")
PrintN("Zugriff : " + FormatDate("%yyyy-%mm-%dd %hh:%ii:%ss", s\st_atime) + "." + StrU(s\st_atimensec, #PB_Long))
PrintN("Modifiziert: " + FormatDate("%yyyy-%mm-%dd %hh:%ii:%ss", s\st_mtime) + "." + StrU(s\st_mtimensec, #PB_Long))
PrintN("Geändert : " + FormatDate("%yyyy-%mm-%dd %hh:%ii:%ss", s\st_ctime) + "." + StrU(s\st_ctimensec, #PB_Long))
Input()
CloseConsole()