kurumi-bioの雑記帳

プログラミング、パソコン、ペット、 犬、お出かけ

初心者のGo言語 -28- フォルダのパーミッション(権限)を調べる

こんにちは、kurumi-bioです。

環境

  • Windows
    OSバージョン:Windows11 Home 22H2
    Go言語のバージョン:go version go1.20 windows/amd64

  • Linux
    OSバージョン:openSUSE Leap 15.4
    Go言語のバージョン:go version go1.20.2 linux/amd64

はじめに

Linuxパーミッション(権限)は、
r:読み取り可能 / w:書き込み可能 / x:実行可能
が指定可能です。
ファイルのパーミッション(権限)は、操作と対応しているで理解できますが、
フォルダの場合は、いまいちわからないです。
ですので、今まで学習してきたfmtパッケージとosパッケージを使って、 パーミッション(権限)ごとに可能な操作を確認するプログラムを作ってみます。

試すこと

パーミッション(権限)を変化させながら下記の操作の可否を試します。

  • フォルダ直下のリストが取得可能か
  • フォルダ移れるか
  • フォルダ直下のファイルの読み込みが可能か
  • フォルダ直下にファイルの書き込みが可能か
  • フォルダ直下のファイルが削除できるか

結果

ソースコードが長いので先に結果を記載します。

  • r
    • 直下のリスト取得の可否
  • w
    • 単体では意味がない
    • Xと組み合わせてフォルダ内のファイル書き込みの可否
  • x
    • フォルダに移る可否
    • フォルダ内のファイル読み込みの可否

テストコード

今回はソースコードが長いので、2つのファイルで作成することにしました。

◆テストコード -1-

package main

import (
    "fmt"
)

func main() {
    const dirName = "test"
    readTestFilePath := fmt.Sprintf("%s/readTest.txt", dirName)
    writeTestFilePath := fmt.Sprintf("%s/writeTest.txt", dirName)

    fmt.Println("             |ls |cd | W | R | D |")

    for i := 0; i <= 700; i = i + 100 {
        s := fmt.Sprintf("%03d", i)
        //前処理(準備)
        md(dirName)           // テスト用のフォルダを作成
        wft(readTestFilePath) // Readテスト用のファイルを作成
        cm(dirName, s)        // フォルダのパーミッションを変更
        pm(dirName)           // フォルダのパーミッションを出力

        //試すこと
        dd(dirName)            // フォルダ直下のリスト取得の可否を出力
        ch(dirName)            // フォルダ移動の可否を出力
        wfp(writeTestFilePath) // フォルダ直下のファイル書き込みの可否を出力
        rf(readTestFilePath)   // フォルダ直下のファイル読み込みの可否を出力
        rm(readTestFilePath)   // フォルダ直下のファイル削除の可否を出力
        fmt.Println("")

        //後処理(片付け)
        cm(dirName, "0700") // フォルダのパーミッションをフルアクセスに変更
        ra(dirName)         // フォルダの削除

    }
}

コードの説明 forループで、フォルダの所有者のパーミッション(権限)を変化させるため000~700まで100刻みでパーミッション(権限)を変化させます。
forループ内で、動作確認テストの前準備として、パーミッション(権限)を確認するためのテストフォルダを作成と読み込みテスト用のファイルを作成します。
その後、試したかった操作を一通り行います。
最後に、テストフォルダを削除するためパーミッション(権限)をフルアクセス可能にしてからフォルダごと削除しています。

◆広告(中):ディスプレイ広告

広告の下に続きます。

◆テストコード -2-

package main

import (
    "fmt"
    "os"
    "strconv"
)

// 引数で指定したフォルダをサブフォルダを含め削除する
func ra(fileName string) {
    os.RemoveAll(fileName)
}

// 引数で指定したファイルを削除する
func rm(fileName string) {
    e := os.Remove(fileName)
    if e != nil {
        fmt.Print("| X |")
    } else {
        fmt.Print("| O |")
    }
}

func wft(filePath string) {
    wf(filePath, true)
}
func wfp(filePath string) {
    wf(filePath, false)
}
// 引数で指定したパスでファイルを作成する
func wf(filePath string, isTest bool) {
    e := os.WriteFile(filePath, []byte("Write Test"), 0666)
    if !(isTest) {
        if e != nil {
            fmt.Print("| X ")
        } else {
            fmt.Print("| O ")
        }
    }
}

// 引数で指定したファイルを読み込む
func rf(filePath string) {
    _, e := os.ReadFile(filePath)
    if e != nil {
        fmt.Print("| X ")
    } else {
        fmt.Print("| O ")
    }
}

// 引数で指定したフォルダ直下のファイルリストを取得する
func dd(dirPath string) {
    _, e := os.ReadDir(dirPath)
    if e != nil {
        fmt.Print("| X ")
    } else {
        fmt.Print("| O ")
    }
}

// 引数で指定したフォルダに変更する
func ch(dirPath string) {
    e := os.Chdir(dirPath)
    if e != nil {
        fmt.Print("| X ")
    } else {
        fmt.Print("| O ")
        os.Chdir("../")
    }
}

// 引数で指定したフォルダを作成する
func md(dirPath string) {
    e := os.Mkdir(dirPath, 0750)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Mkdir", e))
    }
}

// 引数で指定したフォルダのモードを引数で指定したモードに変更する
func cm(filePath string, mode string) {
    i, _ := strconv.ParseInt(mode, 8, 32)
    e := os.Chmod(filePath, os.FileMode(i))
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Chmod", e))
        return
    }
}

// 引数で指定したファイルのパーミッションを出力する
func pm(fileName string) {
    fi, e := os.Stat(fileName)
    if e != nil {
        fmt.Fprintf(os.Stderr, "%v\n", os.NewSyscallError("os.Stat", e))
        return
    }
    fmt.Printf("[%v] ", fi.Mode().Perm())
}

コードの説明 osパッケージの関数を使ってファイルおよびディレクトリの操作を行っています。 操作が正常に終了した場合は"O"を出力し、エラーが発生した場合は"X"を出力しています。

◆実行結果(Linux)

実行結果の説明 各列ですが、
ls列がリスト取得の可否、cd列が移れるかの可否、
W列、R列、D列が、それぞれ直下のファイルに対して書き込み、読み込み、削除の可否
を表しています。
r権限が、ファイル読み込みではなくリスト取得の可否で、x権限がファイル読み込みの可否だったのが意外でした。 Linuxは細かな制御ができるのが良いですよね。

◆実行結果(Windows)

実行結果の説明 Windowsは、パーミッション(権限)にどんな値を指定しても同じ結果になりました。

最後までご覧いただきありがとうございます