gdt: Kangaroo road sign (Default)

The uBITX uses an Arduino internally. This article describes how to update its software.

Required hardware

The connector on the back is a Mini-B USB connector, so you'll need a "Mini-B to A" USB cable. This is not the same cable as used with older Android smartphones. The Mini-B connector was used with a lot of cameras a decade ago.

You'll also need a computer. I use a laptop with Fedora Linux installed.

Required software for software development

In Fedora all the required software is installed with sudo dnf install arduino git. Add yourself to the users and lock groups with sudo usermod -a -G users,lock $USER (on Debian-style systems use sudo usermod -a -G dialout,lock $USER). You'll need to log out and log in again for that to have an effect (if you want to see which groups you are already in, then use the id command).

Run arduino as your ordinary non-root user to create the directories used by the Arduino IDE. You can quit the IDE once it starts.

Obtain the uBITX software

$ cd ~/Arduino
$ git clone https://github.com/afarhan/ubitxv6.git ubitx_v6.1_code

Connect the uBITX to your computer

Plug in the USB cable and turn on the radio. Running dmesg will show the Arduino appearing as a "USB serial" device:

usb 1-1: new full-speed USB device number 6 using xhci_hcd
usb 1-1: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.64
usb 1-1: New USB device strings: Mfr=0, Product=2, SerialNumber=0
usb 1-1: Product: USB Serial
usbcore: registered new interface driver ch341
usbserial: USB Serial support registered for ch341-uart
ch341 1-1:1.0: ch341-uart converter detected
usb 1-1: ch341-uart converter now attached to ttyUSB1

If you want more information about the USB device then use:

$ lsusb -d 1a86:7523
Bus 001 Device 006: ID 1a86:7523 QinHeng Electronics CH340 serial converter
gdt: Kangaroo road sign (Default)

udev can be used to block a USB device (or even an entire class of devices, such as USB storage). Add a file /etc/udev/rules.d/99-local-blacklist.rules containing:

SUBSYSTEM=="usb", ATTRS{idVendor}=="0123", ATTRS{idProduct}=="4567", ATTR{authorized}="0"
gdt: Kangaroo road sign (Default)

This has become substantially simpler in Fedora 29:

sudo dnf install notebook R-IRKernel R-IRdisplay
gdt: Kangaroo road sign (Default)

In case you want to choose a different security compromise, the update has a nice summary:

wpasupplicant (2:2.6-19) unstable; urgency=medium

  With this release, wpasupplicant no longer respects the system
  default minimum TLS version, defaulting to TLSv1.0, not TLSv1.2. If
  you're sure you will never connect to EAP networks requiring anything less
  than 1.2, add this to your wpasupplicant configuration:

    tls_disable_tlsv1_0=1
    tls_disable_tlsv1_1=1

  wpasupplicant also defaults to a security level 1, instead of the system
  default 2. Should you need to change that, change this setting in your
  wpasupplicant configuration:

    openssl_ciphers=DEFAULT@SECLEVEL=2

  Unlike wpasupplicant, hostapd still respects system defaults.

 -- Andrej Shadura <…@debian.org>  Sat, 15 Dec 2018 14:22:18 +0100
gdt: Kangaroo road sign (Default)

To find passwords in libsecret you need to know what attributes to search for. These are often set by some shim but not documented. The attributes tend to vary by shim.

For git's libsecret shim the attributes are: protocol, server, user.

A worked example, the account gdt on git.example.org:

$ secret-tool search --all 'protocol' 'https' 'server' 'git.example.org' 'user' 'gdt'
[/org/freedesktop/secrets/collection/login/123]
label = Git: https://git.example.org/
secret = CvKxlezMsSDuR7piMBTzREJ7l8WL1T
created = 2019-02-01 10:20:34
modified = 2019-02-01 10:20:34
schema = org.gnome.keyring.NetworkPassword
attribute.protocol = https
attribute.server = git.example.org
attribute.user = gdt

Note that the "label" is mere documentation, it's the "attribute" entries which matter.

gdt: Kangaroo road sign (Default)

The screen brightness is held in a EFI variable.

hexdump /sys/firmware/efi/efivars/backlight-level-7c436110-ab2a-4bbb-a880-fe41995c9f82 
0000000 0007 0000 0101
gdt: Kangaroo road sign (Default)
$ sudo install netcdf-devel
$ R --no-restore --no-save
> install.packages('ncdf4')
> q()

There's a good summary of using NetCDF here.

gdt: Kangaroo road sign (Default)

Jupyter with Python

Fedora loves Python has the good oil:

$ sudo dnf install notebook
$ jupyter notebook

Jupyter with R

Firstly, install Jupyter with Python, as above.

IRkernel has the good oil. I've modified their advice to install RPM packages where they are available:

$ sudo dnf install czmq-devel libcurl-devel openssl-devel
$ sudo dnf install R-crayon R-pbdZMQ R-repr
$ R --no-restore --no-save
> install.packages('devtools')
> devtools::install_github(paste0('IRkernel/', c('IRdisplay', 'IRkernel')))
> IRkernel::installspec()
> q()

If you want to do a system-wide installation then run R as root, proceed as above, but the last step is:

> IRkernel::installspec(user = FALSE)

gdt: Kangaroo road sign (Default)

The Linux kernel has fixes for Meltdown, Spectre v1 and Spectre v2. Check the status with:

$ cat /sys/devices/system/cpu/vulnerabilities/meltdown
Mitigation: PTI
$ cat /sys/devices/system/cpu/vulnerabilities/spectre_v1
Mitigation: __user pointer sanitization
$ cat /sys/devices/system/cpu/vulnerabilities/spectre_v2
Mitigation: Full generic retpoline

You'd think that would be enough. But Linux has fucked it up. Here's the output from a Raspberry Pi 3 running 4.9.80. That ARM CPU doesn't have instruction speculation and this isn't vulnerable to Meltdown or Spectre-style bugs.

$ ls /sys/devices/system/cpu/vulnerabilities
ls: cannot access '/sys/devices/system/cpu/vulnerabilities': No such file or directory

That's right. We can't tell if the CPU is immune to the issue or if the Linux kernel is too old to have a fix for the issue. A program wanting to check this is going to have to carry around a table of CPU architectures and Linux versions. Which is likely going to be wrong, because who's going to know the data a fix for Spectre made it into a MIPS build. Classic. All Linux needed to do was to create /sys/devices/system/cpu/vulnerabilities for all architectures. Sigh.

gdt: Kangaroo road sign (Default)

From NANOG list:

dig o-o.myaddr.l.google.com -t txt +short @8.8.8.8

dd

2017-04-01 09:38
gdt: Kangaroo road sign (Default)
The reason for using dd to write to USB flash sticks is historical.

On some other UNIX-like operating systems only "raw" block devices present the partition table, boot sector and unpartitioned space. Specifically, whereas Linux presents a /dev/sda block device containing all the bytes of a disk, in those other operating systems the equivalent would be a /dev/rsda raw block device.

In those other UNIX-like operating systems you must write to raw block devices in multiples of the sector size of the device. dd can do this, cp and cat cannot. How you discover a device's sector size was left as an exercise for the reader, it is traditionally 0.5KB, more recently 4KB, and three orders of magnitude larger again for flash devices.

Linux doesn't have raw devices, so using dd isn't needed to write an image to a disk. You can wget -O /dev/sd𝐱 … a Fedora .iso file directly onto the USB flash drive.

Note that some devices perform better when handed data is particular block sizes. Most USB sticks perform best if handed data in 4MB chunks. dd is useful if you want that optimisation: wget -O - … | dd of=/dev/sd𝐱 bs=4M status=progress. Note that if you do not set the bs blocksize then the default of 0.5KB is going to make writing a USB flash stick very slow.
gdt: Kangaroo road sign (Default)

Understand stable privacy addressing

In Three new things to know about deploying IPv6 I described the new IPv6 Interface Identifier creation scheme in RFC7217.* This scheme results in an IPv6 address which is stable, and yet has no relationship to the device's MAC address, nor can an address generated by the scheme be used to track the machine as it moves to other subnets.

This isn't the same as RFC4941 IP privacy addressing. RFC4941 addresses are more private, as they change regularly. But that instability makes attaching to a service on the host very painful. It's also not a great scheme for support staff: an unstable address complicates network fault finding. RFC7217 seeks a compromise position which provides an address which is difficult to use for host tracking, whilst retaining a stable address within a subnet to simplify fault finding and make for easy hosting of services such as SSH.

The older RFC4291 EUI-64 Interface Identifier scheme is being deprecated in favour of RFC7217 stable privacy addressing.

For servers you probably want to continue to use static addressing with a unique address per service. That is, a server running multiple services will hold multiple IPv6 addresses, and each service on the server bind()s to its address.

Configure stable privacy addressing

To activate the RFC7217 stable privacy addressing scheme in a Linux which uses Network Manager (Fedora, Ubuntu, etc) create a file /etc/NetworkManager/conf.d/99-local.conf containing:

[connection]
ipv6.ip6-privacy=0
ipv6.addr-gen-mode=stable-privacy

Then restart Network Manager, so that the configuration file is read, and restart the interface. You can restart an interface by physically unplugging it or by:

systemctl restart NetworkManagerip link set dev eth0 down && ip link set dev eth0 up

This may drop your SSH session if you are accessing the host remotely.

Verify stable privacy addressing

Check the results with:

ip --family inet6 addr show dev eth0 scope global
1: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2001:db8:1:2:b03a:86e8:e163:2714/64 scope global noprefixroute dynamic 
       valid_lft 2591932sec preferred_lft 604732sec

The highlighted Interface Identifier part of the IPv6 address should have changed from the EUI-64 Interface Identifier; that is, the Interface Identifier should not contain any bytes of the interface's MAC address. The other parts of the IPv6 address — the Network Prefix, Subnet Identifier and Prefix Length — should not have changed.

If you repeat the test on a different subnet then the Interface Identifier should change. Upon returning to the original subnet the Interface Identifier should return to the original value.

gdt: Kangaroo road sign (Default)

It's useful when experimenting with network to have a lot of machines for testing — the development machine; a system under test; a machine running a packet capture. But that leads to a lot of machines. Another approach is to buy a USB hub and a handful of USB/ethernet dongles. Usually we're much more interested in mere connectivity rather than performance, so the shared USB bus back to the computer doesn't worry us.

Let's say a dongle appears as eth1. We can configure that separately from the main set of routing tables by using network namespaces. Users of networking platforms might know this as VRF — virtual routing and forwarding — but Linux's namespace approach applies more widely throughout the operating system than merely the networking components.

Begin by creating the network namespace:

$ sudo ip netns add TEST
$ ip netns show
TEST

[Aside: For descriptive clarity I am using a network namespace name which is all upper case. In the real world we will use lower case.]

Now move the eth1 interface into that namespace:

$ ip link show dev eth1
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 11:22:33:44:55:66 brd ff:ff:ff:ff:ff:ff
$ ip link set dev eth1 netns TEST
$ ip link show dev eth1
Device "eth1" does not exist.

The magic arrives when we can execute commands within that namespace, in this case ip link show dev eth1 to display the ethernet-layer details of eth1:

$ sudo ip netns exec TEST ip link show dev eth1
2: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether 11:22:33:44:55:66 brd ff:ff:ff:ff:ff:ff

The link is down. Let's bring it up:

$ sudo ip netns exec TEST ip link set dev eth1 up
$ sudo ip netns exec TEST ip link show dev eth1
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000

Let's apply an IP address.

$ sudo ip netns exec TEST ip addr add 192.168.255.1/24 dev eth1

Note carefully that every namespace has its own routing table. Sometimes merely being connected to the subnet is enough to do what we need to do. But if we do need a default route then it can be added manually:

$ sudo ip netns exec TEST ip route add 0.0.0.0/0 via 192.168.255.254 dev eth1
$ sudo ip netns exec TEST ip route show
default via 192.168.255.254 dev eth1 
192.168.255.0/24 dev eth1  proto kernel  scope link  src 192.168.255.1
$ sudo ip netns exec TEST ping www.fsf.org
64 bytes from www.fsf.org (208.118.235.174): icmp_seq=1 ttl=43 time=266 ms

If we are connecting to a production network then DHCP works too:

$ sudo ip netns exec TEST dhclient -v eth1
Listening on LPF/eth1/11:22:33:44:55:66
Sending on   LPF/eth1/11:22:33:44:55:66
Sending on   Socket/fallback
DHCPREQUEST on eth1 to 255.255.255.255 port 67
DHCPACK from 192.168.255.254
bound to 192.168.255.96 -- renewal in 10000 seconds.

You'll recall that the concept of "namespaces" is broader than the concept of "VRFs". Although the "dhclient" program appears in ps's process list, the program is executing within the TEST network namespace. It is best to manipulate the program from within that network namespace by using the command ip netns exec …. We can see what network namespace a process is in with:

$ sudo ip netns pids TEST
12345
$ sudo ip netns identify 12345
TEST

As is usual, IPv6 just works. If there is subnet connectivity then the interface has a link local address. If there is global connectivity then the interface also has a global address. You can use IPv6 and mDNS (via Linux's "Avahi" package) to use symbolic names for systems under test.

We needn't be limited to just one namespace. Let's say we're testing a new SDN switch. We could put interface eth1 into a PORT1 namespace and cable it to Port 1 of the switch. We could put interface eth2 into a PORT2 namespace can cable it to Port 2 of the switch. By using namespaces we can be sure that a ping attempt from eth1 to eth2 isn't using the Linux machine's usual routing table, but is using the namespaces' routing tables. That routing can send the packets across the eth1, and — if the switch is working — through switch ports Port 1 and Port 2, before appearing at eth2.

When we are done we can list all the process IDs in the namespace, kill them all, then delete the namespace with:

$ sudo ip netns delete TEST

If we just want to move the interface out of the TEST namespace and into the default namespace that's made tricky by the default namespace having no name. Here's how to give that namespace a name and move the interface:

$ sudo touch /run/netns/default
$ sudo mount --bind /proc/1/ns/net /run/netns/default
$ sudo ip netns exec TEST ip link set dev eth1 down
$ sudo ip netns exec TEST ip link set dev eth1 netns default
$ sudo umount /run/netns/default
$ sudo rm /run/netns/default

We set the interface to "down" to forestall the interface from conflicting with the addressing of another running interface in the destination namespace.

gdt: Kangaroo road sign (Default)

Say you've got a file you want to put into an executable. Some help text, a copyright notice. Putting these into the source code is painful:

static const char *copyright_notice[] = {
 "This program is free software; you can redistribute it and/or modify",
 "it under the terms of the GNU General Public License as published by",
 "the Free Software Foundation; either version 2 of the License, or (at",
 "your option) any later version.",
 NULL   /* Marks end of text. */
};
#include <stdio.h>
const char **line_p;
for (line_p = copyright_notice; *line_p != NULL; line_p++) {
  puts(*line_p);
}

If the file is binary, such as an image, then the pain rises exponentially. If you must take this approach then you'll want to know about VIM's xxd hexdump tool:

$ xxd -i copyright.txt > copyright.i

which gives a file which can be included into a C program:

unsigned char copyright_txt[] = {
  0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d,
  0x20, 0x69, 0x73, 0x20, 0x66, 0x72, 0x65, 0x65, 0x20, 0x73, 0x6f, 0x66,
…
  0x30, 0x31, 0x2c, 0x20, 0x55, 0x53, 0x41, 0x2e, 0x0a
};
unsigned int copyright_txt_len = 681;

That program looks like so:

#include "copyright.i"
unsigned char *p;
unsigned int len;
for (p = copyright_txt, len = 0;
     len < copyright_txt_len;
     p++, len++) {
  putchar(*p);
}

If you are going to use this in anger then modify the generated .i file to declare a static const unsigned char …[]. A sed command can do that easily enough; that way the Makefile can re-create the .i file upon any change to the input binary file.

It is much easier to insert a binary file using the linker, and the rest of this blog post explores how that is done. Again the example file will be copyright.txt, but the technique applies to any file, not just text.

Fortunately the GNU linker supports a binary object format, so using the typical linkage tools a binary file can be transformed into an object file simply with:

$ ld --relocatable --format=binary --output=copyright.o copyright.txt
$ cc -c helloworld.c
$ cc -o helloworld helloworld.o copyright.o

The GNU linker's --relocatable indicates that this object file is to be linked with other object files, and therefore addresses in this object file will need to be relocated at the final linkage.

The final cc in the example doesn't compile anything: it runs ld to link the object files of C programs on this particular architecture and operating system.

The linker defines some symbols in the object file marking the start, end and size of the copied copyright.txt:

$ nm copyright.o
000003bb D _binary_copyright_txt_end
000003bb A _binary_copyright_txt_size
00000000 D _binary_copyright_txt_start

Ignore the address of 00000000, this is relocatable object file and the final linkage will assign a final address and clean up references to it.

A C program can access these symbols with:

extern const unsigned char _binary_copyright_txt_start[];
extern const unsigned char _binary_copyright_txt_end[];
extern const size_t *_binary_copyright_txt_size;

Don't rush ahead and puts() this variable. The copyright.txt file has no final ASCII NUL character which C uses to mark the end of strings. Perhaps use the old-fashioned UNIX write():

#include <stdio.h>
#include <unistd.h>
fflush(stdout);  /* Synchronise C's stdio and UNIX's I/O. */
write(fileno(stdout)),
      _binary_copyright_txt_start,
      (size_t)&_binary_copyright_txt_size);

Alternatively, add a final NUL to the copyright.txt file:

$ echo -e -n "\x00" >> copyright.txt

and program:

#include <stdio.h>
extern const unsigned char _binary_copyright_txt_start[];
fputs(_binary_copyright_txt_start, stdout);

There's one small wrinkle:

$ objdump -s copyright.o
copyright.o:   file format elf32-littlearm
Contents of section .data:
 0000 54686973 2070726f 6772616d 20697320  This program is 
 0010 66726565 20736f66 74776172 653b2079  free software; y
 0020 6f752063 616e2072 65646973 74726962  ou can redistrib
 0030 75746520 69742061 6e642f6f 72206d6f  ute it and/or mo

The .data section is copied into memory for all running instances of the executable. We really want the contents of the copyright.txt file to be in the .rodata section so that there is only ever one copy in memory no matter how many copies are running.

objcopy could have copied an input ‘binary’ copyright.txt file to a particular section in an output object file, and that particular section could have been .rodata. But objcopy's options require us to state the architecture of the output object file. We really don't want a different command for compiling on x86, AMD64, ARM and so on.

So here's a hack: let ld set the architecture details when it generates its default output and then use objcopy to rename the section from .data to .rodata. Remember that .data contains only the three _binary_… symbols and so they are the only symbols which will move from .data to .rodata:

$ ld --relocatable --format=binary --output=copyright.tmp.o copyright.txt
$ objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents copyright.tmp.o copyright.o
$ objdump -s copyright.o
copyright.o:   file format elf32-littlearm
Contents of section .rodata:
 0000 54686973 2070726f 6772616d 20697320  This program is 
 0010 66726565 20736f66 74776172 653b2079  free software; y
 0020 6f752063 616e2072 65646973 74726962  ou can redistrib
 0030 75746520 69742061 6e642f6f 72206d6f  ute it and/or mo

Link this copyright.o with the remainder of the program as before:

$ cc -c helloworld.c
$ cc -o helloworld helloworld.o copyright.o

gdt: Kangaroo road sign (Default)

One neglected moment in Linux history was the arrival of the Pentium II processor with Deschutes core in 1998. Intel had been making capable 32-bit processors since the 80486, but these processors were handily outperfomed by Alpha, MIPS and SPARC. The Pentium II 450MHz turned the tables. These high-end PCs easily outperformed the MIPS- and SPARC-based workstations and drew level with the much more expensive Alpha.

UNIX™ users looking to update their expensive workstations looked at a high-end PC and thought "I wonder if that runs Unix?". Inserting a Red Hat Linux 6.0 CD into the drive slot and installing the OS lead to the discovery of a capable and mature operating system, a better Unix than the UNIX™ they had been using previously. With a few years the majority of UNIX™ systems administrators were familiar with Linux, because they were running it on their own workstations, whatever Unixen they were administering over SSH.

This familiarity in turn lead to an appreciation for Linux's stablity. When it was time to field new small services — such as DNS and DHCP — then it was financially attractive to serve these from a Linux platform rather than a UNIX™ platform. Moreover the Linux distributors did a much better job of packaging the software which people used, whereas the traditional Unix manufacturers took a "not invented here" attitude: shipping very old versions of software such as DNS servers, and making users download and compile simple tools rather than having rhe tools pre-packaged for simple installation.

The Linux distributors did such a good job that it was much easier to run a web site from Linux than from Windows. The relative importance of these 'Internet' applications was missed by a Microsoft keen to dominate the 'enterprise' market. Before 1999 the ambition of Microsoft to crush the Unixen looked likely. After 2000 that ambition was unrealistic hubris.

gdt: Kangaroo road sign (Default)

Once in a while you want to start a daemon with differing parameters from the norm.

For example, the default parameters to Fedora's packaging of ladvd give too much access to unauthenticated remote network units when it allows those units to set the port description on your interfaces[1]. So let's use that as our example.

With systemd unit files in /etc/systemd/system/ shadow those in /usr/lib/systemd/system/. So we could copy the ladvd.service unit file from /usr/lib/... to /etc/..., but we're old, experienced sysadmins and we know that this will lead to long run trouble. /usr/lib/systemd/system/ladvd.service will be updated to support some new systemd feature and we'll miss that update in the copy of the file.

What we want is an "include" command which will pull in the text of the distributor's configuration file. Then we can set about changing it. Systemd has a ".include" command. Unfortunately its parser also checks that some commands occur exactly once, so we can't modify those commands as including the file consumes that one definition.

In response, systemd allows a variable to be cleared; when the variable is set again it is counted as being set once.

Thus our modification of ladvd.service occurs by creating a new file /etc/systemd/system/ladvd.service containing:

.include /usr/lib/systemd/system/ladvd.service
[Service]
# was ExecStart=/usr/sbin/ladvd -f -a -z
# but -z allows string to be passed to kernel by unauthed external user
ExecStart=
ExecStart=/usr/sbin/ladvd -f -a

---
[1] At the very least, a security issue equal to the "rude words in SSID lists" problem. At it's worst, an overflow attack vector.

gdt: Kangaroo road sign (Default)

Background

Zoterto is an excellent reference and citation manager. It runs within Firefox, making it very easy to record sources that you encounter on the web (and in this age of publication databases almost everything is on the web). There are plugins for LibreOffice and for Word which can then format those citations to meet your paper's requirements. Zotero's Firefox application can also output for other systems, such as Wikipedia and LaTeX. You can keep your references in the Zotero cloud, which is a huge help if you use different computers at home and work or school.

The competing product is EndNote. Frankly, EndNote belongs to a previous era of researcher methods. If you use Windows, Word and Internet Explorer and have a spare $100 then you might wish to consider it. For me there's a host of showstoppers, such as not running on Linux and not being able to bookmark a reference from my phone when it is mentioned in a seminar.

Anyway, this article isn't a Zotero versus EndNote smackdown, there's plenty of those on the web. This article is to show a how to configure Zotero's full text indexing for the RaspberryPi and other Debian machines.

Installing Zotero

There are two parts to install: a plugin for Firefox, and extensions for Word or LibreOffice. (OpenOffice works too, but to be frank again, LibreOffice is the mainstream project of that application these days.)

Zotero keeps its database as part of your Firefox profile. Now if you're about to embark on a multi-year research project you may one day have trouble with Firefox and someone will suggest clearing your Firefox profile, and Firefox once again works fine. But then you wonder, "where are my years of carefully-collected references?" And then you cry before carefully trying to re-sync.

So the first task in serious use of Zotero on Linux is to move that database out of Firefox. After installing Zotero on Firefox press the "Z" button, press the Gear icon, select "Preferences" from the dropbox menu. On the resulting panel select "Advanced" and "Files and folders". Press the radio button "Data directory location -- custom" and enter a directory name.

I'd suggest using a directory named "/home/vk5tu/.zotero" or "/home/vk5tu/zotero" (amended for your own userid, of course). The standalone client uses a directory named "/home/vk5tu/.zotero" but there are advantages to not keeping years of precious data in some hidden directory.

After making the change quit from Firefox. Now move the directory in the Firefox profile to whereever you told Zotero to look:

$ cd
$ mv .mozilla/firefox/*.default/zotero .zotero

Full text indexing of PDF files

Zotero can create a full-text index of PDF files. You want that. The directions for configuring the tools are simple.

Too simple. Because downloading a statically-linked binary from the internet which is then run over PDFs from a huge range of sources is not the best of ideas.

The page does have instructions for manual configuration but the page lacks a worked example. Let's do that here.

Manual configuration of PDF full indexing utilities on Debian

Install the pdftotext and pdfinfo programs:

    $ sudo apt-get install poppler-utils

Find the kernel and architecture:

$ uname --kernel-name --machine
Linux armv7l

In the Zotero data directory create a symbolic link to the installed programs. The printed kernel-name and machine is part of the link's name:

$ cd ~/.zotero
$ ln -s $(which pdftotext) pdftotext-$(uname -s)-$(uname -m)
$ ln -s $(which pdfinfo) pdfinfo-$(uname -s)-$(uname -m)

Install a small helper script to alter pdftotext paramaters:

$ cd ~/.zotero
$ wget -O redirect.sh https://raw.githubusercontent.com/zotero/zotero/4.0/resource/redirect.sh
$ chmod a+x redirect.sh

Create some files named *.version containing the version numbers of the utilities. The version number appears in the third field of the first line on stderr:

$ cd ~/.zotero
$ pdftotext -v 2>&1 | head -1 | cut -d ' ' -f3 > pdftotext-$(uname -s)-$(uname -m).version
$ pdfinfo -v 2>&1 | head -1 | cut -d ' ' -f3 > pdfinfo-$(uname -s)-$(uname -m).version

Start Firefox and Zotero's gear icon, "Preferences", "Search" should report something like:

PDF indexing
  pdftotext version 0.26.5 is installed
  pdfinfo version 0.26.5 is installed

Do not press "check for update". The usual maintenance of the operating system will keep those utilities up to date.

gdt: Kangaroo road sign (Default)

The way Fedora does automatic software updates has changed with the replacement of yum(8) with dnf(8).

Start by disabling yum's automatic updates, if installed:

# dnf remove yum-cron yum-cron-daily

Then install the dnf automatic update software:

# dnf install dnf-automatic

Alter /etc/dnf/automatic.conf to change the "apply_updates" line:

apply_updates = yes

Instruct systemd to run the updates periodically:

# systemctl enable dnf-automatic.timer
# systemctl start dnf-automatic.timer
gdt: Kangaroo road sign (Default)

When you boot Fedora with a corruption which is not automatically repaired when systemd runs fsck -a then you are asked on the console if to enter single user mode, or if to continue. If you choose to enter single user mode then you'll find that you can't run fsck /dev/md0 as the root filesystem is mounted.

Dracut has a debugging mode with named breakpoints: it will boot up to the break-point, and then dracut will drop the console into a shell.

This is useful for solving a corrupted root filesystem, we can boot up to just before the disk is mounted, breakpoint into the Dracut shell, and then run fsck on the yet-to-be-mounted root filesystem. To do this temporarily add the Dracut breakpoint parameter

dracut.break=pre-mount

to the Linux kernel.

In Fedora you do can temporarily modify the Linux kernel parameters by pressing e at the Grub bootloader prompt, arrow-ing down to the "linux" command, adding the parameter to the end of that line, and pressing F10 to run the Grub command list you see on the screen.

Dracut will load the logical volumes, assemble any RAID, and then present a shell on the console. Say fsck /dev/md0 (or whereever /etc/fstab says your / filesytem lives) and then reboot. This is a world easier than booting from a CD or USB and working out which partitions are on what logical volumes, and which logical volumes are in which RAID devices.

Breakpoints are a very fine feature of Dracut and, as this blog posting shows, very useful for solving problems which appear during the early stages of booting the machine.

gdt: Kangaroo road sign (Default)

Motivation

In a previous posting I reported a lack of success when enquiring of the USB Implementors' Forum if a Vendor ID had been reserved for documentation.

To recap my motivation, a Vendor ID -- or at least a range of Product IDs -- is desirable to:

  • Avoid defamation, such as using a real VID:PID to illustrate a "workaround", which carries the implication that the product is less-than-perfect. Furthermore, failing to check if a VID:PID has actually been used is "reckless defamation".

  • Avoid consumer law, such as using a real VID:PID to illustrate a a configuration for a video camera, when in fact the product is a mouse.

  • Avoid improper operation, as may occur if a user cuts-and-pastes an illustrative example and that effects a real device.

  • Avoid trademark infringment.

For these reasons other registries of numbers often reserve entries for documentation: DNS names, IPv4 addresses, IPv6 addresses.

Allocation of 256 Product IDs, thanks to OpenMoko

OpenMoko has been generous enough to reserve a range of Product IDs for use by documentation:

0x1d50:0x5200 through to 0x1d50:0x52ff

Note carefully that other Product IDs within Vendor ID 0x1d50 are allocated to actual physical USB devices. Only the Product IDs 0x1d50:0x5200 through to 0x1d50:0x52ff are reserved for use by documentation.

My deep thanks to OpenMoko and Harald Welte.

Application form

The application form submitted to OpenMoko read:

  • a name and short description of your usb device project

    Documentation concerning the configuration of USB buses and devices.

    For example, documentation showing configuration techniques for Linux's udev rules.

    The meaning of "documentation" shall not extend to actual configuration of a actual device. It is constrained to showing methods for configuration. If an VID:PID for an actual device is required then these can be obtained from elsewhere.

    OpenMoko will not assign these "Documentation PIDs" to any actual device, now or forever.

    Operating systems may refuse to accept devices with these "documentation VID:PIDs". Operating systems may refuse to accept configuration which uses these "documentation VID:PIDs".

  • the license under which you are releasing the hardware and/or software/firmware of the device

    The documentation may use any license. Restricting use to only free documentation is problematic: the definition of "free" for documents is controversial; and it would be better if the PID:VIDs were well known and widely used by all authors of technical documentation.

  • a link to the project website and/or source code repository, if any

    Nil, one can be created if this is felt to be necessary (eg, to publicise the allocation).

  • if you need multiple Product IDs, please indicate + explain this at the first message, rather than applying for a second ID later

    Approximately 10.

Page generated 2025-07-06 04:14
Powered by Dreamwidth Studios