mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 06:47:20 +08:00
feat: 优化删除和写入支持自动去除ia属性
This commit is contained in:
1
go.mod
1
go.mod
@@ -57,6 +57,7 @@ require (
|
||||
github.com/devhaozi/huaweicloud-sdk-go-v3 v0.0.0-20241018211007-bbebb6de5db7 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/g0rbe/go-chattr v1.0.1 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
|
||||
github.com/glebarez/go-sqlite v1.22.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
|
||||
2
go.sum
2
go.sum
@@ -21,6 +21,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/g0rbe/go-chattr v1.0.1 h1:CHwYB+WKB46hkzt6Jxyvkyrz7u9njghUOFvmx2gir84=
|
||||
github.com/g0rbe/go-chattr v1.0.1/go.mod h1:yQc6VPJfpDDC1g+W2t47+yYmzBNioax/GLiyJ25/IOs=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6 h1:3+PzJTKLkvgjeTbts6msPJt4DixhT4YtFNf1gtGe3zc=
|
||||
github.com/gabriel-vasile/mimetype v1.4.6/go.mod h1:JX1qVKqZd40hUPpAfiNTe0Sne7hdfKSbOqqmkq8GCXc=
|
||||
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
|
||||
|
||||
123
pkg/chattr/chattr.go
Normal file
123
pkg/chattr/chattr.go
Normal file
@@ -0,0 +1,123 @@
|
||||
// Package chattr https://github.com/g0rbe/go-chattr/pull/3
|
||||
package chattr
|
||||
|
||||
/*
|
||||
A package for change attribute of a file on Linux, similar to the chattr command.
|
||||
|
||||
Example to set the immutable attribute to a file:
|
||||
|
||||
file, err := os.OpenFile("file.txt", os.O_RDONLY, 0666)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
|
||||
err = chattr.SetAttr(file, chattr.FS_IMMUTABLE_FL)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
*/
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// from /usr/include/linux/fs.h
|
||||
const (
|
||||
FS_SECRM_FL uint32 = 0x00000001 /* Secure deletion */
|
||||
FS_UNRM_FL = 0x00000002 /* Undelete */
|
||||
FS_COMPR_FL = 0x00000004 /* Compress file */
|
||||
FS_SYNC_FL = 0x00000008 /* Synchronous updates */
|
||||
FS_IMMUTABLE_FL = 0x00000010 /* Immutable file */
|
||||
FS_APPEND_FL = 0x00000020 /* writes to file may only append */
|
||||
FS_NODUMP_FL = 0x00000040 /* do not dump file */
|
||||
FS_NOATIME_FL = 0x00000080 /* do not update atime */
|
||||
FS_DIRTY_FL = 0x00000100
|
||||
FS_COMPRBLK_FL = 0x00000200 /* One or more compressed clusters */
|
||||
FS_NOCOMP_FL = 0x00000400 /* Don't compress */
|
||||
FS_ENCRYPT_FL = 0x00000800 /* Encrypted file */
|
||||
FS_BTREE_FL = 0x00001000 /* btree format dir */
|
||||
FS_INDEX_FL = 0x00001000 /* hash-indexed directory */
|
||||
FS_IMAGIC_FL = 0x00002000 /* AFS directory */
|
||||
FS_JOURNAL_DATA_FL = 0x00004000 /* Reserved for ext3 */
|
||||
FS_NOTAIL_FL = 0x00008000 /* file tail should not be merged */
|
||||
FS_DIRSYNC_FL = 0x00010000 /* dirsync behaviour (directories only) */
|
||||
FS_TOPDIR_FL = 0x00020000 /* Top of directory hierarchies*/
|
||||
FS_HUGE_FILE_FL = 0x00040000 /* Reserved for ext4 */
|
||||
FS_EXTENT_FL = 0x00080000 /* Extents */
|
||||
FS_EA_INODE_FL = 0x00200000 /* Inode used for large EA */
|
||||
FS_EOFBLOCKS_FL = 0x00400000 /* Reserved for ext4 */
|
||||
FS_NOCOW_FL = 0x00800000 /* Do not cow file */
|
||||
FS_INLINE_DATA_FL = 0x10000000 /* Reserved for ext4 */
|
||||
FS_PROJINHERIT_FL = 0x20000000 /* Create with parents projid */
|
||||
FS_RESERVED_FL = 0x80000000 /* reserved for ext2 lib */
|
||||
|
||||
)
|
||||
|
||||
// from ioctl_list manpage
|
||||
const (
|
||||
FS_IOC_GETFLAGS uintptr = 0x80086601
|
||||
FS_IOC_SETFLAGS uintptr = 0x40086602
|
||||
)
|
||||
|
||||
func ioctl(f *os.File, request uintptr, attrp *uint32) error {
|
||||
argp := uintptr(unsafe.Pointer(attrp))
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_IOCTL, f.Fd(), request, argp)
|
||||
if errno != 0 {
|
||||
return os.NewSyscallError("ioctl", errno)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAttrs retrieves the attributes of a file.
|
||||
func GetAttrs(f *os.File) (uint32, error) {
|
||||
attr := uint32(1)
|
||||
err := ioctl(f, FS_IOC_GETFLAGS, &attr)
|
||||
|
||||
return attr, err
|
||||
}
|
||||
|
||||
// SetAttr sets the given attribute.
|
||||
func SetAttr(f *os.File, attr uint32) error {
|
||||
attrs, err := GetAttrs(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attrs |= attr
|
||||
|
||||
return ioctl(f, FS_IOC_SETFLAGS, &attrs)
|
||||
|
||||
}
|
||||
|
||||
// UnsetAttr unsets the given attribute.
|
||||
func UnsetAttr(f *os.File, attr uint32) error {
|
||||
attrs, err := GetAttrs(f)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
attrs ^= attrs & attr
|
||||
|
||||
return ioctl(f, FS_IOC_SETFLAGS, &attrs)
|
||||
}
|
||||
|
||||
// IsAttr checks whether the given attribute is set.
|
||||
func IsAttr(f *os.File, attr uint32) (bool, error) {
|
||||
attrs, err := GetAttrs(f)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if (attrs & attr) != 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/TheTNB/panel/pkg/chattr"
|
||||
)
|
||||
|
||||
// Write 写入文件
|
||||
@@ -12,27 +14,58 @@ func Write(path string, data string, permission os.FileMode) error {
|
||||
return err
|
||||
}
|
||||
|
||||
err := os.WriteFile(path, []byte(data), permission)
|
||||
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, permission)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
iFlag, _ := chattr.IsAttr(file, chattr.FS_IMMUTABLE_FL)
|
||||
aFlag, _ := chattr.IsAttr(file, chattr.FS_APPEND_FL)
|
||||
if iFlag {
|
||||
_ = chattr.UnsetAttr(file, chattr.FS_IMMUTABLE_FL)
|
||||
}
|
||||
if aFlag {
|
||||
_ = chattr.UnsetAttr(file, chattr.FS_APPEND_FL)
|
||||
}
|
||||
|
||||
_, err = file.WriteString(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if iFlag {
|
||||
_ = chattr.SetAttr(file, chattr.FS_IMMUTABLE_FL)
|
||||
}
|
||||
if aFlag {
|
||||
_ = chattr.SetAttr(file, chattr.FS_APPEND_FL)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteAppend 追加写入文件
|
||||
func WriteAppend(path string, data string) error {
|
||||
file, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
iFlag, _ := chattr.IsAttr(file, chattr.FS_IMMUTABLE_FL)
|
||||
if iFlag {
|
||||
_ = chattr.UnsetAttr(file, chattr.FS_IMMUTABLE_FL)
|
||||
}
|
||||
|
||||
_, err = file.WriteString(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if iFlag {
|
||||
_ = chattr.SetAttr(file, chattr.FS_IMMUTABLE_FL)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
// Remove 删除文件/目录
|
||||
func Remove(path string) error {
|
||||
_, _ = shell.Execf("chattr -R -ia '%s'", path)
|
||||
return os.RemoveAll(path)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user