programmatically detect SD card write protect - linux

Back in the good-old days of floppy, if you enable write protection of a floppy, DOS would kindly tell you that you cannot write to it. Now we have SD card that can hold the content of thousands of floppy and we still have the write protection - and it's handy sometime. But nobody is able to tell me I can't write to it, at least on Linux. I have a lovely script that partition and format a SD card in a way I like. It took me 1/2 hour of debugging just to find out that the SD card is write-protected.
So the question, is there a way that the software can detect such condition?
Thanks,

The driver knows when the card is write-protected, and it actually warns when you mount it via command line:
# mount /dev/sdc1 /media/flash
mount: block device /dev/sdc1 is write-protected, mounting read-only
In case you would like to check it yourself at device level, you can use the hdparm command to query read-only status of disk device, including SD card and USB flash drive in general. This program should be available in most GNU/Linux distributions, commonly in a package named "hdparm".
If you are not root, be sure to specify full path to the hdparm command; and this assumes you have read permission on your card of course.
For example: my SD card is inserted, detected as /dev/sdc, and write protection tab is at Unlock:
$ /sbin/hdparm -r /dev/sdc
/dev/sdc:
readonly = 0 (off)
When I slided the write protection tab to Lock, re-insert the card, and run the command again:
$ /sbin/hdparm -r /dev/sdc
/dev/sdc:
readonly = 1 (on)
If you would like to do it in shell script, you can try something like:
READONLY=`/sbin/hdparm -r /dev/sdc 2>&1 | sed -n 's/^.*= *\([01]\) .*$/\1/p'`
if [ "$READONLY" = "0" ]
then
echo Card is writable.
else
echo Card is not writable.
fi
Note: If you prefer to do it in C, you can try either:
Opening the device file in write mode and see if it fails with errno value EROFS (Read-only file system), or...
Opening the device file in read mode, then issue ioctl() named BLKROGET, and check if the result value is nonzero; this is the way hdparm work.

Related

on linux, how do I list only mounted removable media / device?

I know we can list all mounted devices using the mount command. or even the df command.
But how can we know if the listed device is removable or not, such as USB, CMROM, External Hardisk, etc?
For this question, we can start with how to do it on SUSE or RedHat.
Thanks!
After thinking about this a bit more, the way to determine if a drive is removable is to check whether the contents of:
/sys/block/sdX/removable
Is set to 0 - non-removable or 1 - removable. You can get the list of mounted drives (presuming the form /dev/sdX where X is a, b, c, etc..) and then loop over the devices checking the contents of the removable file.
For bash using Process-Substitution to feed a while loop to loop over the device names removing the trailing partition digits and only taking unique devices you could do:
#!/bin/bash
while read -r name; do
if [ "$(<${name/dev/sys\/block}/removable)" -eq "1" ]; then
echo "$name - removable"
else
echo "$name - non-removable"
fi
done < <(awk '/^\/dev\/sd/ {sub(/[0-9]+$/,"",$1); print $1}' /proc/mounts | uniq)
Which will list all devices and whether they are removable. For example, running the script with a flash drive inserted (/dev/sdc) and my normal hard drive (/dev/sdb), you would receive:
$ bash list-removable.sh
/dev/sdb - non-removable
/dev/sdc - removable
There are probably many other ways to do it.
You can do something like this:
for dev in /dev/disk/by-id/usb*; do mount | grep $(readlink -f ${dev}); done
This first runs mount to list devices that are mounted. It then looks at /dev/disk/by-id/ which will have a udev link to the device, using the manufacture id of the device. This link will resolve to the /dev/device that it corresponds to. It greps the output of mount for these devices and will display them on the screen along with their current mount points and fs options.
*Edit to include checking against mount

How to mount a character device like eeprom in LINUX

I know I can mount a block device like SD card by the following command;
mount /dev/mmcblk /mnt/SD
Then I can use ls and cp command in the filesystem in SD. I can also execute a file in it.
However, I don't know how to mount a character device like eeprom or nor flash which is controled by I2C or SPI.
I want to make a embedded system that doesn't depend on SD. My goal is to use ls or cp command, and execute some files in such devices like you can do it in SD.
Actually, I made an original I2C driver in which I can open, read and write data through /dev/myi2cdriver.
But when I mount that device file, error message appears saying "device is not a block device" and mount fails.
Could you give me advices?
As you have seen, this isn't intended to work.
You could probably copy /dev/myi2cdriver to a file and mount -o loop that. You might be able to just mount -o loop your character device directly.
Alternatively, develop a block device driver?

How to insert my driver automatically on the insertion of USB mouse in Linux System?

I know that on the insertion of any usb device in the Linux system a specific device driver got loaded. Now I want to insert my driver on the insertion of USB mouse.
I know that I can do this task using two approaches: by using depmod or using udev concept. I have read a few things about it on the Internet but I don't get the exact answer. Can anyone suggest which approach is best to use and for that in the Linux kernel tree where I need to make changes?
Thanks all for your help.
I follow the udev approach to load module automatically on the USB insertion
Below is the procedure to load your Driver automatically on the Insertion of Hot plug-gable device (I experiment with the USB mouse and below procedure is working fine for it)
Run Following command
cmd > udevadm info -a -p $(udevadm info -q path -n /dev/input/mouse)
In place of ?? in the above command user need to add the device ID based on its entry in /dev (e.g.for USB flash drive: sdb1 or sda1 etc. based on the device identity)
Get the Value of the below parameters from the output of above command
KERNEL, ATTRS{idVendor}, ATTRS{idProduct}, ATTRS{serial}
Go to /etc/dev/rule.d directory and Add your rule
cmd > sudo vim 40-usbmouse.rules
ACTION=="add", SUBSYSTEM=="block", KERNEL=="sd?1", ATTRS{idVendor}=="058f", ATTRS{idProduct}=="6387", ATTRS{serial} =="4EPLXAXE", SYMLINK+="usbpd", RUN+="/usr/local/bin/InsertModule.sh"
Save this file.
Above rule is defined for the USB Mouse.
Parameter SYMLINK creates a link of your device in the /dev directory and In RUN+ you can give your script location which is going to execute on your device insertion.
For more info on How to write a rule refer below link
http://hackaday.com/2009/09/18/how-to-write-udev-rules/
Now after you define your rule user need to restart the udev to take your rule in notice by kernel.
cmd > sudo stop udev
cmd > sudo start udev
Insert your USB and validate that your script which you define in your rule shows its effact.
For Mouse user can use below command
cmd > udevadm info -a -p $(udevadm info -q path -n /dev/input/mouse)
P.S.: cmd stands for the command shell (Terminal).The above procedure is working with any USB device.
You may use MODULE_SOFTDEP macro defined in module.h in your driver where you can specify the name of the USB driver which gets loaded when the USB mouse is inserted. This will load your driver automatically. The depmod approach is the way to go.
Use MODULE_DEVICE_TABLE macro. That will export supported device table so that your hotplug tool (whether it udev or something else) can load your module. I've described the loading process in this answer.
To see example usage, refer to drivers/hid/usbhid/usbmouse.c. If this driver compiled as module, it is loaded every time any usb mouse is attached.

Detecting USB Thumb Drive when Ready in Linux Shell Script

I am a Windows admin and dev, I do not generally work with Linux so forgive me if this is in some way obvious.
I have a not so good Linux box, some older version of Open SUSE, and I have a script that unmounts the USB thumb drive, formats it, and then waits for the device to become ready again before it runs a script that does a copy/MD5 checksum verification on the source and destination file to ensure the copy was valid. The problem is that on one box the USB thumb drive does not become ready after the format in a consistent way. It takes anywhere from 1 to 2+ minutes before I can access the drive via /media/LABELNAME.
The direct path is /dev/sdb but, of course, I cannot access it directly via this path to copy the files. Here is my shell script as it stands:
#!/bin/bash
set -e
echo "Starting LABELNAME.\n\nUnmounting /dev/sdb/"
umount /dev/sdb
echo "Formatting /dev/sdb/"
mkfs.vfat -I -F32 -n "LABELNAME" /dev/sdb
echo "Waiting on remount..."
sleep 30
echo "Format complete. Running make master."
perl /home/labelname_master.20120830.pl
Any suggestions? How might I wait for the drive to become ready and detect it? I have seen Detecting and Writing to a USB Key / Thumb DriveAutomatically but quite frankly I don't even know what that answer means.
It seems that you have some automatic mounting service running which detects the flash disk and mounts the partition. However, you already know what the partition is, so I recommend that you simply mount the disk in your script, choosing a suitable mount point yourself.
mkfs.vfat -I -F32 -n "LABELNAME" /dev/sdb
echo "Format complete, remounting"
mount /dev/sdb $mountpoint #<-- you would choose $mountpoint
echo "Running make master."
perl /home/labelname_master.20120830.pl

bash command to force file closure on usb drive

I thought doing a sync in my bash script would force the file to be completely written out. When I looked at the thumb drive, it showed all the files I had copied, but after a power supply failure, the usb drive showed 0 files. Do I have to eject the drive manually or is there something I can do programmatically in my script?
If you want to eject the usb device from your bash script a simple umount on the device should do the trick. For example
mount /dev/usb /mnt/usb
# Your copy operations here... then on success:
umount /mnt/usb
you can also try to use the linux sync instruction that syncronize writing over disk if you're usb key is using a journalized file system

Resources