Dosyayı dizine dönüştürme


14

Bildiğimiz gibi "Linux'taki her şey" bir dosyadır ve dahası dizin sadece diğer dosyaları içeren bir dosyadır.

Yani, bu "çılgın fikir" in mümkün olup olmadığını bilmiyorum, ama yukarıdaki prensibe göre bir şekilde olmalı.

Basit bir ifadeyle, mevcut bir boş dosyayı dizine nasıl değiştirebilirim? Mümkün mü?

Bazı beyin fırtınası olarak, dosya meta verilerinde bir değişiklik yapmayı düşündüm ve dizin meta verileri bunu yapmalıdır!

Herhangi bir bilgi takdir.


GÜNCELLEME: Kesinlikle bir dosyayı silmek ve onun yerine dir oluşturmak istemiyorum! Ben sadece bazı dosya meta verileri ile oynayabilir eğer yukarıdaki felsefenin uygulanabilir olduğunu bilmek çalışıyorum.


1
Bunu yapmak için bir neden olabilir?
Pilot6

1
Tek doğru yol dosyayı silmek ve bir dizin oluşturmaktır. Aksi takdirde dosya sistemi bozulabilir. Düşük seviyede yapabilirsiniz, ancak dosya sistemine bağlıdır. Ext4 inode'da düzenlenmelidir diye düşünüyorum.
Pilot6

2
"Dosya" kavramı bununla ilgili değil. Aygıtlar da dosya olarak kabul edilir, ancak bu bir dosyayı aygıta dönüştürebileceğiniz anlamına gelmez. :))
Pilot6

5
debugfs, dosya bayrağını dir olarak ayarlamanıza izin verecek bir inode'u doğrudan düzenlemenize izin veren bir change_inode komutuna sahiptir. Ayrıca bir mkdir <inode> komutu vardır. Hiçbir şey yapmadım ve denemek üzereyim.
tallus

4
"Linux'taki her şey" bir dosyadır. Bildiğimiz gibi "Linux'taki her şey bir dosyadır DESCRIPTOR". Fark yaratan bir dünya yaratır.
Rinzwind

Yanıtlar:


21

Dönüşüme ulaşmak

Test dosya sistemi oluşturma

Bu deneyi çalıştırdıktan sonra ana dosya sistemimizi olası hasarlardan korumak için, test amacıyla normal bir dosyanın içinde küçük bir dosya sistemi oluşturacağız.

  1. test10 megabayt boyutunda sıfır dolu bir dosya oluşturun :

    dd if=/dev/zero of=~/test bs=10M count=1
    
  2. Dosyanın içinde, bir bölümmiş gibi bir Ext4 dosya sistemi oluşturun:

    mkfs.ext4 ~/test
    

Bazı dosyalar ve dizinler oluşturma

Şimdi tamamen işlevsel bir dosya sistemimiz var. test dosyanın , bu yüzden içinde bazı dosyalar ve dizinler oluşturacağız.

  1. Yeni oluşturulan dosya sistemini içine monte edin /mnt :

    sudo mount ~/test /mnt
    
  2. Bir dosya ve dizin oluşturun:

    sudo mkdir /mnt/folder
    echo "contents" | sudo tee /mnt/file
    
  3. Dosya sisteminin içeriğini kontrol edin:

    ls -l /mnt
    

    Çıktı şu şekilde olmalıdır:

    total 2
    -rw-r--r-- 1 root root     0 may 21 18:53 file
    drw-r--r-- 2 root root  1024 may 21 18:55 folder
    
  4. Test dosya sistemini çıkarın:

    sudo umount /mnt
    

Dosya ve klasörü değiştirme

  1. Yazma izniyle dosyaya debugfskarşı çalıştır test( -wişaret):

    debugfs -w ~/test
    
  2. Dönüştürmek fileBir klasöre :

    • İstendiğinde şunu debugfsyazın:

      modify_inode file
      
    • Size bir mod soran bir komut istemi görünecektir; bunu yaz:

      040644
      
    • returnBilgi istemi tekrar görüntüleninceye kadar kalan verileri olduğu gibi bırakmak için basılı tutun .

  3. folderBir dosyaya dönüştürün :

    • İstendiğinde şunu debugfsyazın:

      modify_inode folder
      
    • Size bir mod soran bir komut istemi görünecektir; bunu yaz:

      0100644
      
    • returnBilgi istemi tekrar görüntüleninceye kadar kalan verileri olduğu gibi bırakmak için basılı tutun .

  4. İstemden çıkmak için debugfs, tuşuna basıp qardındanreturn

Operasyonun başarısını kontrol etme

  1. Test dosya sistemini tekrar bağlayın:

    sudo mount ~/test /mnt
    
  2. Dosya sistemi içeriğini kontrol edin:

    ls -l /mnt
    

    Şimdi, dosyayı bir dizinmiş gibi göstermeli ya da tam tersi :

    total 2
    drw-r--r-- 1 root root     0 may 21 18:53 file
    -rw-r--r-- 2 root root  1024 may 21 18:55 folder
    

İnode modlarını hesaplayan komut dosyası

#!/bin/bash

#### See https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Table

## Terminal measures:
x="$(( $(tput cols) / 2 ))"   # Width of the terminal
y="$(( $(tput lines) /  2 ))" # Height of the terminal

## File descriptors:
declare -A types       # Declare an associative array with file descriptors
types[f]='0x8000'      # File
types[l]='0xA000'      # Link
types[s]='0xC000'      # Socket
types[d]='0x4000'      # Directory
types[p]='0x1000'      # Named pipe
types[b]='0x6000'      # Block device
types[c]='0x2000'      # Character device

## Permissions:
declare -A permission  # Declare an associative array with permissions
permission[user_S]='0x800'  # UID
permission[user_s]='0x840'  # UID and user can execute
permission[user_r]='0x100'  # User can read
permission[user_w]='0x80'   # User can write
permission[user_x]='0x40'   # User can execute
permission[group_S]='0x400' # GID
permission[group_s]='0x408' # GID and group can execute
permission[group_r]='0x20'  # Group can read
permission[group_w]='0x10'  # Group can write
permission[group_x]='0x8'   # Group can execute
permission[other_T]='0x200' # Sticky bit
permission[other_t]='0x201' # Sticky bit and other can execute
permission[other_r]='0x4'   # Other can read
permission[other_w]='0x2'   # Other can write
permission[other_x]='0x1'   # Other can execute

## Cleanup function:
function cleanup() {
    tput cvvis        # Make the cursor visible
    tput rmcup        # Restore saved terminal contents
    stty sane         # Fix problems caused by read -s
    exit 0            # Exit gracefully
}

## Function to print at a specified position:
function pprint() {
    tput cup $1 $2
    printf "${@:3}"
}

## Function to clear the notification area:
function reset() {
    pprint $((y+2)) $((x-40)) ' %.0s' {1..25} # Print 25 spaces
}

## Function to notify something to the user:
function notify() {
    reset                          # Clear the notification area
    pprint $((y+2)) $((x-40)) "$@" # Print the notification text
}

## If the terminal is smaller than 100x8, exit gracefully (self-explainatory):
if [ $x -lt 50 ] || [ $y -lt 5 ]; then
    echo 'Error, I need a minimum of 100x10 lines to run'
    exit 0
fi

## Initialize the terminal:
trap cleanup EXIT SIGHUP SIGINT SIGTERM # Call cleanup function after receiving ^C
stty -echo  cbreak                      # Put terminal in silent mode
tput smcup                              # Save terminal contents
tput civis                              # Make the cursor inisible

## Draw the big box:
printf '\033[1;37m'                            # Color
pprint $((y-3)) $((x-48)) '\u2500%.0s' {1..97} # Upper line
pprint $((y+4)) $((x-48)) '\u2500%.0s' {1..97} # Lower line
for ((i=4;i>-4;i--)); do                       # Sides:
    pprint $((y+i)) $((x-49)) '\u2502'             # Left line
    pprint $((y+i)) $((x+49)) '\u2502'             # Right line
done                                           # End sides
pprint $((y-3)) $((x-49)) '\u256D'             # Upper-left corner
pprint $((y+4)) $((x-49)) '\u2570'             # Lower-left corner
pprint $((y-3)) $((x+49)) '\u256E'             # Upper-right corner
pprint $((y+4)) $((x+49)) '\u256F'             # Lower-right corner

## Draw the small box:
printf '\033[1;35m'                             # Color
pprint $((y+1)) $((x-10)) '\u2501%.0s' {1..10}  # Upper line
pprint $((y+3)) $((x-10)) '\u2501%.0s' {1..10}  # Lower line
pprint $((y+2)) $((x-11)) '\u2503'              # Left line
pprint $((y+2)) $((x+00)) '\u2503'              # Right line
pprint $((y+1)) $((x-11)) '\u250F'              # Upper-left corner
pprint $((y+3)) $((x-11)) '\u2517'              # Lower-left corner
pprint $((y+1)) $((x+00)) '\u2513'              # Upper-right corner
pprint $((y+3)) $((x+00)) '\u251B'              # Lower-right corner

## Print type help:
pprint $((y-2)) $((x-44)) '\033[0;37mInode type: \033[1;37mf\033[0;37mile, \033[1;37md\033[0;37mirectory, \033[1;37ml\033[0;37mink, named \033[1;37mp\033[0;37mipe, \033[1;37ms\033[0;37mocket, \033[1;37mc\033[0;37mharacter device or \033[1;37mb\033[0;37mlock device.'

## Print permission help:
pprint $((y-1)) $((x-40)) '\033[0;36mPermission (\033[1;32mu\033[0;32mser\033[0;36m, \033[1;33mg\033[0;33mroup\033[0;36m or \033[1;31mo\033[0;31mther\033[0;36m): \033[1;36mr\033[0;36mead, \033[1;36mw\033[0;36mrite, e\033[1;36mx\033[0;36mecute, \033[1;36mhyphen\033[0;36m or \033[1;36mspace\033[0;36m to skip.'
pprint $((y+0)) $((x+8)) 's\033[1;36mt\033[0;36micky bit and executable, '
pprint $((y+1)) $((x+8)) 's\033[1;36mT\033[0;36micky bit not executable, '
pprint $((y+2)) $((x+8)) '\033[1;36ms\033[0;36metuid/setgid and executable, '
pprint $((y+3)) $((x+8)) '\033[1;36mS\033[0;36metuid/setgid not executable. '

## Endless loop:
while :; do

    ## Clear the input area:
    pprint $((y+2)) $((x-10)) '% *s\n' 10         # Print 16 spaces

    ## Print mask in the input area:
    printf '\033[1;37m'                           # Color for the type
    pprint $((y+2)) $((x-10)) '\u2588'            # Block for the type
    printf '\033[1;36m'                           # Color for the permision
    pprint $((y+2)) $((x- 9)) '\u2588%.0s' {1..9} # Blocks for the permission

    ## Loop through all variables to make a proper input:
    for var in type {user,group,other}_{r,w,x}; do

        ## Assign colors and regex to fields:
        case "$var" in
            (type)    color='\033[1;37m';     regex='^[fdlpscb]$'    ;;

            (other_x)                         regex='^[-xtT]$'       ;;&
            (user_x|group_x)                  regex='^[-xsS]$'       ;;&
            (user_[rw]|group_[rw]|other_[rw]) regex="^[-${var: -1}]$";;&

            (user*)   color='\033[1;32m'                             ;;
            (group*)  color='\033[1;33m'                             ;;
            (other*)  color='\033[1;31m'                             ;;
        esac

        ## Change the pointer position:
        pprint $((y+3)) $(((x-10)+pointer)) "${color}\u2501"           # Print the pointer on its new position
        if (( pointer > 0 )); then                                     # If the pointer is not in the first position:
            pprint $((y+3)) $(((x-10)+(pointer-1))) '\033[1;35m\u2501'     # Clear the old pointer         
        fi

        ## Infinite loop until there is a valid input for the current character:
        while :; do
            printf "$color"                       # Set the character color
            IFS= read -rn 1 $var                  # Read a character (even if it's a space)

            declare $var="${!var// /-}"           # Convert spaces to hyphens.
            if [[ "$var" == "type" ]]; then       # If the current variable is type:
                declare $var="${!var//-/f}"           # Convert "-" to "f"
            fi

            if [[ "${!var}"  =~ $regex ]]; then   # If there is a valid input:
                reset                                 # Clear error notification if any
                break                                 # Exit from this loop
            else                                  # Else:
                notify "\033[1;31mWrong input!"       # Print the error message
            fi
        done

        ## Print the entered value:
        pprint $((y+2)) $(((x-10)+pointer)) "${!var}"

        ## Sum the current permission:
        ((mode+=permission[${var%_*}_${!var}]))

        ## Increment the pointer:
        ((pointer++))
    done

    ## Post-read:
    unset pointer                                 # Reset the pointer
    pprint $((y+3)) $((x-1)) "\033[1;35m\u2501"   # Clear the pointer
    read -n 1                                     # Wait for Return or another character

    ## Sum file descriptor type:
    ((mode+=${types[$type]}))

    ## Final commands:
    mode=$(printf "%o" $mode)                      # Convert mode to octal (before this was decimal)
    notify "\033[1;32mOctal mode:\033[1;34m $mode" # Print the octal mode
    unset mode                                     # Reset the mode
done

GitHub'da komut dosyasını görüntüle

Handikap

  • Klasör açılmıyor. Sen Açamıyoruz sürece bunun üzerine başlangıçta içerdiği "ham klasör verilerini" koydu.

daha fazla okuma

https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Table


@Tallus sayesinde .Bana harika bir ipucu verdi:

debugfs, dosya bayrağını dir olarak ayarlamanıza izin verecek bir inode'u doğrudan düzenlemenize izin veren bir change_inode komutuna sahiptir.


2
+1 Güzel yanıt, ancak 755 dönüştürülen dosya için yürütme yapacağından bir dosyanın izinlerini değiştirmemek için sadece notlar 0100755olmalıdır 0100644...
Maythux

Ayrıca, yeni dönüştürülen dizin açılmaz. Dosyanın klasör haline geldiğini gösterir ancak klasör açılamaz. Bunun için bir çözümün var mı?
Maythux

Bir süre daha açık tutacağım, başka büyük bir cevap yoksa seninkini işaretleyeceğim
Maythux

3
Lanet olsun bu güzel @helio: D
Rinzwind

1
Ne harika bir cevap! Tamam, sonuçta işe yaramaz, ama yine de çok etkileyici, bu yüzden benden +1.
Carl H
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.