web-dev-qa-db-fra.com

Golang instancie correctement os.FileMode

J'ai vu d'innombrables exemples et tutoriels qui montrent comment créer un fichier et tous "tricher" en définissant simplement les bits d'autorisation du fichier. Je voudrais savoir/découvrir comment instancier correctement os.FileMode à fournir à un écrivain lors de la création/mise à jour d'un fichier.

Voici un exemple grossier:

func FileWrite(path string, r io.Reader, uid, gid int, perms string) (int64, error){
    w, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0664)
    if err != nil {
        if path == "" {
            w = os.Stdout
        } else {
            return 0, err
        }
    }
    defer w.Close()

    size, err := io.Copy(w, r)

    if err != nil {
        return 0, err
    }
    return size, err
}

Dans la fonction de base ci-dessus, les bits d'autorisation 0664 sont définis et bien que cela puisse avoir du sens, je préfère parfois avoir un moyen approprié de définir correctement le mode de fichier. Comme vu ci-dessus, un exemple courant serait que l'UID/GID est connu et déjà fourni en tant que valeurs int et les perms étant des chiffres octaux qui ont été précédemment rassemblés et insérés dans une base de données sous forme de chaîne.

19
Will H

FileMode n'est qu'un uint32. http://golang.org/pkg/os/#FileMode

La définition via des constantes n'est pas de la "tricherie", vous l'utilisez comme les autres valeurs numériques. Si vous n'utilisez pas de constante, vous pouvez utiliser une conversion sur des valeurs numériques valides:

mode := int(0777)
os.FileMode(mode)
29
JimB

Mon correctif a été de définir mes propres constantes car je n'en ai trouvé aucune dans os ou syscall:

    const (
        OS_READ = 04
        OS_WRITE = 02
        OS_EX = 01
        OS_USER_SHIFT = 6
        OS_GROUP_SHIFT = 3
        OS_OTH_SHIFT = 0

        OS_USER_R = OS_READ<<OS_USER_SHIFT
        OS_USER_W = OS_WRITE<<OS_USER_SHIFT
        OS_USER_X = OS_EX<<OS_USER_SHIFT
        OS_USER_RW = OS_USER_R | OS_USER_W
        OS_USER_RWX = OS_USER_RW | OS_USER_X

        OS_GROUP_R = OS_READ<<OS_GROUP_SHIFT
        OS_GROUP_W = OS_WRITE<<OS_GROUP_SHIFT
        OS_GROUP_X = OS_EX<<OS_GROUP_SHIFT
        OS_GROUP_RW = OS_GROUP_R | OS_GROUP_W
        OS_GROUP_RWX = OS_GROUP_RW | OS_GROUP_X

        OS_OTH_R = OS_READ<<OS_OTH_SHIFT
        OS_OTH_W = OS_WRITE<<OS_OTH_SHIFT
        OS_OTH_X = OS_EX<<OS_OTH_SHIFT
        OS_OTH_RW = OS_OTH_R | OS_OTH_W
        OS_OTH_RWX = OS_OTH_RW | OS_OTH_X

        OS_ALL_R = OS_USER_R | OS_GROUP_R | OS_OTH_R
        OS_ALL_W = OS_USER_W | OS_GROUP_W | OS_OTH_W
        OS_ALL_X = OS_USER_X | OS_GROUP_X | OS_OTH_X
        OS_ALL_RW = OS_ALL_R | OS_ALL_W
        OS_ALL_RWX = OS_ALL_RW | OS_GROUP_X
)

Cela me permet alors de spécifier directement mon intention:

        // Create any directories needed to put this file in them
        var dir_file_mode os.FileMode
        dir_file_mode = os.ModeDir | (OS_USER_RWX | OS_ALL_R)
        os.MkdirAll(dir_str, dir_file_mode)

Je suis sûr que cela pourrait être amélioré en utilisant iota et quelques autres combinaisons d'autorisations, mais cela fonctionne pour moi pour l'instant.

34
Chris Hopkins