<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
	<title>Tanguy Ortolo - To remember</title>
	<link>https://tanguy.ortolo.eu/blog/categorie20/remember</link>
	<language>en</language>
	<description>a blog about Debian and self-hosting</description>
<atom:link xmlns:atom="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="https://tanguy.ortolo.eu/blog/feed.php" />
	<lastBuildDate>Thu, 24 Sep 2020 19:09:00 +0000</lastBuildDate>
	<generator>PluXml</generator>
	<item>
		<title>Vignette d&#039;assurance cycliste</title> 
		<link>https://tanguy.ortolo.eu/blog/article167/vignette-assurance-cycliste</link>
		<guid>https://tanguy.ortolo.eu/blog/article167/vignette-assurance-cycliste</guid>
		<description>&lt;p&gt;Lorsqu&#039;on circule à moto ou en automobile, on doit avoir un certificat d&#039;assurance,
sous la forme d&#039;une vignette verte bien visible sur le véhicule.&lt;/p&gt;

&lt;p&gt;À vélo, rien de tel, l&#039;assurance n&#039;étant pas obligatoire. Pour autant, presque tous
les cyclistes sont assurés en responsabilité civile sans le savoir ! Pour faciliter
l&#039;identification de l&#039;assureur en cas de collision, j&#039;ai donc rédigé un
&lt;a href=&quot;https://tanguy.ortolo.eu/pub/2020/01/30/vignette-velo.xhtml&quot;&gt;générateur
de vignette d&#039;assurance pour les cyclistes&lt;/a&gt;, à imprimer et à installer à un endroit
visible sur le vélo.&lt;/p&gt;

&lt;div class=&quot;figure&quot; style=&quot;text-align: center; margin: 2em&quot;&gt;
    &lt;object type=&quot;image/svg+xml&quot; data=&quot;https://tanguy.ortolo.eu/blog/data/images/illustrations/vignette-assurance-cycliste.svg&quot;
        title=&quot;Vignette d&#039;assurance RC&quot;&gt;
        Informations d&#039;assurance responsabilité civile
    &lt;/object&gt;
&lt;/div&gt;&lt;h2&gt;L&#039;assurance responsabilité civile&lt;/h2&gt;

&lt;p&gt;En fait, la souscription d&#039;une police d&#039;assurance spécifique pour une moto ou une
automobile n&#039;est nécessaire que parce que la conduite de véhicules à moteur est
explicitement exclue des garanties des contrats d&#039;assurance habitation et responsabilité
civile.&lt;/p&gt;

&lt;p&gt;Comme il n&#039;y a aucune exclusion similaire pour la conduite de cycles, il suffit de
disposer d&#039;une assurance de responsabilité civile générale, pour être couvert lorsqu&#039;on
se déplace à pied, à vélo, sur des patins à roulette, bref n&#039;importe comment tant que ce
n&#039;est pas motorisé.&lt;/p&gt;

&lt;p&gt;Ce genre d&#039;assurance, qui concerne presque tout le monde, puisqu&#039;elle est include
dans les contrats d&#039;assurance habitation, prend en charge les conséquences des dommages
que l&#039;on peut causer à autrui, et inclut souvent une assistance pour le recours à l&#039;assureur
du tiers responsable d&#039;une collision dont on serait victime.&lt;/p&gt;

&lt;h2&gt;L&#039;intérêt d&#039;une vignette&lt;/h2&gt;

&lt;p&gt;La vignette d&#039;assurance cycliste, non obligatoire et non reglementée, est à mon avis
utile, parce qu&#039;elle permet d&#039;identifier rapidement l&#039;assureur et le contrat d&#039;un cycliste,
même s&#039;il est hors d&#039;état de communiquer, ou qu&#039;il ne connaît pas par cœur ces références.
&lt;/p&gt;

&lt;p&gt;Elle permet également d&#039;informer sur le fait qu&#039;on est assuré, et de rassurer ceux
qui s&#039;inquiètent du fait que les cyclistes devraient l&#039;être : la plupart du temps, ils
le sont déjà !&lt;/p&gt;</description>
		<pubDate>Thu, 24 Sep 2020 19:09:00 +0000</pubDate>
		<dc:creator>Tanguy</dc:creator>
	</item>
	<item>
		<title>Safely untying a shoelace knot</title> 
		<link>https://tanguy.ortolo.eu/blog/article164/untie-shoelace</link>
		<guid>https://tanguy.ortolo.eu/blog/article164/untie-shoelace</guid>
		<description>&lt;p&gt;Untying a shoelace knot is easy, but sometimes, one end got through a loop,
and you end up blocking the knot. I invented a way to safely untie such a knot,
regardless of whether or not it has been messed up, all with a single hand!&lt;/p&gt;&lt;div class=&quot;figure&quot; style=&quot;text-align: center&quot;&gt;
    &lt;video src=&quot;https://tanguy.ortolo.eu/blog/data/images/videos/untying-shoelace.webm&quot; controls=&quot;controls&quot;
        poster=&quot;data/images/photo/untying-shoelace.jpg&quot;&gt;
        &lt;track label=&quot;English&quot; kind=&quot;subtitles&quot; srclang=&quot;en&quot;
            src=&quot;https://tanguy.ortolo.eu/blog/data/images/videos/untying-shoelace.en.vtt&quot; default=&quot;default&quot;/&gt;
        &lt;track label=&quot;French&quot; kind=&quot;subtitles&quot; srclang=&quot;fr&quot;
            src=&quot;https://tanguy.ortolo.eu/blog/data/images/videos/untying-shoelace.fr.vtt&quot; default=&quot;default&quot;/&gt;
    &lt;/video&gt;
&lt;/div&gt;

&lt;p&gt;Here it is:&lt;/p&gt;

&lt;ol&gt;
    &lt;li&gt;Catch a loop using your middle finger as a hook.&lt;/li&gt;
    &lt;li&gt;Grab the end of the same side with your thumb and index finger.&lt;/li&gt;
    &lt;li&gt;Pull the loop and end together.&lt;/li&gt;
    &lt;li&gt;The knot will untie itself cleanly, after which you will be left with
        the starting knot which is always easy to remove.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note that, while useful with regular knots, this method will not work if you are using safety knots. You cannot have your cake and eat it, sorry.&lt;/p&gt;</description>
		<pubDate>Sat, 09 Feb 2019 16:23:00 +0000</pubDate>
		<dc:creator>Tanguy</dc:creator>
	</item>
	<item>
		<title>Homemade U-lock holder</title> 
		<link>https://tanguy.ortolo.eu/blog/article163/u-lock-holder</link>
		<guid>https://tanguy.ortolo.eu/blog/article163/u-lock-holder</guid>
		<description>&lt;p&gt;A U-lock is, arguably, one of the best ways to secure a bicycle
against theft. When you buy one, it comes with a holder to carry it on
the bike frame. Now, while the lock, basically made of hardened steel,
is very tough and will probably last more than ten years, the holder is
made of plastic, and will fail after a couple of years. Then, like most
cyclist, you will have to carry your lock on the rack, which is far less
practical.&lt;/p&gt;

&lt;p&gt;There are several ways to make a U-lock holder; here is mine, which I
have never found documented, so I may have actually invented it. It
requires very simple material, it is very easy to implement, and it is
quite durable and practical to use.&lt;/p&gt;&lt;h2&gt;Material&lt;/h2&gt;

&lt;ul&gt;
    &lt;li&gt;a short length of plastic pipe, chosen so a lock arm can slide into
        it, and cut so it is about one centimetre longer than the rack
        width;&lt;/li&gt;
    &lt;li&gt;some duct tape, ideally with the same colour as the rack.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Oh, and you need to have a rack on your bicycle. Some racks may not
be optimally compatible with that, sorry if that happens to be your
case. You will also not be able to carry your lock that way together with
bicycle bags.&lt;/p&gt;

&lt;h2&gt;Instructions&lt;/h2&gt;

&lt;p&gt;This is so simple that this photograph may be enough to explain it.
You will find text instructions just below.&lt;/p&gt;

&lt;div class=&quot;figure&quot; style=&quot;text-align: center&quot;&gt;
    &lt;a href=&quot;https://tanguy.ortolo.eu/blog/data/images/photos/u-lock-holder.jpg&quot;&gt;&lt;img src=&quot;https://tanguy.ortolo.eu/blog/data/images/photos/u-lock-holder.tb.jpg&quot; alt=&quot;Homemade U-lock holder on a bicycle rack&quot;/&gt;&lt;/a&gt;
&lt;/div&gt;

&lt;ol&gt;
    &lt;li&gt;Put the pipe on the two arms that attach the rack to the seat
        stays, so it is perpendicular to bike frame. Try to find a place
        where it can be held stable;&lt;/li&gt;
    &lt;li&gt;Attach it with some tape.&lt;/li&gt;
    &lt;li&gt;Open the U-lock.&lt;/li&gt;
    &lt;li&gt;If your rack has a spring-loaded clamp, open it and hold it that
        way.&lt;/li&gt;
    &lt;li&gt;Slide one of its arms into the pipe, the other one relying on
        the rack.&lt;/li&gt;
    &lt;li&gt;Release the rack clamp, if you have it, otherwise use a bungee
        cord to secure the lock against vibrations.&lt;/li&gt;
&lt;/ol&gt;</description>
		<pubDate>Tue, 04 Dec 2018 13:12:00 +0000</pubDate>
		<dc:creator>Tanguy</dc:creator>
	</item>
	<item>
		<title>Bad support of ZIP archives with extra fields</title> 
		<link>https://tanguy.ortolo.eu/blog/article156/zip-extra-field</link>
		<guid>https://tanguy.ortolo.eu/blog/article156/zip-extra-field</guid>
		<description>&lt;p&gt;For sharing multiple files, it is often convenient to pack them
into an archive, and the most widely supported format to do so is
probably ZIP. Under *nix, you can archive a directory with Info-ZIP:&lt;/p&gt;

&lt;pre class=&quot;cli&quot;&gt;
% zip -r something.zip something/
&lt;/pre&gt;

&lt;p&gt;(When you have several files, it is recommended to archive them in a
directory, to avoid cluttering the directory where people will extract
them.)&lt;/p&gt;&lt;h2&gt;Unsupported ZIP archive&lt;/h2&gt;

&lt;p&gt;Unfortunately, while we would expect ZIP files to be widely
supported, I found out that this is not always the case, and I had
many recipients failing to open them under operating systems such as
iOS.&lt;/p&gt;

&lt;h2&gt;Avoid extra fields&lt;/h2&gt;

&lt;p&gt;That issue seems to be linked to the usage of extra file attributes,
that are enabled by default, in order to store Unix file metadata. The
field designed to store such extra attributes was designed from the
beginning so each implementation can take into account attributes it
supports and ignore any other ones, but some buggy ZIP implementation
appear not to function at all with them.&lt;/p&gt;

&lt;p&gt;Therefore, unless you actually need to preserve Unix file metadata,
you should avoid using extra fields. With Info-ZIP, you would have to
add the option &lt;code&gt;-X&lt;/code&gt;:&lt;/p&gt;

&lt;pre class=&quot;cli&quot;&gt;
% zip -rX something.zip something/
&lt;/pre&gt;</description>
		<pubDate>Tue, 21 Mar 2017 19:33:00 +0000</pubDate>
		<dc:creator>Tanguy</dc:creator>
	</item>
	<item>
		<title>Generate man pages for awscli</title> 
		<link>https://tanguy.ortolo.eu/blog/article153/awscli-manpages</link>
		<guid>https://tanguy.ortolo.eu/blog/article153/awscli-manpages</guid>
		<description>&lt;h2&gt;No man pages, but almost&lt;/h2&gt;

&lt;p&gt;The AWS Command Line Interface, which is available in Debian,
provides no man page. Instead, that tool has an integrated help system,
which allows you to run commands such as &lt;code class=&quot;command&quot;&gt;aws rds
    help&lt;/code&gt;, that, for what I have seen, generates some
reStructuredText, then converts it to a man page in troff format, then
calls troff to convert it to text with basic formatting, and eventually
passes it to a pager. Since this is close to what &lt;em&gt;man&lt;/em&gt; does, the
result looks like a degraded man page, with some features missing such
as the adaptation to the terminal width.&lt;/p&gt;

&lt;p&gt;Well, this is better than nothing, and better than what many
under-documented tools can offer, but for several reasons, it still
sucks: most importantly, it does not respect administrators&#039; habits and
it does not integrate with the system man database. You it does not
allow you to use commands such as &lt;code class=&quot;command&quot;&gt;apropos&lt;/code&gt;,
and you will get no man page name auto-completion from your shell since
there is no man page.&lt;/p&gt;&lt;h2&gt;Generate the man pages&lt;/h2&gt;

&lt;p&gt;Now, since the integrated help system does generate a man page
internally, we can hack it to output it, and save it to a file:&lt;/p&gt;

&lt;pre class=&quot;code diff patch&quot;&gt;
Description: Enable a mode to generate troff man pages
 The awscli help system internally uses man pages, but only to convert
 them to text and show them with the pager. This patch enables a mode
 that prints the troff code so the user can save the man page.
 .
 To use that mode, run the help commands with an environment variable
 OUTPUT set to &#039;troff&#039;, for instance:
     OUTPUT=&#039;troff&#039; aws rds help
Forwarded: no
Author: Tanguy Ortolo &amp;lt;tanguy+debian@ortolo.eu&amp;gt;
Last-Update: 2016-11-22

Index: /usr/lib/python3/dist-packages/awscli/help.py
===================================================================
--- /usr/lib/python3/dist-packages/awscli/help.py       2016-11-21 12:14:22.236254730 +0100
+++ /usr/lib/python3/dist-packages/awscli/help.py       2016-11-21 12:14:22.236254730 +0100
@@ -49,6 +49,8 @@
     Return the appropriate HelpRenderer implementation for the
     current platform.
     &quot;&quot;&quot;
+    if &#039;OUTPUT&#039; in os.environ and os.environ[&#039;OUTPUT&#039;] == &#039;troff&#039;:
+        return TroffHelpRenderer()
     if platform.system() == &#039;Windows&#039;:
         return WindowsHelpRenderer()
     else:
@@ -97,6 +99,15 @@
         return contents


+class TroffHelpRenderer(object):
+    &quot;&quot;&quot;
+    Render help content as troff code.
+    &quot;&quot;&quot;
+
+    def render(self, contents):
+        sys.stdout.buffer.write(publish_string(contents, writer=manpage.Writer()))
+
+
 class PosixHelpRenderer(PagingHelpRenderer):
     &quot;&quot;&quot;
     Render help content on a Posix-like system.  This includes
&lt;/pre&gt;

&lt;p&gt;This patch must be applied from the root directory with &lt;code
     class=&quot;command&quot;&gt;patch -p0&lt;/code&gt;, otherwise GNU patch will not
accept to work on files with absolute names.&lt;/p&gt;

&lt;p&gt;With that patch, you can run help commands with an environment
variable &lt;code class=&quot;environment variable&quot;&gt;OUTPUT=&#039;troff&#039;&lt;/code&gt; to get
the man page to use it as you like, for instance:&lt;/p&gt;

&lt;pre class=&quot;cli&quot;&gt;
% OUTPUT=&#039;troff&#039; aws rds help &amp;gt; aws_rds.1
% man -lt aws_rds.1 | lp
&lt;/pre&gt;

&lt;h2&gt;Generate all the man pages&lt;/h2&gt;

&lt;p&gt;Now that we are able to generate the man page of any aws command,
all we need to generate all of them is a list of all the available
commands. This is not that easy, because the commands are somehow
derived from functions provided by a Python library named botocore,
which are derived from a bunch of configuration files, and some of them
are added, removed or renamed. Anyway, I have been able to write a
Python script that does that, but it includes a static list of these
modifications:&lt;/p&gt;

&lt;pre class=&quot;python code&quot;&gt;
#! /usr/bin/python3

import subprocess
import awscli.clidriver


def write_manpage(command):
    manpage = open(&#039;%s.1&#039; % &#039;_&#039;.join(command), &#039;w&#039;)
    command.append(&#039;help&#039;)
    process = subprocess.Popen(command,
            env={&#039;OUTPUT&#039;: &#039;troff&#039;},
            stdout=manpage)
    process.wait()
    manpage.close()


driver = awscli.clidriver.CLIDriver()
command_table = driver._get_command_table()

renamed_commands = \
    {
        &#039;config&#039;: &#039;configservice&#039;,
        &#039;codedeploy&#039;: &#039;deploy&#039;,
        &#039;s3&#039;: &#039;s3api&#039;
    }
added_commands = \
    {
        &#039;s3&#039;: [&#039;cp&#039;, &#039;ls&#039;, &#039;mb&#039;, &#039;mv&#039;, &#039;presign&#039;, &#039;rb&#039;, &#039;rm&#039;, &#039;sync&#039;,
               &#039;website&#039;]
    }
removed_subcommands = \
    {
        &#039;ses&#039;: [&#039;delete-verified-email-address&#039;,
                &#039;list-verified-email-addresses&#039;,
                &#039;verify-email-address&#039;],
        &#039;ec2&#039;: [&#039;import-instance&#039;, &#039;import-volume&#039;],
        &#039;emr&#039;: [&#039;run-job-flow&#039;, &#039;describe-job-flows&#039;,
                &#039;add-job-flow-steps&#039;, &#039;terminate-job-flows&#039;,
                &#039;list-bootstrap-actions&#039;, &#039;list-instance-groups&#039;,
                &#039;set-termination-protection&#039;,
                &#039;set-visible-to-all-users&#039;],
        &#039;rds&#039;: [&#039;modify-option-group&#039;]
    }
added_subcommands = \
    {
        &#039;rds&#039;: [&#039;add-option-to-option-group&#039;,
                &#039;remove-option-from-option-group&#039;]
    }

# Build a dictionary of real commands, including renames, additions and
# removals.
real_commands = {}
for command in command_table:
    subcommands = []
    subcommand_table = command_table[command]._get_command_table()
    for subcommand in subcommand_table:
        # Skip removed subcommands
        if command in removed_subcommands \
                and subcommand in removed_subcommands[command]:
            continue
        subcommands.append(subcommand)
    # Add added subcommands
    if command in added_subcommands:
        for subcommand in added_subcommands[command]:
            subcommands.append(subcommand)
    # Directly add non-renamed commands
    if command not in renamed_commands:
        real_commands[command] = subcommands
    # Add renamed commands
    else:
        real_commands[renamed_commands[command]] = subcommands
# Add added commands
for command in added_commands:
    real_commands[command] = added_commands[command]

# For each real command and subcommand, generate a manpage
write_manpage([&#039;aws&#039;])
for command in real_commands:
    write_manpage([&#039;aws&#039;, command])
    for subcommand in real_commands[command]:
        write_manpage([&#039;aws&#039;, command, subcommand])
                         &#039;sync&#039;, &#039;website&#039;]}
&lt;/pre&gt;

&lt;p&gt;This script will generate more than 2,000 man page files in the
current directory; you will then be able to move them to &lt;em
     class=&quot;filename&quot;&gt;/usr/local/share/man/man1&lt;/em&gt;.&lt;/p&gt;


&lt;p&gt;Since this is a lot of man pages, it may be appropriate to
concatenate them by major command, for instance all the &lt;code
     class=&quot;command&quot;&gt;aws rds&lt;/code&gt; together…&lt;/p&gt;</description>
		<pubDate>Wed, 23 Nov 2016 17:25:00 +0000</pubDate>
		<dc:creator>Tanguy</dc:creator>
	</item>
	<item>
		<title>Process command line arguments in shell</title> 
		<link>https://tanguy.ortolo.eu/blog/article150/shell-process-arguments</link>
		<guid>https://tanguy.ortolo.eu/blog/article150/shell-process-arguments</guid>
		<description>&lt;p&gt;When writing a wrapper script, one often has to process the command
line arguments to transform them according to his needs, to change some
arguments, to remove or insert some, or perhaps to reorder them.&lt;/p&gt;&lt;h2&gt;Naive approach&lt;/h2&gt;

&lt;p&gt;The naive approach to do that is&lt;a href=&quot;https://tanguy.ortolo.eu/blog/rss/categorie20#note1&quot; id=&quot;call1&quot;&gt;¹&lt;/a&gt;:&lt;/p&gt;

&lt;pre class=&quot;code script shell&quot;&gt;
# Process arguments, building a new argument list
new_args=&quot;&quot;
for arg in &quot;$@&quot;
do
    case &quot;$arg&quot;
    in
        --foobar)
            # Convert --foobar to the new syntax --foo=bar
            new_args=&quot;$args --foo=bar&quot;
        ;;
        *)
            # Take other options as they are
            new_args=&quot;$args $arg&quot;
        ;;
    esac
done

# Call the actual program
exec program $new_args
&lt;/pre&gt;

&lt;p&gt;This naive approach is simple, but fragile, as it will break on
arguments that contain a space. For instance, calling &lt;code
    class=&quot;shell&quot;&gt;wrapper --foobar &quot;some file&quot;&lt;/code&gt; (where &lt;code&gt;some
    file&lt;/code&gt; is a single argument) will result in the call &lt;code
    class=&quot;shell&quot;&gt;program --foo=bar some file&lt;/code&gt; (where
&lt;code&gt;some&lt;/code&gt; and &lt;code&gt;file&lt;/code&gt; are two distinct arguments).&lt;/p&gt;

&lt;h2&gt;Correct approach&lt;/h2&gt;

&lt;p&gt;To handle spaces in arguments, we need either:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;to quote them in the new argument list, but that requires
        escaping possible quotes they contain, which would be
        error-prone, and implies using external programs such as
        sed;&lt;/li&gt;
    &lt;li&gt;to use an actual list or array, which is a feature of advanced
        shells such as Bash or Zsh, not standard shell…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;… except standard shell does support arrays, or rather, it does
support &lt;em&gt;one specific array&lt;/em&gt;: the positional parameter list
&lt;code class=&quot;shell&quot;&gt;&quot;$@&quot;&lt;/code&gt;&lt;a href=&quot;https://tanguy.ortolo.eu/blog/rss/categorie20#note2&quot; id=&quot;call2&quot;&gt;²&lt;/a&gt;. This
leads to one solution to process arguments in a reliable way, which
consists in rebuilding the positional parameter list with the built-in
command &lt;code class=&quot;shell&quot;&gt;set --&lt;/code&gt;:&lt;/p&gt;

&lt;pre class=&quot;code script shell&quot;&gt;
# Process arguments, building a new argument list in &quot;$@&quot;
# &quot;$@&quot; will need to be cleared, not right now but on first iteration only
first_iter=1
for arg in &quot;$@&quot;
do
    if [ &quot;$first_iter&quot; -eq 1 ]
    then
        # Clear the argument list
        set --
        first_iter=0
    fi
    case &quot;$arg&quot;
    in
        --foobar) set -- &quot;$@&quot; --foo=bar ;;
        *) set -- &quot;$@&quot; &quot;$arg&quot; ;;
    esac
done

# Call the actual program
exec program &quot;$@&quot;
&lt;/pre&gt;

&lt;h2&gt;Notes&lt;/h2&gt;

&lt;ol&gt;
    &lt;li id=&quot;note1&quot;&gt;I you prefer, &lt;code class=&quot;shell&quot;&gt;for arg in &quot;$@&quot;&lt;/code&gt; can be
        simplified to just &lt;code class=&quot;shell&quot;&gt;for arg&lt;/code&gt;.&lt;a
            href=&quot;https://tanguy.ortolo.eu/blog/rss/categorie20#call1&quot;&gt;↑&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;note2&quot;&gt;As a reminder, and contrary to what it looks like, quoted
        &lt;code class=&quot;shell&quot;&gt;&quot;$@&quot;&lt;/code&gt; does not expand to a single
        field, but to &lt;em&gt;one field per positional parameter&lt;/em&gt;. &lt;a
            href=&quot;https://tanguy.ortolo.eu/blog/rss/categorie20#call2&quot;&gt;↑&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
		<pubDate>Wed, 08 Jun 2016 13:29:00 +0000</pubDate>
		<dc:creator>Tanguy</dc:creator>
	</item>
	<item>
		<title>Removing sam2p from Debian</title> 
		<link>https://tanguy.ortolo.eu/blog/article143/removing-sam2p-from-debian</link>
		<guid>https://tanguy.ortolo.eu/blog/article143/removing-sam2p-from-debian</guid>
		<description>&lt;h2&gt;Issues with sam2p and removal&lt;/h2&gt;

&lt;p&gt;I have been maintaining the Debian package of sam2p for some time.
Unfortunately, the upstream development of that program is no longer
active, and it is using an old custom build chain that no longer works
with recent version of GCC.&lt;/p&gt;

&lt;p&gt;This package is currently failing to build from source, and while I
have been able to patch some issues in the past, and it may still be
possible to fix it again, this is not really sustainable.&lt;/p&gt;

&lt;p&gt;I am therefore considering to remove sam2p from Debian, unless
someone has a very good reason to keep it and is able and willing to
maintain it.&lt;/p&gt;&lt;h2&gt;Alternative&lt;/h2&gt;

&lt;p&gt;sam2p is a raster image conversion tool that can convert PNG and JPEG
to EPS and PDF while keeping their compression, which is mostly useful
to use them in documents compiled with LaTeX. Fortunately, the same can
be done with ImageMagick. If you want to convert to EPS, you have to
specify that you want EPS 2 or 3, otherwise it would produce EPS level 1
which does not provide native raster compression:&lt;/p&gt;

&lt;pre class=&quot;cli&quot;&gt;
% convert debian-openlogo-raster100.png \
          eps3:debian-openlogo-raster100.eps
% convert debian-openlogo-raster100.png \
          debian-openlogo-raster100.pdf
% ls -lh
1.7K debian-openlogo-raster100.png
6.0K debian-openlogo-raster100.eps
8.8K debian-openlogo-raster100.pdf

% convert photograph.jpg eps3:photograph.eps
% convert photograph.jpg photograph.pdf
% ls -lh
657K photograph.jpg
662K photograph.eps
664K photograph.pdf

% convert scanned-document.png eps3:scanned-document.eps
% convert scanned-document.png scanned-document.pdf
140K scanned-document.png
145K scanned-document.eps
150K scanned-document.pdf
&lt;/pre&gt;

&lt;p&gt;This is a bit less efficient than sam2p, as convert seems to add some
fixed overhead, but it does keep the appropriate compression algorithm.
See this &lt;a href=&quot;http://www.imagemagick.org/Usage/formats/#pdf_options&quot;
            title=&quot;ImageMagick PDF output options&quot;&gt;documentation
            page from ImageMagick&lt;/a&gt; for more information.&lt;/p&gt;

&lt;h2&gt;Using appropriate formats&lt;/h2&gt;

&lt;p&gt;As a reminder, when writing LaTeX documents, depending on your build
chain, you can use:&lt;/p&gt;

&lt;dl&gt;
    &lt;dt&gt;photographs&lt;/dt&gt;
    &lt;dd&gt;JPEG or EPS (converted from JPEG with ImageMagick);&lt;/dd&gt;
    &lt;dt&gt;raster drawings, screenshots…&lt;/dt&gt;
    &lt;dd&gt;PNG or EPS (converted from PNG with ImageMagick);&lt;/dd&gt;
    &lt;dt&gt;vector graphics&lt;/dt&gt;
    &lt;dd&gt;PDF or EPS (convertes from SVG with Inkscape).&lt;/dd&gt;
&lt;/dl&gt;</description>
		<pubDate>Fri, 22 Jan 2016 00:52:00 +0000</pubDate>
		<dc:creator>Tanguy</dc:creator>
	</item>
	<item>
		<title>Using bsdtar to change an archive format</title> 
		<link>https://tanguy.ortolo.eu/blog/article134/bsdtar-change-archive-format</link>
		<guid>https://tanguy.ortolo.eu/blog/article134/bsdtar-change-archive-format</guid>
		<description>&lt;h2&gt;Streamable archive formats&lt;/h2&gt;

&lt;a href=&quot;http://tango.freedesktop.org/&quot; title=&quot;From the Tango Desktop project, Public Domain&quot;&gt;&lt;img src=&quot;https://tanguy.ortolo.eu/blog/data/images/icons/tango-archive-128.png&quot; alt=&quot;Package icon&quot; style=&quot;float: right;&quot;/&gt;&lt;/a&gt;

&lt;p&gt;Archive formats such as &lt;em class=&quot;format manpage&quot;&gt;tar(5)&lt;/em&gt; and &lt;em
    class=&quot;format manpage&quot;&gt;cpio(5)&lt;/em&gt; have the advantage of being streamable,
so you can use them for transferring data with pipes and remote shells,
without having to store the archive in the middle of the process, for instance:&lt;/p&gt;

&lt;pre class=&quot;cli&quot;&gt;
$ cd public_html/blog
$ rgrep -lF &quot;archive&quot; data/articles \
      | pax -w \
      | ssh newserver &quot;mkdir public_html/blog ;
                       cd public_html/blog ;
                       pax -r&quot;
&lt;/pre&gt;&lt;h2&gt;Turning a  ZIP archive into tarball&lt;/h2&gt;

&lt;p&gt;Unfortunately, many people will send you data in non-streamable archive
formats such as ZIP&lt;a href=&quot;https://tanguy.ortolo.eu/blog/rss/categorie20#note1&quot; id=&quot;notecall1&quot;&gt;¹&lt;/a&gt;. For such cases, &lt;em
    class=&quot;command manpage&quot;&gt;bsdtar(1)&lt;/em&gt; can be useful, as it is able to
convert an archive from one format to another:&lt;/p&gt;

&lt;pre class=&quot;cli&quot;&gt;
$ bsdtar -cf - @archive.zip \
      | COMMAND
&lt;/pre&gt;

&lt;p&gt;These arguments tell &lt;em class=&quot;command&quot;&gt;bsdtar&lt;/em&gt; to:&lt;/p&gt;

&lt;ul&gt;
    &lt;li&gt;create an archive;&lt;/li&gt;
    &lt;li&gt;write it to stdout (contrary to GNU tar which defaults to stdout,
    bsdtar defaults to a tape device);&lt;/li&gt;
    &lt;li&gt;put into it the files it will find in the archive &lt;em
        class=&quot;filename&quot;&gt;archive.zip&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a tape archive, which is easier to manipulate in a stream than
a ZIP archive.&lt;/p&gt;

&lt;h2&gt;Notes&lt;/h2&gt;

&lt;ol&gt;
    &lt;li id=&quot;note1&quot;&gt;Some will say that although ZIP is based on an file index, it
    can be stream because that index is placed at the end of the archive. In
    fact, that characteristic only allows to stream the archive creation, but
    requires to store the full archive before being able to extract it. &lt;a
        href=&quot;https://tanguy.ortolo.eu/blog/rss/categorie20#notecall1&quot;&gt;↑&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;</description>
		<pubDate>Tue, 09 Dec 2014 16:00:00 +0000</pubDate>
		<dc:creator>Tanguy</dc:creator>
	</item>
</channel>
</rss>