Showing posts with label Linux. Show all posts
Showing posts with label Linux. Show all posts

Friday, February 19, 2021

Rename files with Regex rule

 In Linux, there is very powerful tool to rename files based on pattern we specify.  The pattern follows Perl-like regular expression.


For example, if I have files as follow:



01_-_bohemian_rhapsody_-_queen_-_greatest_hits_cd1.mp3

05_-_bicycle_race_-_queen_-_greatest_hits_cd1.mp3

"07_-_it's_a_hard_life_-_queen_-_greatest_hits_cd2.mp3"

09_-_who_wants_to_live_forever_-_queen_-_greatest_hits_cd2.mp3

11_-_the_miracle_-_queen_-_greatest_hits_cd2.mp3

15_-_friends_will_be_friends_-_queen_-_greatest_hits_cd2.mp3

16_-_the_show_must_go_on_-_queen_-_greatest_hits_cd2.mp3

16_-_we_will_rock_you_-_queen_-_greatest_hits_cd1.mp3

17_-_we_are_the_champions_-_queen_-_greatest_hits_cd1.mp3


and I want to rename them by replacing the "_-_" part to be just "-".  The single command to do that is:




$ rename -n -v 's/_-_/-/g' *

rename(01_-_bohemian_rhapsody_-_queen_-_greatest_hits_cd1.mp3, 01-bohemian_rhapsody-queen-greatest_hits_cd1.mp3)

rename(05_-_bicycle_race_-_queen_-_greatest_hits_cd1.mp3, 05-bicycle_race-queen-greatest_hits_cd1.mp3)

rename(07_-_it's_a_hard_life_-_queen_-_greatest_hits_cd2.mp3, 07-it's_a_hard_life-queen-greatest_hits_cd2.mp3)

rename(09_-_who_wants_to_live_forever_-_queen_-_greatest_hits_cd2.mp3, 09-who_wants_to_live_forever-queen-greatest_hits_cd2.mp3)

rename(11_-_the_miracle_-_queen_-_greatest_hits_cd2.mp3, 11-the_miracle-queen-greatest_hits_cd2.mp3)

rename(15_-_friends_will_be_friends_-_queen_-_greatest_hits_cd2.mp3, 15-friends_will_be_friends-queen-greatest_hits_cd2.mp3)

rename(16_-_the_show_must_go_on_-_queen_-_greatest_hits_cd2.mp3, 16-the_show_must_go_on-queen-greatest_hits_cd2.mp3)

rename(16_-_we_will_rock_you_-_queen_-_greatest_hits_cd1.mp3, 16-we_will_rock_you-queen-greatest_hits_cd1.mp3)

rename(17_-_we_are_the_champions_-_queen_-_greatest_hits_cd1.mp3, 17-we_are_the_champions-queen-greatest_hits_cd1.mp3)


(the argument "-n" above is to tell rename not to actually perform renaming, but just to display what it would do).  I use "/g" in the regular expression to tell it to rename all occurrences of "_-_" throughout the file name, not just for the first time it encounters it.

Linux script to display Some information of MP3 files

 The following bash script utilizes mediainfo command line to retrieve various metadata inside an MP3 (or any media file, in fact):


#!/bin/sh

i=0
for f in "$@"
do
    i=$((i+1))
    printf "%d," $i
    mediainfo --Inform="General;%CompleteName%,%Format%,%OverallBitRate_Mode%,%BitRate%,%FileSize/String4%" "${f}"
done





For example (I put the above into a script named 'bitrate.sh'):

$ bitrate.sh *.mp3
1,01_-_bohemian_rhapsody_-_queen_-_greatest_hits_cd1.mp3,MPEG Audio,CBR,256000,10.94 MiB
2,05_-_bicycle_race_-_queen_-_greatest_hits_cd1.mp3,MPEG Audio,CBR,256000,5.612 MiB
3,07_-_it's_a_hard_life_-_queen_-_greatest_hits_cd2.mp3,MPEG Audio,CBR,256000,7.620 MiB
4,09_-_who_wants_to_live_forever_-_queen_-_greatest_hits_cd2.mp3,MPEG Audio,CBR,256000,9.075 MiB
5,11_-_the_miracle_-_queen_-_greatest_hits_cd2.mp3,MPEG Audio,CBR,256000,9.002 MiB
6,15_-_friends_will_be_friends_-_queen_-_greatest_hits_cd2.mp3,MPEG Audio,CBR,256000,7.599 MiB
7,16_-_the_show_must_go_on_-_queen_-_greatest_hits_cd2.mp3,MPEG Audio,CBR,256000,8.048 MiB
8,16_-_we_will_rock_you_-_queen_-_greatest_hits_cd1.mp3,MPEG Audio,CBR,256000,3.741 MiB
9,17_-_we_are_the_champions_-_queen_-_greatest_hits_cd1.mp3,MPEG Audio,CBR,256000,5.542 MiB


The output is in CSV, suitable to be imported as a table in spreadsheet.

Sunday, January 31, 2016

Raspberry Pi vs. Next-Big-Thing's CHIP SoC Computer


Feature
RPI 1 Model A
RPI 1 Model B
RPI 1 Model A+
RPI 1 Model B+
RPI 2ModelB
NBT CHIP

SoC
BRCM 2835
BRCM 2835
BRCM 2835
BRCM 2835

AllWinner's R8
Standard SoC Speed (MHz)
700
700
700
700
900
1000

RAM (MB)
256
512
256
512

512
Ethernet (Mbps)
N/A
100
100
100
1000
N/A

HDMI output
N/A
Yes
Yes
Yes
Yes
With extra module

Composite Video out
Yes
Yes
via 3.5 mm jack
via 3.5 mm jack
via 3.5 mm jackYes

Number of USB2.0
2
2
1
4
4
1

CPU Cores111141
StorageSD CardSD Cardmicro SDmicro SDMicroSDBuilt-in Flash
Internal Storage CapacityN/AN/AN/AN/AN/A4 MB
Camera Interface (CSI)
yesyesyesyesyes
Display Interface (DSI)
yesyesyesyesyes
Video/Graphic CoprocessorVideoCore IVVideoCore IVVideoCore IVVideoCore IVVideoCore IVPowerVR SGX544
ArchitectureARM11v6ARM11v6ARM11v6ARM11v6ARMv7ARMv7
GPIO Pins2640404040

Monday, December 16, 2013

How to mount disk used by ReadyNAS

The following steps are useful if we want to salvage data stored in the drive in ReadyNAS.
I am not sure if the steps below are going to work on other ReadyNAS models, but it works on my ReadyNAS Duo (Sparc CPU).

Basically, what we need is a SATA-to-USB cable (can be bought on the Internet for couple of bucks).
NETGEAR ReadyNAS partitions the drive into 4 partitions.  In my case, it is detected as /dev/sdc:


[root@r3000 media]# fdisk -l /dev/sdc

Disk /dev/sdc: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders, total 1953525168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1               2     4096001     2048000   83  Linux
/dev/sdc2         4096002     4608001      256000   82  Linux swap / Solaris
/dev/sdc3         4608002  1953092233   974242116    5  Extended
/dev/sdc5         4608003  1953092233   974242115+  8e  Linux LVM
[root@r3000 media]# 


There are couple of issues if we try to mount the partitions directly:

  1. ReadyNAS uses non-standard ext3 block-size, which in my case is 16384 bytes (use command "lvsc" to check)
  2. The home directory is partitioned as LV group, so conventional mount command is not gonna work
Here's the steps:
  • Scan the usb for LVM volumes and identify in the output the volume group name that has your READYNAS volume (mine proved to be c):
# vgscan
[root@r3000 media]# vgscan
  Reading all physical volumes.  This may take a while...
  Found volume group "c" using metadata type lvm2
  Found volume group "vg_r3000" using metadata type lvm2
  Found volume group "VolGroup" using metadata type lvm2

  • Activate the group for ReadyNAS (in this case, the group name is "C")
# vgchange -ay c
  • Find the logical volume that  (mine proved to be 'c'):
# lvs
  • root@r3000:/home/root# lvs
      LV   VG   Attr      LSize   Pool Origin Data%  Move Log Copy%  Convert
      c    c    -wi-ao--- 929.09g  
     
  • To display the logical name of the partition, use command "lvdisplay":
# lvdisplay /dev/c
  --- Logical volume ---
  LV Name                /dev/c/c
  VG Name                c
  LV UUID                7HUOrf-B5bL-ur6r-ULsd-yl4m-gCrA-zQc4s9
  LV Write Access        read/write
  LV Status              available
  # open                 0
  LV Size                929.09 GiB
  Current LE             29731
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:5


We cannot use regular command "mount" to mount the non-standard blocksize ext3 partition.  Fortunately, there is a tool called "fuse-ext3" running in userspace that can help us.  The tool can be downloaded here.

Here's an example how to mount my ReadyNAS's LV volume:

fuse-ext2 -o sync_read,allow_other,rw+ /dev/c/c /media/readynas2

And here is the command to mount the system (root) partition which has the Linux software (I will post later about how to reset root password without resetting the ReadyNAS to factory default etc.)

fuse-ext2 -o sync_read,allow_other,rw+ /dev/c/c /media/readynas2


Note: don't forget to unmount the partitions once your'de done.



Thursday, January 17, 2013

Reverse Engineer USB protocol of Canon 4200F (part 1)

So far, there is no Linux driver support available for Canon Scanner 4200F, albeit with the latest and greatest kernel.  Blame the problem to Canon who doesn't want to support Linux community.

With the spirit of hacking, I now try to reverse-engineer the driver (which is only available for Windows, and probably iOS) to be able to write its bare minimum linux driver. I will try to post progress here, so you will see in the title "part x".

First, do this:


mount -t debugfs none_debugs /sys/kernel/debug
modprobe usbmon


do:

lsusb

On my system, it reveals (partially copied here):
..

Bus 001 Device 004: ID 056a:0017 Wacom Co., Ltd Bamboo Fun 4x5
Bus 001 Device 005: ID 046d:08d7 Logitech, Inc. QuickCam Communicate STX
Bus 001 Device 006: ID 04a9:221b Canon, Inc. CanoScan 4200F
Bus 001 Device 007: ID 046d:c52b Logitech, Inc. Unifying Receiver
...

Or, with the class hierarchy:


root@HP-m9000t:~# lsusb -t
1-3.4:1.0: No such file or directory
1-3.7.3:1.0: No such file or directory
/:  Bus 08.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
/:  Bus 07.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
/:  Bus 06.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
/:  Bus 05.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
/:  Bus 04.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
/:  Bus 03.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/8p, 480M
    |__ Port 4: Dev 2, If 0, Class=hub, Driver=hub/4p, 480M
        |__ Port 1: Dev 4, If 0, Class=vend., Driver=mceusb, 1.5M
        |__ Port 1: Dev 4, If 1, Class=HID, Driver=usbhid, 1.5M
        |__ Port 2: Dev 5, If 0, Class=stor., Driver=usb-storage, 480M
    |__ Port 8: Dev 3, If 0, Class=hub, Driver=hub/2p, 480M
/:  Bus 01.Port 1: Dev 1, Class=root_hub, Driver=ehci_hcd/4p, 480M
    |__ Port 3: Dev 2, If 0, Class=hub, Driver=hub/7p, 480M
        |__ Port 1: Dev 3, If 0, Class=hub, Driver=hub/2p, 12M
            |__ Port 1: Dev 9, If 0, Class=HID, Driver=usbhid, 12M
            |__ Port 1: Dev 9, If 1, Class=HID, Driver=usbhid, 12M
            |__ Port 2: Dev 10, If 0, Class=audio, Driver=snd-usb-audio, 12M
            |__ Port 2: Dev 10, If 1, Class=audio, Driver=snd-usb-audio, 12M
            |__ Port 2: Dev 10, If 2, Class=audio, Driver=snd-usb-audio, 12M
        |__ Port 2: Dev 4, If 0, Class=HID, Driver=wacom, 12M
        |__ Port 3: Dev 5, If 0, Class=vend., Driver=gspca_zc3xx, 12M
        |__ Port 3: Dev 5, If 1, Class=audio, Driver=snd-usb-audio, 12M
        |__ Port 3: Dev 5, If 2, Class=audio, Driver=snd-usb-audio, 12M
        |__ Port 4: Dev 6, If 0, Class=vend., Driver=, 480M
        |__ Port 6: Dev 7, If 0, Class=HID, Driver=usbhid, 12M
        |__ Port 6: Dev 7, If 1, Class=HID, Driver=usbhid, 12M
        |__ Port 6: Dev 7, If 2, Class=HID, Driver=usbhid, 12M
        |__ Port 7: Dev 8, If 0, Class=hub, Driver=hub/4p, 12M
            |__ Port 2: Dev 11, If 0, Class=stor., Driver=usb-storage, 12M
            |__ Port 3: Dev 12, If 0, Class=vend., Driver=, 12M
            |__ Port 3: Dev 12, If 1, Class=vend., Driver=ftdi_sio, 12M
root@HP-m9000t:~# 

As can be seen above, there is no driver available for the scanner.



Then open with a text editor this file: /sys/kernel/debug/usb/devices.  Search for "Canon" (or search by Vendor and product ID found above).


T:  Bus=01 Lev=02 Prnt=02 Port=03 Cnt=04 Dev#=  6 Spd=480  MxCh= 0
D:  Ver= 2.00 Cls=ff(vend.) Sub=ff Prot=ff MxPS=64 #Cfgs=  1
P:  Vendor=04a9 ProdID=221b Rev= 2.00
S:  Manufacturer=Canon
S:  Product=CanoScan
C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr= 10mA
I:* If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none)
E:  Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
E:  Ad=83(I) Atr=03(Int.) MxPS=   1 Ivl=16ms

From the information above, we can see that the scanner uses three endpoints:

  • One OUT bulk endpoint
  • One IN bulk endpoint
  • One IN interrupt endpoint
We then can tell our PC uses OUT bulk for general control dan normal data to send to the scanner, uses  IN bulk endpoint to receive scanned/preview image from the scanner, and IN interrupt endpoint for receiving other interrupts (e.g, when any of the scanner's buttons is pressed)

How to use usbmon?

The captured data are stored in /sys/kernel/debug/usb/usbmon/<file>, where file can be "0u" to capture packets in all buses, and <bus#>u for a specific bus.  Where can we find the bus number information? See the content of file device above!.  The first line says "Bus=01", it means to capture packets to/from the scanner, we just need to cat file "1u" (the detail instruction/documentation about usbmon can be read here: http://lxr.linux.no/linux+v2.6.28.8/Documentation/usb/usbmon.txt)

An easier way is to use Wireshark (as root, because we need to gain access to usb devices).  Start capture for sometime and stop it.  Apply filter " usb.idVendor == 0x4a9 && usb.idProduct == 0x221b" or "usb.device_address == 6 && usb.bus_id==1".  In my case, I know the scanner is address 6 and bus=1.  Save the captured data to a file (select "Wireshark/tcpdump" format).  

To read it:

tshark -r pcapfile -T fields -V -e usb.capdata

or

tshark -r pcapfile -T fields -x

For example:

root@HP-m9000t:~# tshark -P -r ./usbscanner1.pcap -x -V -R "usb.bus_id==1 && usb.device_address==6"

tshark: Lua: Error during loading:
 [string "/usr/share/wireshark/init.lua"]:45: dofile has been disabled
Running as user "root" and group "root". This could be dangerous.
Frame 528: 64 bytes on wire (512 bits), 64 bytes captured (512 bits)
    WTAP_ENCAP: 115
    Arrival Time: Jan 17, 2013 22:29:25.703289000 PST
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1358490565.703289000 seconds
    [Time delta from previous captured frame: 0.000025000 seconds]
    [Time delta from previous displayed frame: 0.000000000 seconds]
    [Time since reference or first frame: 2.030187000 seconds]
    Frame Number: 528
    Frame Length: 64 bytes (512 bits)
    Capture Length: 64 bytes (512 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: usb]
USB URB
    URB id: 0xffff88013280d240
    URB type: URB_SUBMIT ('S')
    URB transfer type: URB_CONTROL (0x02)
    Endpoint: 0x80, Direction: IN
        1... .... = Direction: IN (1)
        .000 0000 = Endpoint value: 0
    Device: 6
    URB bus id: 1
    Device setup request: relevant (0)
    Data: not present ('<')
    URB sec: 1358490565
    URB usec: 703289
    URB status: Operation now in progress (-EINPROGRESS) (-115)
    URB length [bytes]: 40
    Data length [bytes]: 0
URB setup
    bmRequestType: 0x80
        1... .... = Direction: Device-to-host
        .00. .... = Type: Standard (0x00)
        ...0 0000 = Recipient: Device (0x00)
    bRequest: GET DESCRIPTOR (6)
    Descriptor Index: 0x00
    bDescriptorType: DEVICE (1)
    Language Id: no language specified (0x0000)
    wLength: 40

0000  40 d2 80 32 01 88 ff ff 53 02 80 06 01 00 00 3c   @..2....S......<
0010  c5 eb f8 50 00 00 00 00 39 bb 0a 00 8d ff ff ff   ...P....9.......
0020  28 00 00 00 00 00 00 00 80 06 00 01 00 00 28 00   (.............(.
0030  00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00   ................

Frame 529: 82 bytes on wire (656 bits), 82 bytes captured (656 bits)
    WTAP_ENCAP: 115
    Arrival Time: Jan 17, 2013 22:29:25.704138000 PST
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1358490565.704138000 seconds
    [Time delta from previous captured frame: 0.000849000 seconds]
    [Time delta from previous displayed frame: 0.000849000 seconds]
    [Time since reference or first frame: 2.031036000 seconds]
    Frame Number: 529
    Frame Length: 82 bytes (656 bits)
    Capture Length: 82 bytes (656 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: usb]
USB URB
    URB id: 0xffff88013280d240
    URB type: URB_COMPLETE ('C')
    URB transfer type: URB_CONTROL (0x02)
    Endpoint: 0x80, Direction: IN
        1... .... = Direction: IN (1)
        .000 0000 = Endpoint value: 0
    Device: 6
    URB bus id: 1
    Device setup request: not relevant ('-')
    Data: present (0)
    URB sec: 1358490565
    URB usec: 704138
    URB status: Success (0)
    URB length [bytes]: 18
    Data length [bytes]: 18
    [Request in: 528]
    [Time from request: 0.000849000 seconds]
    [bInterfaceClass: Unknown (0xffff)]
DEVICE DESCRIPTOR
    bLength: 18
    bDescriptorType: DEVICE (1)
    bcdUSB: 0x0200
    bDeviceClass: VENDOR_SPECIFIC (0xff)
    bDeviceSubClass: 255
    bDeviceProtocol: 255
    bMaxPacketSize0: 64
    idVendor: 0x04a9
    idProduct: 0x221b
    bcdDevice: 0x0200
    iManufacturer: 3
    iProduct: 4
    iSerialNumber: 0
    bNumConfigurations: 1

0000  40 d2 80 32 01 88 ff ff 43 02 80 06 01 00 2d 00   @..2....C.....-.
0010  c5 eb f8 50 00 00 00 00 8a be 0a 00 00 00 00 00   ...P............
0020  12 00 00 00 12 00 00 00 00 00 00 00 00 00 00 00   ................
0030  00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00   ................
0040  12 01 00 02 ff ff ff 40 a9 04 1b 22 00 02 03 04   .......@..."....
0050  00 01                            

usb.capdata is one of the fields.  There are many other fields we can display.  Check WireShark documentation http://www.wireshark.org/docs/dfref/u/usb.html for more detail.

Because there is still no clue from the collected data above (except information about host queried the scanner and the scanner responded back), I will try again on Windows, where there the original driver has been installed.

(to be continued...)



Saturday, June 23, 2012

How to set root password on ReadyNAS

Recently I had forgotten my ReadyNAS password.  Even worse, I couldn't login at all due reckless upgrade I did on the box.  I was able to undo the upgrade by letting the box recopy the Linux from its firmware to the drive (see ReadyNAS forum/documentation on how to make the ReadyNAS box recopy the firmware), but still I forgot what my root password was.

Various steps I had tried as I found on the Internet as well as on the ReadyNAS website, but none of them work. Finally, I had an idea to just access the drive directly thru SATA-to-USB cable and reset the password manually.

Basically what I did was to set the root password stored in the file /etc/passwd (fortunately the authententication is still the old-fashioned one, where the MD5 encrypted password stored directly in the file instead in shadow file).

You might ask, "How the hell I access the drive?".  Well, first you need remove the drive from the ReadyNAS bay (make sure it is turned off!!) then  attach the SATA-to-USB cable to the drive.  Connect the usb end to our PC.

We cannot mount directly to the drive, because some other issues.  To mount, see my previous post ("How to mount disk used by ReadyNAS").  Once it is  mounted (just mount the ext3 partition [first partition], no need to mount the LVM), we can now modify the file /etc/passwd.

First, save the following script (thanks to somebody who posted it on the Internet), say, as /home/<yourloginname>/bin/setpasswd:


#!/usr/bin/perl
################################################################################
# Generate an MD5 hash for a string.
# Created to allow me to set a blank Linux password. Required this to create
# multiple VsFTP accounts with anonymous style credientials.
#
# If all you want is the MD5 Hash for NULL (blank password) here's one...
# $1$VNMbpxGH$sew7cnwH9ixU.x27UbFNn.
#
# Advice: If replacing a Linux password with a blank string, ensure you give 
# the user a shell of /sbin/nologin as you wouldn't want them to login!
################################################################################
# Load dependancies...
# perl -MCPAN -e 'install Crypt::PasswdMD5'
################################################################################

use strict;
use Crypt::PasswdMD5 qw(unix_md5_crypt);
my @salt = ( '.', '/', 0 .. 9, 'A' .. 'Z', 'a' .. 'z' );
my %encrypted;


sub abort {
print "ABORT: $_[0]\n";
exit 1
}


sub gensalt { #------------------------------------------------------------
# uses global @salt to construct salt string of requested length
my $count = shift;

my $salt;
for (1..$count) {
$salt .= (@salt)[rand @salt];
}

return $salt;
} # end gensalt


sub get_encryptedpw { #--------------------------------------------------
my $unencrypted="$_[0]";

# generate traditional (weak!) DES password, and more modern md5
$encrypted{des} = crypt( $unencrypted, gensalt(2) );
$encrypted{md5} = unix_md5_crypt( $unencrypted, gensalt(8) );

return %encrypted;
}

################################################################################
print "Enter password string to encrypt (can be blank) : ";
my $password = <STDIN>;
chomp $password;

get_encryptedpw($password);

print "Plaintext \"$password\" = MD5 Hash: $encrypted{md5}\n";
print "\nReplace the /etc/shadow password string with the above to force pass change\n";


(Don't forget to make it executable by doing "chmod +x ./setpasswd)
Run the script.  It will ask you to enter a password.  An example of the output (with blank password):


$ setpasswd
Enter password string to encrypt (can be blank) : 
Plaintext "" = MD5 Hash: $1$udf2EDLY$a/cLQQ4h25rwZQc9VKmG6/

Replace the /etc/shadow password string with the above to force pass change

Copy the portion after the string "MD5 Hash: " above and paste it in the <READYNAS MOUNTPOINT>/etc/passwd.  To be precise, it should be pasted in line where "root:...". Paste it right after "root:", and let the rest of the existing text still intact.

Save the file, unmount (just use the regular umount for this one), reinsert the drive into the ReadyNAS bay and turn it on.  Once it is running, try to SSH to the box as root and enter the new password.  It should work!