Reputation: 574
(sorry for bad English, I'm German)
I'm trying to write a program on linux that writes data on any inserted USB flash device that is inserted.
But this:
file = fopen("/run/media/abc/xyz/logFile.txt", "w");
will fail if the username is not abc, or the name of the device is not xyz or linux does not want my program to work.
I found a program that outputs this:
sysfs /sys
proc /proc
devtmpfs /dev
securityfs /sys/kernel/security
tmpfs /dev/shm
devpts /dev/pts
tmpfs /run
tmpfs /sys/fs/cgroup
cgroup /sys/fs/cgroup/systemd
pstore /sys/fs/pstore
cgroup /sys/fs/cgroup/freezer
cgroup /sys/fs/cgroup/cpu,cpuacct
cgroup /sys/fs/cgroup/perf_event
cgroup /sys/fs/cgroup/memory
cgroup /sys/fs/cgroup/pids
cgroup /sys/fs/cgroup/net_cls,net_prio
cgroup /sys/fs/cgroup/blkio
cgroup /sys/fs/cgroup/devices
cgroup /sys/fs/cgroup/cpuset
cgroup /sys/fs/cgroup/hugetlb
configfs /sys/kernel/config
/dev/mapper/fedora_msi--linux-root /
selinuxfs /sys/fs/selinux
systemd-1 /proc/sys/fs/binfmt_misc
debugfs /sys/kernel/debug
hugetlbfs /dev/hugepages
tmpfs /tmp
mqueue /dev/mqueue
binfmt_misc /proc/sys/fs/binfmt_misc
nfsd /proc/fs/nfsd
/dev/sda1 /boot
/dev/mapper/fedora_msi--linux-home /home
sunrpc /var/lib/nfs/rpc_pipefs
tmpfs /run/user/1000
gvfsd-fuse /run/user/1000/gvfs
fusectl /sys/fs/fuse/connections
/dev/sdc1 /run/media/username/usbname
But using this looks like bad style to me and I don't know how to differ between "/dev/sdc1 /run/media/username/usbname" (the right one) and "/dev/sda1 /boot" (the false one).
Note: The Program is does not have to run on non-Linux operating systems.
Note: I do not want to write directly into /dev/sdc1
I would be thankful if anyone knows how to find the correct mounting points, or if anyone gives me a link to (official) documentation.
Upvotes: 2
Views: 4824
Reputation: 12708
In linux you don't have (in general, it depends on the distribution you use) a fixed path to mount usb devices. Even you don't have them to be mounted automatically (this is something configured in your distribution, but not a general issue). So there's no general standard way to detect that some usb device has been plugged and mounted.
The procedure for mounting automatically usb devices comes from udevd(8)
that is, the daemon in charge of detecting the kernel events about plugged devices into the several buses linux can have attached, receives a message telling some special device has been attached and installs the proper device driver to cope with it (normally, for a usb pendrive, this is a chain of device drivers, terminating in a script that creates the device inodes in /dev/...
and mounts them if applicable). If you read that daemon documentation, you'll see how to install a shell script that will be executed as soon as you detect a new plugged device and it's ready to be mounted.
What is expected this shell script to do. Well, if you want to be conservative, you'll not overwrite each device plugged, if you don't detect something else, that allows you to identify the plugged device. This can be a special labeled partition or something like this, that allows you to recognise the device you want to overwrite or no. It can be something so simple as a magic name in the root directory of that device.
In order to be pragmatic and give you a solution that works without having to read long manual pages, something that should work is to scan periodically the mount table (you get it from /proc/mounts
or reading the output of the mount(8)
command) and detecting which entries have changed since the last time you executed them. If some entry has been added, just check (entries from mount(8)
command have the format mount_device\tmount_directory\tmount_options\t...
and you have to keep the mount_directory
to check if some special named file is in there, and then proceed to copy there all the information you want.
To periodically check the mount table, you have to include in your crontab(7)
file something like:
* * * * check_mounts.sh
and this shell script will be executed each minute to do this kind of work.
Something that can be also useful is to write a timestamp of when it was the last time you wrote information to the plugged device, so you can get information of what has changed since you last wrote to it (this can be the contents of that special file you use to check if this mount point is suitable to write the information you want to store there)
Upvotes: 0
Reputation: 177
In Linux generally, you need to mount the attached device into a directory on your filesystem for reading and writing from that.
In your case, as I can see your distro (Ubuntu perhaps?) has already mounted the device into /run/media/username/usbname, which has been done automatically for end-user. So, your code may works on this distro and does not work on others(or even in Ubuntu server) which requires the mounting progress should be done manually.
I can suggest you research tutorial like this to understand how to work with usb flash drive on Linux first. How to mount the devices manually using command line.
Then make yourself a directory, name it whatever you want. Automatically mount devices to that directory when it is plugged (a bit of Bash scripting, perhaps)
Finally, you can do whatever you want on your directory using C++ without worrying the name changing.
UPDATE
How can I know if the device has been plugged?
Everytime you plug the usb in, dmesg
will write logs for the event. Here is the example from my Ubuntu Desktop when I plug my 32GB Kingston USB.
....
[ 39.647394] scsi 4:0:0:0: Direct-Access Kingston DataTraveler 3.0 PMAP PQ: 0 ANSI: 6
[ 39.647950] sd 4:0:0:0: Attached scsi generic sg1 type 0
[ 41.108262] sd 4:0:0:0: [sdb] 60632064 512-byte logical blocks: (31.0 GB/28.9 GiB)
[ 41.108722] sd 4:0:0:0: [sdb] Write Protect is off
[ 41.108726] sd 4:0:0:0: [sdb] Mode Sense: 23 00 00 00
[ 41.109185] sd 4:0:0:0: [sdb] No Caching mode page found
[ 41.109190] sd 4:0:0:0: [sdb] Assuming drive cache: write through
[ 41.114913] sdb: sdb1
[ 41.120164] sd 4:0:0:0: [sdb] Attached SCSI removable disk
And then the mount
command (without root privilege) can give you the mount point in your filesystem. Eg:
/dev/sdb1 on /media/nuc/MULTIBOOT type fuseblk (rw,nosuid,nodev,allow_other,default_permissions,blksize=4096)
Alternative, you can also read /proc/mounts
to get the same report.
How can I automatically get all this information to my code?
It's your job. In C/C++, you can trigger the commands to the Shell, get the output string, analyzing it using key-words. The output report from Linux is pretty universal, which mean you expect it will be the same from time to time.
Upvotes: 2