QFileDialog doesn’t list tty* files in /dev/ on Linux - linux

I’m working on a Linux desktop application that needs to open a USB serial port, typically /dev/ttyUSB0 or /dev/ttyUSB1. I’m using QFileDialog to let the user select the file:
QFileDialog dialog(this);
dialog.setFileMode(QFileDialog::AnyFile);
dialog.setFilter(QDir::System | QDir::AllEntries | QDir::Hidden);
dialog.setViewMode(QFileDialog::Detail);
QStringList fileNames;
if (dialog.exec())
fileNames = dialog.selectedFiles();
When I direct the FileDialog to /dev, none of the files that I can see by typing “ls /dev -al” are there. The directories show up, but for example, this file doesn’t:
$ ls -al /dev/ttyS0
crw-rw---- 1 root dialout 4, 64 2011-10-09 10:47 /dev/ttyS0
My user is a member of the dialout group:
$ groups
luke adm dialout cdrom audio video plugdev users fuse netdev bluetooth lpadmin admin sambashare
I’ve tried adding QDir::Readable and QDir::Writable and the above file still doesn’t show up. What am I doing wrong?

It amazes me how often people don't answer the question that was originally asked. I'll try not to do that here, if I can. I've done some homework on this problem since I'm having exactly the same issue. The short answer is that you can't use QFileDialog to reliably list and select nodes in "/dev". When you set the "QDIR::System" bit in the QFileDialog Filter using QFileDialog::setFilter(QDIR::System), you would expect that all the files in /dev would show up, but they do not. Admittedly, there are more entries than when it is not set, but most of the device nodes are still not displayed. It is clear that QFileDialog is doing some additional filtering behind the scenes, and that this filtering cannot be turned off in any obvious way.
On the other hand, if you use the QDir class with the QDir::System filter bit set, then in fact all of the /dev entries do appear in the entryList. For example, assuming that you already have a QComboBox named TTYDevices in your user interface, try something like this:
DevDir=new QDir("/dev","tty*",QDir::Name,QDir::System);
ui->TTyDevices->addItems(DevDir->entryList());
Then use the standard signals from QComboBox to detect and act on selection of the desired device node. By the way, ui is the standard Qt pointer to the instance of your parent window class and should be set up in the Window's constructor. Just make sure that you don't reference it before the constructor calls ui->setupUi(this). If you do, the program will crash.
This trick provides identical functionality to QFileDialog, with the additional features provided by accessing the QDir object directly. It does mean that you cannot easily have the same familiar, uniform interface provided QFileDialog, but it works and is remarkably easy to code.

Related

Open file by inode

Is it possible to open a file knowing its inode?
ls -i /tmp/test/test.txt
529965 /tmp/test/test.txt
I can provide path, inode (above 529965) and I am looking to get in return a file descriptor.
This is not possible because it would open a loophole in the access control rules. Whether you can open a file depends not only on its own access permission bits, but on the permission bits of every containing directory. (For instance, in your example, if test.txt were mode 644 but the containing directory test were mode 700, then only root and the owner of test could open test.txt.) Inode numbers only identify the file, not the containing directories (it's possible for a file to be in more than one directory; read up on "hard links") so the kernel cannot perform a complete set of access control checks with only an inode number.
(Some Unix implementations have offered nonstandard root-only APIs to open a file by inode number, bypassing some of the access-control rules, but if current Linux has such an API, I don't know about it.)
Not exactly what you are asking, but (as hinted by zwol) both Linux and NetBSD/FreeBSD provide the ability to open files using previously created “handles”: These are inode-like persistent names that identify a file on a file system.
On *BSD (getfh and fhopen) using this is as simple as:
#include <sys/param.h>
#include <sys/mount.h>
fhandle_t file_handle;
getfh("<file_path>", &file_handle); // Or `getfhat` for the *at-style API
// … possibly save handle as bytes somewhere and recreate it some time later …
int fd = fhopen(&file_handle, O_RDWR);
The last call requiring the caller to be root however.
The Linux name_to_handle_at and open_by_handle_at system calls are similar, but a lot more explicit and require the caller to keep track of the relevant file system mount IDs/UUIDs themselves, so I'll humbly link to the detailed example in the manpage instead. Beware, that the example is not complete if you are looking to persist the handles across reboots; one has to convert the received mount ID to a persistent filesystem identifier, such as a filesystem UUID, and convert that back to a mount ID later on. In essence they do the same however. And just like on *BSD using the later system call requires elevated privileges (CAP_DAC_READ_SEARCH to be exact).

Linux: device appears in /dev but cannot be accessed

I have created a Linux device driver and can add it to the system (insmod, mknod). When I look in /dev I see it listed as camerax:
ls -l /dev/camerax
crw-r--r-- 1 root root 245, 0 Jun 27 17:19
Even so, I cannot access it. Whatever I do, I get an error.
For example:
int fd = open("/dev/camerax", O_RDONLY);
printf("%d [%s]\n", fd, strerror(errno));
Generates:
-1 [No such device or address]
I'm running as a super user. Any suggestions?
Your Module is not linked to the special file which you have mentioned so it is giving error.
If your module is successfully inserted verify in /proc/devices using cat command
cat /proc/devices.
file created using mknod in the path /dev/____ is just a refrence to your driver
The major and minor number should match with your inserted device.
I have solved the problem.
Instead of creating the major device number dynamically, as described in the documentation, I now set it explicitly to 61. Everything now works.
The only difference I can see between the working and non-working versions is the major number (and yes, I change anything that uses the device number so I am always using the appropriate one).
This adds one more bizarre feature of the system to my growing list.

Weird URI string displayed on mounting iPod

I have written a small program to detect whenever a device is mounted on a desktop running Linux. I have used GIO for this. I am extracting the URI of the mounted resource and displaying it to the user. When I put in a CD I get a URI string which looks like file:///media/cdrom0/ which I can understand. But when I mount an iPod the URI I see is something like gphoto2://[usb:002,028]. What does this mean? I have observed that the second number (028) keeps increasing every time I take the device out and plug it back in. Can some one interpret this URI for me?
Update: As shodanex answered, the two numbers are the bus number and device number respectively. gphoto2:// indicates the protocol (PTP/MTP).
gphoto2://[usb:002,028]
I guess 002 is the bus number, and 28 is the adress of the device on that bus.
It maps to the second and fourth field of the lsusb util output. Here is an example
on my system :
Bus 001 Device 015: ID 05e3:0715 Genesys Logic, Inc. USB 2.0 microSD Reader
I guess it would translate to :
usb:001,015
I have these kinds of URL's in Nautilus too, but the other response doesn't explain how that relates to a mount location on disk. I can navigate through the files on an SD card via the Nautilus file browser, but I don't see any of these files in /mnt/ or /media/ or anywhere else I would typically look for automatically mounted file systems.
Eventually I tried right-clicking the folder, selecting "Open with other application," choosing a text editor, and then I could see that the folder was actually mounted at:
'~/.gvfs/gphoto2 mount on usb%3A001,010'
I wish Nautilus and other tools in ubuntu would provide some more obvious way to find these files... this seems pretty un-intuitive.

Version Control soft that will keep ALL files and their metadata from POSIX FS (ext3/ext4)

THE SCENARIO
I'm developing a Root FS for some embedded Linux device. It is sitting on the host, exported via NFS and my development board mounts is under "/".
The workflows that I need are:
- to share my FS to other developers(they have with their own dev. boards)
- to backup my Root FS onto some "server"
- to deploy my Root FS onto flash-disks or other media
- track changes in specific files in my Root FS, branching&merging,roll back etc.
Guys, this seems to me as a Version Control scenario, and I even use git.
THE PROBLEM
As you know Git(and svn/mercurial/bazaar too !) 1) does not store special files (device files under /dev etc.) 2) does not store file owners and permissions.
I want to store everything and AS IS.
THE QUESTION:
Do you know some VCS that will do the job ?
Or may be you know about another (but simple) solution for doing my scenarios ?
IS IT A COMMON PROBLEM...
I believe that it is, because till now I've heard about scripts/hooks/custom soft that everybody(!) works out for his purposes. All I need is an all-eating-VSS
Thank you !!
Having done something similar (developing firmware for an embedded Linux OS), I've found that it's better to put device file creation into a script called by your build system, rather than to store device files directly on the development machine. Then the script that creates the files goes into version control, instead of the files themselves, and (BONUS) you don't need to be root to modify them. Run the build through fakeroot instead.
I suppose this doesn't directly answer your question, but it may be worth thinking about revising your development model. It's NEVER a good idea to run your build as root, because what happens if you accidentally have a "/" in front of a common path? You may inadvertently replace /bin with a whole bunch of links to busybox built for a different architecture.
This is the tool for you:
http://fsvs.tigris.org/
it has svn backend.
I know this seems a little obvious, but as you haven't mentioned it: Have you considered mechanisms to put all your special files into a regular file, like, for example, into a tar archive? You could store that just fine with any version control system, and as filesystems have lots of binary data anyway diffs between two revisions of a full root filesystem aren't that useful anyway, so you might even not lose too many of the features your version control system provides.
initramfs is a good answer to the userid groupid, permissioon problem. In your kernel source directory, there is scripts/gen_initramfs_list.sh.
This script allows you to build an initramfs archive from several sources. You can for example, specify :
a directory : The files and directory found in this base directory will be at the root of your file system.
a file liste : it is a text file, very useful to create directory, files and special device files. See example below
If you develop as non root, and your rootfs is in rootfsdir, then probably the file in rootfsdir are owned by you. gen_initramfs_list can translate your uid, gid into 0, 0. Here is an exemple command line :
gen_initramfs_list -u $MYUID -o initramfs.gz rootfsdir/ device.txt
Where device.txt contains :
# This is a very simple, default initramfs
dir /dev 0755 0 0
nod /dev/console 0600 0 0 c 5 1
dir /root 0700 0 0
# file /kinit usr/kinit/kinit 0755 0 0
# slink /init kinit 0755 0 0
Then you can use standard version control for your rootfsdir content, and add the device.txt file under version control, and here you are : content and file attribute are versionned :).
I don't know if you can change the permission and uid/gid of a file in a directory source via a filelist source, but this would be a logical feature.
Of course you can start with minimal root fs, from which you mount your existing nfs_export.
It is a common problem, and gen_initramfs_list is the tool to solve it.
Why not just use rsync? Something like rsnapshot (http://www.rsnapshot.org) will do what you want. Alternatively Unison (http://www.cis.upenn.edu/~bcpierce/unison/) is explicitly designed for this - it describes itself as a cross-platform file synchronisation technology with version control, and might be what you need.

Problem with chardev.c example from The Linux Kernel Module Programmers Guide

I compiled and ran the chardev.c example from the lkmpg and when writing to the device received an unexpected error:
anon#anon:~/lkmpg$ sudo echo "hi" > /dev/chardev
bash: /dev/chardev: Permission denied
The module write function looks like this:
/*
* Called when a process writes to dev file: echo "hi" > /dev/chardev
*/
static ssize_t
device_write(struct file *filp, const char *buff, size_t len, loff_t * off)
{
printk(KERN_ALERT "Sorry, this operation isn't supported.\n");
return -EINVAL;
}
I'm not getting the expected error of invalid operation and the error printed to /var/log/messages.
I can read from the device with no problem, receiving the expected results:
anon#anon:~/lkmpg$ cat /dev/chardev
I already told you 6 times Hello world!
The device /dev/chardev is created manually using:
sudo mknod /dev/chardev c 252 0
What's the deal?
--Edit--
Apparently when I mknod to create the device it ends up with the following permissions:
crw-r--r-- 1 root root 252, 0 2009-10-30 09:27 /dev/chardev.
Once I did sudo chmod a+w /dev/chardev the driver worked as expected.
However, people have said it is not correct to do this.
What is the correct course of action and why?
A really, really, really straight forward and simple example of how to implement character drivers can be found in drivers/watchdog/softdog.c
You can compare your code to this example, which shows you how to do the following:
Read from the device
Write to the device
Present an ioctl interface via the device
While softdog is a very useful tool, its as much a tutorial as anything else. Alan Cox threw it together, so its a good example of more 'proper' implementation.
If you can post the whole source to your module, we can help you find out why your function is not being entered as expected.
Update:
It is perfectly acceptable to allow under privileged users to write to character devices! I repeat, it is perfectly acceptable to allow under privileged users to write to character devices! If this was not the case, stuff like FUSE, Modems, USB Gadgets, CD ROMS and other things would require root access to use.
What you can do is take advantage of group memberships. I.e., on Ubuntu, users permitted to use FUSE (file system in user space) should belong to the 'fuse' group, which permits granular access on who can and can not use that feature. Similarly, on some of my systems, a QRNG (quantum random number generator) is in use .. and is (you guessed it) a character device. I need to allow PHP to access that device , so I:
Create a QRNG group
Make sure PHP runs as the user (not anonymous system users)
Add users owning apps that need access to the device to the QRNG group
I hope that clears it up :)
I think, actual problem is the command which you issued to write is incorrect. Try
#sudo sh -c "echo "hi" > /dev/chardev"
If you want to run multiple commands with sudo then you should use command as shown above. With this, you dont need to do chmod and change its permissions as well. Hope this helps.

Resources