Why is the difference between oldolduname and uname? - c

Why is the difference between oldolduname and uname?
I have been reading the man pages and I don't get the subtlety.

First of all, if you call uname from userspace, you do not need to care about the difference, and there should be no need to use olduname or oldolduname. From userspace, you use struct utsname and you call the uname() function.
From the man page:
Over time, increases in the size of the utsname structure have led to
three successive versions of uname(): sys_olduname() (slot
__NR_oldolduname), sys_uname() (slot __NR_olduname), and sys_newuname() (slot __NR_uname). The first one used length 9 for all
fields; the second used 65; the third also uses 65 but adds the
domainname field. The glibc uname() wrapper function hides these
details from applications, invoking the most recent version of the
system call provided by the kernel.
So, throughout history the sizes and content of struct utsname has changed slightly, and the kernel has kept 3 different versions around to keep compatibility with userspace, you can see the different versions that the kernel handles here: http://lxr.free-electrons.com/source/include/linux/utsname.h?v=2.6.38#L24 . However glibc, or any C library on linux hides all this from you.

uname is the function called by user code.
It calls one of the kernel functions sys_newuname, sys_uname, or sys_olduname, depending on the version of the Linux kernel. The difference between these is the lengths of the name fields (9 characters in sys_olduname, 65 characters in the other two), and sys_newuname adds an additional domainname field to the structure.

Related

Why do both fstat(2) and fstat(3) exist and which one should I use?

I was trying to read the man page for fstat, and I got fstat(2), fstat(3) and fstat(3P).
Having in the past used a system (2) command, I know the difference is that I have to write a prototype myself to announce the function (which is reflected in the fstat(2) man page).
But never have I seen that a function is both a C function (3) and a system function (2) at the same time. What would be the benefit of using one over the other? How would C even differentiate whether I am using (2) or (3).
Also, I understand that sys/stat.h is platform specific, so which of (2) and (3) would be safer to use for cross-platform? Since I don't see a prototype line in the Windows page example, I assume it is a (3)
Please explain this to be because I cannot wrap my head around why both would exist.
Web-based manpages are always a second-best option, since they can only show you a generic view of the interfaces. If you use the man command on your own system (at least for Unix-like systems), the result should reflect your actual installation, assuming you've correctly installed the documentation for your distribution.
Section 2 of the manual is intended for the description of system calls rather than standard library APIs. However, at least in the case of Linux documentation, section 2 is also used to describe the library wrappers around the system calls, which effectively documents the particular features implemented by the standard C library, normally glibc. In such cases, section 3P is used to document the to contain documentation extracted or adapted from the Posix standard. So if you want to write portable code, use only the features documented in section 3P. If you are happy to use all the extensions available to you on your system, use section 2.
man7.org and linux.die.net use different manpage repositories; on the latter, section 3P doesn't exist and the Posix programming manual is found in section 3. So https://www.man7.org/linux/man-pages/man3/fstat.3p.html and https://linux.die.net/man/3/fstat contain the same information. If you use a linux distribution, you'll probably find that man 3 fstat actually gives you the page from section 3p.
In any event, there is only one interface in the C library, which should conform to the Posix standard, but may extend it.

What is the purpose of libc_nonshared.a?

Why does libc_nonshared.a exist? What purpose does it serve? I haven't been able to find a good answer for its existence online.
As far as I can tell it provides certain symbols (stat, lstat, fstat, atexit, etc.). If someone uses one of these functions in their code, it will get linked into the final executable from this archive. These functions are part of the POSIX standard and are pretty common so I don't see why they wouldn't just be put in the shared or static libc.so.6 or libc.a, respectively.
It was a legacy mistake in glibc's implementing extensibility for the definition of struct stat before better mechanisms (symbol redirection or versioning) were thought of. The definitions of the stat-family functions in libc_nonshared.a cause the version of the structure to bind at link-time, and the definitions there call the __xstat-family functions in the real shared libc, which take an extra argument indicating the desired structure version. This implementation is non-conforming to the standard since each shared library ends up gettings its own copy of the stat-family functions with their own addresses, breaking the requirement that pointers to the same function evaluate equal.
Here's the problem. Long ago, members of the struct stat structure had different sizes than they had today. In particular:
uid_t was 2 bytes (though I think this one was fixed in the transition from libc5 to glibc)
gid_t was 2 bytes
off_t was 4 bytes
blkcnt_t was 4 bytes
time_t was 4 bytes
also, timespec wasn't used at all and there was no room for nanosecond precision.
So all of these had to change. The only real solution was to make different versions of the stat() system call and library function and you get the version you compiled against. That is, the .a file matches the header files. These things didn't all change at once, but I think we're done changing them now.
You can't really solve this by a macro because the structure name is the same as the function name; and inline wasn't mandated to exist in the beginning so glibc couldn't demand everybody use it.
I remember there used to be this thing O_LARGEFILE for saying you could handle files bigger than 4GB; otherwise things just wouldn't work. We also used to have to define things like _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE but it's all handled automatically now. Back in the day, if you weren't ready for large file support yet, you didn't define these and you didn't get the 64-bit version of the stat structure; and also worked on older kernel versions lacking the new system calls. I haven't checked; it's possible that 32-bit compilation still doesn't define these automatically, but 64-bit always does.
So you probably think; okay, fine, just don't franken-compile stuff? Just build everything that goes into the final executable with the same glibc version and largefile-choice. Ever use plugins such as browser plugins? Those are pretty much guaranteed to be compiled in different places with different compiler and glibc versions and options; and this didn't require you to upgrade your browser and replace all its plugins at the same time.

How to get x86 Linux kernel definitions

Let's say I want to find the real definition of O_APPEND, which is one of the flags for open() syscall. By real definition, I mean a number like 0x2.
I go to LXR and do a search:
Defined in 5 files:
arch/alpha/include/uapi/asm/fcntl.h, line 10 (as a macro)
arch/mips/include/uapi/asm/fcntl.h, line 13 (as a macro)
arch/parisc/include/uapi/asm/fcntl.h, line 4 (as a macro)
arch/sparc/include/uapi/asm/fcntl.h, line 4 (as a macro)
include/uapi/asm-generic/fcntl.h, line 35 (as a macro)
However, there's no x86 here. Why?
I faced the same problem when I needed to look up the numbers for syscalls and I ended up using a 3rd-party website that contains a generated table.
If I understood correctly, syscalls are somehow generated on-the-fly, so there's no possibility to look them up until the kernel is preprocessed for a specific architecture.
Is it the same story for all the defines for x86 and x86_64? How do I continue when I need something that is not already on the Internet generated by someone? I could've looked it up on my desktop in headers, but I use x86_64, not x86.
So, how do I find the exact numbers flags and modes are #defined to for x86 architechture?
In the case of the user space API (uapi), it will be defined in include/uapi/asm-generic/fcntl.h.
The generic part of the path means this is architecture independent code.

Writing my first systemcall(for learning kernel development) in freebsd

So I have just started customizing the FreeBSD kernel, but unfortunately the resources available for FreeBSD development are scarce .
Im writing a systemcall in which should read a file(optionally), read the blocks of physical memory according to input and write the results into another file(generally "filename.results")
my problems are:
Standard C libraries: it seems to be that they are unavailable for kernel module programming so how should I replace the functions such as write and read(and strlen and some others in string.h)?
Malloc function: it seems that it accepts 3 inputs instead of 1, and I have no idea how to fill the 2nd variable even after reading the man page(tried FOO but returns symlink error).
Also I was interested in any other topics u think they are useful for this routine.
In case of malloc, do "man 9 malloc". The "9" here means section describing kernel functions, userland malloc is described in section 3.
Well I've said that I got the answer.
So for future reads I'm just leaving it here.
MALLOC: you need to define your own memory description(or use an existing one) in order to be able to locate it, that's a POSIX standard and its for sanity check purposes.
as for the other things, for the fact that standard c libraries are not available in kernel mode, the kernel variant of them is likely available in libkern (open /sys/libkern), and they will be all available once you implement it(say uprintf, strlen and stuff), if its not there you have to call the relying module by implementing them in your header file(say for FILE interaction you need to include the I/O module located in /sys/(dir)) since you ARE in kernel mode it doesn't create a problem.(also note that those functions are well implemented so you wont likely face a kernel crash.)
As an obvious fact you have to copy the buffer from user memory to kernel memory in order to do modifications on it, and copy it back when you are done.
one last thing, in order to implement your systemcall via sysproto auto build you need to include it as well(and add your syscall to the list). and don't forget to include your file in the source file configuration file (located in /sys/(dir) again).

Find out MAC address on Linux&FreeBSD in C

I am trying to find out MAC address and I managed to create working solution using sysctl in Linux, problem is, that this solution is not working on FreeBSD version I am developing on. Is there any way I can find out mac address in C other than using sysctl?
Use the libpcap library. Its the most multi platform way you can find.
This library is used on network sniffers and intrusion detections, as well as dedicate measuring other network statistics. The nethogs utility to measure per process network usage, the iftop used to measure per machine/port bandwidth usage. Is very flexible in many roles.
Is written in C but there are some wrappers for other languages.
1: http://en.wikipedia.org/wiki/Pcap
[2]: http://www.tcpdump.org
[3]: http://sourceforge.net/projects/libpcap/
Edit:
here is a complete and exact and working example with the code and functions detailed:
http://coderrr.wordpress.com/2008/03/07/get-the-mac-address-of-a-local-ip/
There are plenty of tutorials and the source code is your best friend.
Edit 2: blaze pointed out getifaddrs(3) which seems to do the job, just a few caveats, its a non-posix function. Is a bsd function which glibc linux supports but do NOT documents. Is almost an undocumented featured :-)
All documentation are man pages and from the manual at kernel.org:
Not in POSIX.1-2001. This function first appeared in BSDi and is
present on
the BSD systems, but with slightly different semantics documented--returning
one entry per interface, not per address. This means ifa_addr and other
fields can actually be NULL if the interface has no address, and no link-level
address is returned if the interface has an IP address assigned. Also, the
way of choosing either ifa_broadaddr or ifa_dstaddr differs on various
systems.
and
The addresses returned on Linux will usually be the IPv4 and IPv6
addresses
assigned to the interface, but also one AF_PACKET address per interface
containing lower-level details about the interface and its physical layer. In
this case, the ifa_data field may contain a pointer to a struct
net_device_stats, defined in , which contains various
interface attributes and statistics.
So it may vary in behavior and you'll may have to #ifndef compile anyway.
The kernel.org man page at http://www.kernel.org/doc/man-pages/online/pages/man3/getifaddrs.3.html does provides example code in it, which may be helpful. My local linux man page is rather poor in comparison to the above linked.
I still think that libpcap is more portable if only because someone else had done all the portability work and all the extra features you gain by using it.
Hope this helps.
getifaddrs(3) returns IP addresses and MAC addresses on local interfaces. Portable between Linux and FreeBSD.

Resources