Saving video from Flash Player 10.2 or unlink is not a hindrance to us

    I, like probably many other Linux users, used to save videos from sites like YouTube by copying temporary files created by Adobe Flash. Like that:
    $ cp /tmp/FlashIBmQCU video.flv

    Having put a fresh pre-release of a flash player, which was recently discussed on the hub (I have a 64-bit system), I was surprised to find that this method no longer works, since no files are created in the temporary directory. Having reasoned, however, that the player hardly stores the entire video in memory, and somewhere he still needs to write it, I started an investigation.

    ... That is, I decided to see the list of files opened by the plugin. First, we need the PID of the process in which the plugin is hosted. I use Firefox, so we’ll simply search:
    $ ps x | grep firefox
     9800 ?        S      0:00 /bin/sh /usr/lib/firefox-3.6.9/firefox
     9805 ?        S      0:00 /bin/sh /usr/lib/firefox-3.6.9/run-mozilla.sh /usr/lib/firefox-3.6.9/firefox-bin
     9809 ?        Sl    14:58 /usr/lib/firefox-3.6.9/firefox-bin
    10099 ?        Sl     4:10 /usr/lib/firefox-3.6.9/plugin-container /usr/lib/mozilla/plugins/libflashplayer.so 9809 plugin
    26199 pts/13   S+     0:00 grep firefox

    As you can see, Mozilla runs the plugin in a separate process and its PID is 10099. Now you can see the list of open files with the command lsof:
    $ lsof -p 10099
    COMMAND     PID    USER   FD   TYPE             DEVICE     SIZE    NODE NAME
    # поскипано 152 строки
    plugin-co 10099 rooslan  mem    REG               8,21    26048    2656 /usr/lib/gconv/gconv-modules.cache
    plugin-co 10099 rooslan  mem    REG               8,21      343  106080 /usr/lib/locale/ru_RU.utf8/LC_IDENTIFICATION
    plugin-co 10099 rooslan    0r   CHR                1,3             3419 /dev/null
    plugin-co 10099 rooslan    1w  FIFO                0,6             9649 pipe
    plugin-co 10099 rooslan    2w  FIFO                0,6             9649 pipe
    plugin-co 10099 rooslan    3u  unix 0xffff88007304a3c0           287192 socket
    plugin-co 10099 rooslan    4r  0000                0,7        0      32 anon_inode
    plugin-co 10099 rooslan    5w  unix 0xffff8800c5425e40           287277 socket
    plugin-co 10099 rooslan    6r  unix 0xffff8800c5424b00           287278 socket
    plugin-co 10099 rooslan    7w  FIFO                0,6           287279 pipe
    plugin-co 10099 rooslan    8r  FIFO                0,6           287279 pipe
    plugin-co 10099 rooslan    9w  FIFO                0,6           287280 pipe
    plugin-co 10099 rooslan   10u  FIFO                0,6           287280 pipe
    plugin-co 10099 rooslan   11u  FIFO                0,6           287281 pipe
    plugin-co 10099 rooslan   12u  FIFO                0,6           287281 pipe
    plugin-co 10099 rooslan   13u  unix 0xffff88007304a100           287284 socket
    plugin-co 10099 rooslan   14u   REG               8,24   376832 1409239 /home/rooslan/.mozilla/firefox/xxxxxxxx.default/cert8.db
    plugin-co 10099 rooslan   15w   REG               8,24    16384 1409240 /home/rooslan/.mozilla/firefox/xxxxxxxx.default/key3.db
    plugin-co 10099 rooslan   16u   REG               8,23   494641      16 /tmp/FlashXXlm7mcU (deleted)
    plugin-co 10099 rooslan   17u  FIFO                0,6           404625 pipe
    plugin-co 10099 rooslan   18u  FIFO                0,6           404625 pipe
    plugin-co 10099 rooslan   19r  FIFO                0,6           404626 pipe
    plugin-co 10099 rooslan   20w  FIFO                0,6           404626 pipe
    plugin-co 10099 rooslan   21r  unix 0xffff880015a2b9c0           404630 socket

    All the most interesting things turned out to be at the end and right before my eyes, but for the sake of order, let’s try to filter out regular files opened by the process. This can probably be done with built-in tools lsof, but the dimensions man lsofquickly discourage the desire to read it to solve such a passing problem. Therefore, I preferred to use a simple filter on AWK:
    $ lsof -p 10099 | awk '$4 ~ /^[0-9]+/ && $5 == "REG"'
    plugin-co 10099 rooslan   14u   REG               8,24   376832 1409239 /home/rooslan/.mozilla/firefox/xxxxxxxx.default/cert8.db
    plugin-co 10099 rooslan   15w   REG               8,24    16384 1409240 /home/rooslan/.mozilla/firefox/xxxxxxxx.default/key3.db
    plugin-co 10099 rooslan   16u   REG               8,23   494641      16 /tmp/FlashXXlm7mcU (deleted)

    It immediately became clear where our temporary file went : the plugin removed ( unlink ) the link to the file from the directory, but left its descriptor open. Thus, the file ceased to be visible in the file system, but did not disappear, and it will be permanently deleted only when the last handle that refers to it closes.
    But how do we now get the contents of a file opened by only one process? Very simple using the procfs file system . The directory /proc/$PID/fdcontains symbolic links to all descriptors opened by the PID process .
    $ ls -l /proc/10099/fd
    итого 0
    lr-x------ 1 rooslan rooslan 64 2010-09-16 23:56 0 -> /dev/null
    l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 1 -> pipe:[9649]
    lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 10 -> pipe:[287280]
    lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 11 -> pipe:[287281]
    lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 12 -> pipe:[287281]
    lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 13 -> socket:[287284]
    lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 14 -> /home/rooslan/.mozilla/firefox/xxxxxxxx.default/cert8.db
    l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 15 -> /home/rooslan/.mozilla/firefox/xxxxxxxx.default/key3.db
    lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 16 -> /tmp/FlashXXpOdDuF (deleted)
    lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 17 -> pipe:[396658]
    lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 18 -> pipe:[396658]
    lr-x------ 1 rooslan rooslan 64 2010-09-16 23:56 19 -> pipe:[396659]
    l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 2 -> pipe:[9649]
    l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 20 -> pipe:[396659]
    lr-x------ 1 rooslan rooslan 64 2010-09-16 23:56 21 -> socket:[396663]
    lrwx------ 1 rooslan rooslan 64 2010-09-16 23:56 3 -> socket:[287192]
    lr-x------ 1 rooslan rooslan 64 2010-09-16 23:56 4 -> anon_inode:[eventpoll]
    l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 5 -> socket:[287277]
    lr-x------ 1 rooslan rooslan 64 2010-09-16 23:56 6 -> socket:[287278]
    l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 7 -> pipe:[287279]
    lr-x------ 1 rooslan rooslan 64 2010-09-16 23:56 8 -> pipe:[287279]
    l-wx------ 1 rooslan rooslan 64 2010-09-16 23:56 9 -> pipe:[287280]

    (Here, by the way, is another way to view files opened by the process, in addition to lsof).
    And, although readlink returns the names of nonexistent files for some of these links, you can safely read from them (if permissions allow), which we will use:
    $ cp /proc/10099/fd/16 video.flv

    That's all. These are quite trivial things (many, I think, have guessed what will be discussed from the heading alone), but, I hope, for someone this simple trick will be useful.

    UPD
    kreon designed these actions as a script (I allowed myself to modify it a bit by adding an argument):
    #!/bin/sh
    PID=`ps x | grep libflashplayer.so | grep -v grep | awk '{print $1}'`
    FD=`lsof -p $PID | grep Flash | awk '{print $4}' | sed 's/u^//'`
    cp /proc/$PID/fd/$FD "$1"

    Using:
    $ saveflash.sh coolvideo.flv

    UPD 2
    In the comments, they repeatedly pointed to the irrationality of this method and in return offered a variety of browser programs and plugins for downloading videos. Of course, for downloading from YouTube it will be more convenient to use them (although you still need to see if they have the ability to get video from the browser cache because of the above). However, all these plugins are sharpened on a specific, albeit a fairly large, list of video hosting sites. This method also allows you to get video almost always if the video is downloaded via HTTP, and RTMP streaming is not used.

    Also popular now: