List of serial ports - c

I am writing small C project to list available serial ports (actually on Linux). It should list usable ttyS, ttyUSB, pty and so on.
My problem is that I have no idea what is the proper way to do it. For example in my /dev directory I have devices from ttyS0 to ttyS31 but in fact no one is usable. I tried looking for drivers in /sys/class/tty/ttyS* but all devices seems to be real.
Actually I can only list pty's opened by 'socat pty pty', but in my opinion it's hack, because I just wrapped the command 'lsof -w -c socat | grep -o '/dev/pts/[0-9]*' | uniq -u' and I am looking for a better way.
My project: https://github.com/mdrost/serialportlist
I will be grateful for possible technical help and comments about functionality.

Related

How can I identify the protocol used in hard disk?

I have an application which needs to read information from a hard disk, stuff like serial model etc.
Now of course it matters if the drive is a SAS, SATA or FC drive.
Is there a reliable way that I can identify which protocol a connected drive uses? Either via an OS command or checking some logs or inquiring the device?
I don't want to use sysfs structure. I want to know how the OS know if it's an ATA, SCSI or whatever type of disk.
As you have mentioned in comments to user3588161's answer, you are having SATA and SAS disk attached to the same SAS controller, so I'd suggest to use the smartctl command!
The smartctl command act as a control and monitor Utility for SMART disks under Linux and Unix like operating systems. Type the following command to get information about /dev/sda (SATA disk):
# smartctl -d ata -a -i /dev/sda
For SAS disk use one of the following syntax:
# smartctl -d scsi --all /dev/sgX
# smartctl -d scsi --all /dev/sg1
# smartctl -d scsi --all /dev/sg1 -H
I guess all of the information is somehow related to this location :-
/sys/class/scsi_device/?:?:?:?/device/model
I suggest you try doing this too to check what output does it render.
cat /sys/class/scsi_device/0\:0\:0\:0/device/{model,vendor}
(The backslashes next to zeros are for escaping special char :.)
Also, I'd like to suggest you to visit these two links in order for more information or detail like sample output,etc :-
Find Out Hard Disk Specs
To Check Disk behind Adaptec RAID Controllers
Checking boot information, it seems the disk type is set in kernel ahci calls. You can check (as root) with dmesg | grep ahci (on sysvinit systems) or with journalctl -k -b -0 -l --no-pager | grep ahci (with systemd). The relevant query/setting looks to be:
kernel: ahci 0000:00:12.0: version 3.0
kernel: ahci 0000:00:12.0: controller can't do 64bit DMA, forcing 32bit
kernel: ahci 0000:00:12.0: AHCI 0001.0100 32 slots 4 ports 3 Gbps 0xf impl SATA mode
kernel: ahci 0000:00:12.0: flags: ncq sntf ilck pm led clo pmp pio slum part ccc
The third line holds the controller/type information you are looking for. This seems to be where the information comes from, but from your questions standpoint, it isn't a viable solution.
The question becomes where does this information get recorded or stored within /dev /proc or /sys. I have looked and cannot find a one-to-one correlation between this initial determination of disk type on boot and any flag stored. This information may well be part of the coded data, for example, /sys/class/scsi_disk/0:0:0:0/device or similar location. Hopefully this information may allow you or others to help pinpoint if, and if so, where this information is captured and available on a running system.
Answer rewritten in view of clarification: libATA is what you want. It's what hdparm calls and it reports the transport too. It's hard to find up to date docs on it though. See http://docs.huihoo.com/linux/kernel/2.6.26/libata/index.html for example.
I have not used libATA (directly) myself, so I can't be more specific as to the API calls needed. Since not many people need to write something like hdparm themselves, your best bet is to consult its sources to see what exactly it calls.
hdparm can report stuff like:
[root#alarmpi ~]# hdparm -I /dev/sdb
/dev/sdb:
ATA device, with non-removable media
Model Number: TOSHIBA DT01ACA200
Serial Number: Z36GKMKGS
Firmware Revision: MX4OABB0
Transport: Serial, ATA8-AST, SATA 1.0a, SATA II Extensions, SATA Rev 2.5, SATA Rev 2.6, SATA Rev 3.0; Revision: ATA8-AST T13 Project D1697 Revision 0b
If your actual problem is that only sdparm works on your system for SCSI drives (can happen) then it seems the problem is reduced to figuring out which of hdparm or sdparm to call isn't it? You could use udevinfo for that. See https://chromium.googlesource.com/chromiumos/third_party/laptop-mode-tools/+/775acea9e819bdee90cca8d2363827c13967a14b/laptop-mode-tools_1.52/usr/share/laptop-mode-tools/modules/hdparm for example.

Performing the equivalent of chattr +i filename.txt from Linux application

Is there any interface in the Linux userspace API that will allow me to perform the action equivalent to
chattr +i myfile
chattr -i myfile
If possible I need to do this from within my application but I cannot find anything online that suggests how one would go about doing this from the Linux API. I would have thought there would be some kind of ioctl call available to do this but I simply cannot find any details about it.
have a look at:
http://www.danlj.org/lad/src/setflags.c.html
and if you do some strace on chattr, you could have found out that it calls stuff that looks like:
ioctl(fd, EXT2_IOC_SETFLAGS, flags)
(have a look at this thread)

What is the most general way to list all the kernel tasks in a linux system?

I am trying to figure out the best way to write a cross platform kernel code/shell script to list all the kernel task {(pid/tid , name)} in a linux dis. machine. it should be the most general possible. I tried to use ps -T but it is seems to be inaccurate and some platform don't support it in their busybox. Any suggestions?
If you want to distinguish user processes from kernel tasks, then this is a previous discussion on the subject: Identifying kernel threads
My answer to that question does not require any tools, it simply reads the contents of /proc//stat, so it should work on any distribution.
You could try
ps -e -o pgrp= -o pid= -o cmd= | sed -ne 's/^ *0 *// p'
although it assumes all kernel tasks belong to process group 0.

Get used ports and states

How can I get used ports and their states on Linux? Basically, everything that netstat can do, but in C?
Running strace on a run of netstat will show you the system calls it makes and their arguments.
$ strace netstat
...
open("/proc/net/tcp6", O_RDONLY) = 3
open("/proc/net/udp", O_RDONLY) = 3
...
This is often a good way to find out what a program is doing or the calls it makes and can sometimes be easier than looking at the source if all you need is to find out which call to look up on a man page.
Well, for “everything that netstat can do,” you could start with netstat itself. The source code is here:
http://net-tools.git.sourceforge.net/git/gitweb.cgi?p=net-tools/net-tools;a=blob;f=netstat.c;h=f046f09162689f258f8920c1c2af27e01cdc77f2;hb=HEAD
It should be noted that most of what netstat does, it obtains from the /proc filesystem; it looks like the *_do_one routines hold most of the "interesting" guts.

Linux programming: which device a file is in

I would like to know which entry under /dev a file is in. For example, if /dev/sdc1 is mounted under /media/disk, and I ask for /media/disk/foo.txt, I would like to get /dev/sdc as response.
Using stat system call on that file I will get its partition major and minor numbers (8 and 33, for sdc1). Now I need to get the "root" device (sdc) or its major/minor from that. Is there any syscall or library function I could use to link a partition to its main device? Or even better, to get that device directly from the file?
brw-rw---- 1 root floppy 8, 32 2011-04-01 20:00 /dev/sdc
brw-rw---- 1 root floppy 8, 33 2011-04-01 20:00 /dev/sdc1
Thanks in advance!
The quick and dirty version: df $file | awk 'NR == 2 {print $1}'.
Programmatically... well, there's a reason I started with the quick and dirty version. There's no portable way to programmatically get the list of mounted filesystems. (getmntent() gets fstab entries, which is not the same thing.) Moreover, you can't even parse the output of mount(8) reliably; on different Unixes, the mountpoint may be the first or the last item. The most portable way to do this ends up being... parsing df output (And even that is iffy, as you noticed with the partition number.). So you're right back to the quick and dirty shell solution anyway, unless you want to traverse /dev and look for block devices with matching major(st_rdev) (major() being from sys/types.h).
If you restrict this to Linux, you can use /proc/mounts to get the list of mounted filesystems. Other specific Unixes can similarly be optimized: for example, on OS X and I think FreeBSD, you can use sysctl() on the vfs tree to get mountpoints. At worst you can find and use the appropriate header file to decipher whatever the mount table file is (and yes, even that varies: on Solaris it's /etc/mnttab, on many other systems it's /etc/mtab, some systems put it in /var/run instead of /etc, and on many Linuxes it's either nonexistent or a symlink to /proc/mounts). And its format is different on pretty much every Unix-like OS.
The information you want exists in sysfs which exposes the linux device tree. This models the relationships between the devices on the system and since you are trying to determine a parent disk device from a partition, this is the place to look. I don't know if there are any hard and fast rules you can rely on to stop your code breaking with future versions of the kernel, but the kernel developers do try to maintain sysfs as a stable interface.
If you look at /sys/dev/block/<major>:<minor>, you'll see it is a symlink with the tail components being block/<disk-device-name>/<partition-device-name>. If you were to perform a readlink(2) system call on that, you could parse the link destination to get the disk device name. In shell (since it's easier to express this way, but doing it in C will be pretty easy):
$ echo $(basename $(dirname $(readlink /sys/dev/block/8:33)))
sdc
Alternatively, you could take advantage of the nesting of partition directories in the disk directories (again in shell, but from C, its an open(2), read(2), and close(2)):
$ cat /sys/dev/block/8:33/../dev
8:32
That assumes your starting major:minor is actually for a partition, not some other sort of non-nested device.
What you looking for is impossible - there is no 1:1 connection between a block device file and the partition it is describing.
Consider:
You can create multiple block device files with different names (but the same major and minor numbers) and they are indistinguishable (N:1)
You can use a block device file as an argument to mount to mount a partition and then delete the block device file leaving the partition mounted. (0:1)
So there is no way to do what you want except in a few specific and narrow cases.
Major number will tell you which device it is: 3 - IDE on 1st controller, 22 - IDE on 2nd controller and 8 for SCSI.
Minor number will tell you partition number and - for IDE devices - if it's primary or secondary drive. This calculation is different for IDE and SCSI.
For IDE it is: x*64 + p, x is drive number on the controller (0 or 1) and p is partition
For SCSI it is: y*16 + p, where y is drive number and p is partition
Not a syscall, but:
df -h /path/to/my/file
From https://unix.stackexchange.com/questions/128471/determine-what-device-a-directory-is-located-on
So you could look at df's source code and see what it does.
I realize this post is old, but this question was the 2nd result in my search and no one has mentioned df -h

Resources