برنامه نویسی

روز 10: ls -l *

Summarize this content to 400 words in Persian Lang

نمای کلی

بازار سخت است. ای کاش مصاحبه راحت تری داشتم. اما، هر بار که مقاله ای می نویسم، مشکل لیت کد را انجام می دهم یا یک کار روزانه را به پایان می برم، آسان تر می شود. آنها در آخرین مصاحبه SRE من را به من منتقل کردند، اما این اشکالی ندارد. این فقط به من می گوید که به هر دلیلی، من بهترین نامزد نبودم. یا به این معنی بود که آنها کارفرمای مناسبی برای من نبودند. در هر صورت، من همچنان به تمرین، مطالعه و پشتکار ادامه خواهم داد.

لیست در Bash در لینوکس

یکی از سوالاتی که از من پرسیدند این بود که این دستور در لینوکس چه کار می کند؟

$ ls -l *

خروجی

در اینجا یک نمونه از خروجی است:

➜ pwd $ ls -l *
-rw-r–r–@ 1 user group 0 Month 01 14:05 LICENSE
-rw-r–r–@ 1 user group 202 Month 01 14:05 go.mod
-rw-r–r–@ 1 user group 896 Month 01 14:05 go.sum
-rw-r–r–@ 1 user group 138 Month 01 14:05 main.go

cmd:
total 8
-rw-r–r–@ 1 user group 1444 Month 01 14:05 root.go

internal:
total 16
-rw-r–r–@ 1 user group 37 Month 01 16:05 main.go
-rw-r–r–@ 1 user group 225 Month 01 14:10 main_test.go

در اینجا مواردی وجود دارد که تا به حال دیده ایم:

دایرکتوری فعلی و تمام محتویات غیر مخفی آن را نشان می دهد.

مجوزهای فایل ها را در نماد نمادین نشان می دهد (برخلاف نمادگذاری حالت فایل مانند 0755). این مجوزها شامل مالک، گروه و سایر مجوزها (به ترتیب) همراه با @ نشان دادن ویژگی های توسعه یافته مانند SELinux.

تعداد کل عناصر فرزند را در زیر هر دایرکتوری زیر دایرکتوری فعلی (pwd) نشان می دهد.

این لیست کاربر و گروهی را که روی فرزند نشان داده شده است (فایل یا dir) نشان می دهد.
آخرین تاریخ/زمان مود برای فایل.

چگونه می کند ls دریافت این اطلاعات؟

stat – برای دریافت اطلاعات فایل و دایرکتوری برای هر مورد فهرست شده، حتی با پیوندهای نمادین و عدم استفاده از آن -l گزینه (طولانی لیست).

lstat – برای دریافت اطلاعات فراداده برای هنگام استفاده -l (طولان لیست) در انواع فایل پیوند نمادین.

نمونه کد

در تلاش برای پیاده سازی ls با -l پشتیبانی در حال حرکت، در اینجا یک نمونه کد است.

اینجاست stat_t بخش تجزیه:

func New(n string, stat *syscall.Stat_t) Stat {
var m Stat
m.BaseName = path.Base(n)
m.AbsolutePath, _ = filepath.Abs(n)
if stat.Mode&syscall.S_IFDIR == syscall.S_IFDIR {
m.Type = “directory”
} else if stat.Mode&syscall.S_IFREG == syscall.S_IFREG {
m.Type = “file”
} else if stat.Mode&syscall.S_IFLNK == syscall.S_IFLNK {
m.Type = “symlink”
} else if stat.Mode&syscall.S_IFIFO == syscall.S_IFIFO {
m.Type = “fifo”
} else if stat.Mode&syscall.S_IFSOCK == syscall.S_IFSOCK {
m.Type = “socket”
} else if stat.Mode&syscall.S_IFCHR == syscall.S_IFCHR {
m.Type = “character_device”
} else if stat.Mode&syscall.S_IFBLK == syscall.S_IFBLK {
m.Type = “block_device”
} else {
m.Type = “unknown”
}
m.SizeBytes = stat.Size
m.Mode = stat.Mode
m.UserID = stat.Uid
m.GroupID = stat.Gid
m.LastAccessedTime = time.Unix(stat.Atimespec.Sec, stat.Atimespec.Nsec)
m.LastModifiedTime = time.Unix(stat.Mtimespec.Sec, stat.Mtimespec.Nsec)
m.CreateTime = time.Unix(stat.Ctimespec.Sec, stat.Ctimespec.Nsec)
m.BirthTime = time.Unix(stat.Birthtimespec.Sec, stat.Birthtimespec.Nsec)
m.BlockSize = uint32(stat.Blksize)
m.NumBlocks = uint64(stat.Blocks)

var err error
u, err := user.LookupId(fmt.Sprintf(“%d”, stat.Uid))
if err == nil {
m.Owner = u.Username
m.UserName = u.Username
} else {
m.Owner = “unknown”
m.UserName = “unknown”
}

u, err = user.LookupId(fmt.Sprintf(“%d”, stat.Gid))
if err == nil {
m.GroupName = u.Username
} else {
m.GroupName = “unknown”
}

m.HardLinkReferenceCount = uint16(stat.Nlink)

octalPerm := os.FileMode(stat.Mode) & os.ModePerm
m.Permissions.Octal = fmt.Sprintf(“%o”, octalPerm)

const (
ownerStatTOffset = 6
groupStatTOffset = 3
otherStatTOffset = 1
)

// https://man7.org/linux/man-pages/man7/inode.7.html
// who-has-what-perms section starts at offset 6 and ends at offset 10.

// The >> operator in Go shifts the bits of a number to the right.
// Think of the number as a row of lights (1 = on, 0 = off).
// – >> 1 moves all the lights 1 step to the right, filling empty spaces on the left:
// – Positive numbers fill with 0 (e.g., 8 >> 1: 00001000 -> 00000100 = 4).
// – Negative numbers fill with 1 to keep the number negative.
// – Bits that fall off the right edge disappear.
var (
ownerPerms = uint8(octalPerm >> ownerStatTOffset)
groupPerms = uint8(octalPerm >> groupStatTOffset)
otherPerms = uint8(octalPerm >> otherStatTOffset)
)
m.Permissions.Symbolic.Owner = perm.New(ownerPerms)
m.Permissions.Symbolic.Group = perm.New(groupPerms)
m.Permissions.Symbolic.Other = perm.New(otherPerms)
return m
}

و این هم کد تجزیه مجوزها:

func New(mode uint8) SymbolicPermission {
var (
read bool
write bool
execute bool
)
const (
readOffset = 4
writeOffset = 2
executeOffset = 1
)

// bitIsSet determines whether a specific bit is set in an unsigned int.
// Example:
// mode := uint8(5) // Binary: 101
// bitIsSet(mode, 4) // Returns true (read bit is set)
// 0b101 & 0b100 = 0b100 (comparison: 0b100 == 0b100 → true)
// bitIsSet(mode, 2) // Returns false (write bit is not set)
// 0b101 & 0b010 = 0b000 (comparison: 0b000 == 0b010 → false)
// bitIsSet(mode, 1) // Returns true (execute bit is set)
// 0b101 & 0b001 = 0b001 (comparison: 0b001 == 0b001 → true)
bitIsSet := func(mode, offset uint8) bool {
return mode&offset == offset
}
read = bitIsSet(mode, readOffset)
write = bitIsSet(mode, writeOffset)
execute = bitIsSet(mode, executeOffset)

return SymbolicPermission{
Read: read,
Write: write,
Execute: execute,
}
}

نمای کلی

بازار سخت است. ای کاش مصاحبه راحت تری داشتم. اما، هر بار که مقاله ای می نویسم، مشکل لیت کد را انجام می دهم یا یک کار روزانه را به پایان می برم، آسان تر می شود. آنها در آخرین مصاحبه SRE من را به من منتقل کردند، اما این اشکالی ندارد. این فقط به من می گوید که به هر دلیلی، من بهترین نامزد نبودم. یا به این معنی بود که آنها کارفرمای مناسبی برای من نبودند. در هر صورت، من همچنان به تمرین، مطالعه و پشتکار ادامه خواهم داد.

لیست در Bash در لینوکس

یکی از سوالاتی که از من پرسیدند این بود که این دستور در لینوکس چه کار می کند؟

$ ls -l *

خروجی

در اینجا یک نمونه از خروجی است:

➜  pwd $ ls -l *
-rw-r--r--@ 1 user  group    0 Month 01 14:05 LICENSE
-rw-r--r--@ 1 user  group  202 Month 01 14:05 go.mod
-rw-r--r--@ 1 user  group  896 Month 01 14:05 go.sum
-rw-r--r--@ 1 user  group  138 Month 01 14:05 main.go

cmd:
total 8
-rw-r--r--@ 1 user  group  1444 Month 01 14:05 root.go

internal:
total 16
-rw-r--r--@ 1 user  group   37 Month 01 16:05 main.go
-rw-r--r--@ 1 user  group  225 Month 01 14:10 main_test.go

در اینجا مواردی وجود دارد که تا به حال دیده ایم:

  1. دایرکتوری فعلی و تمام محتویات غیر مخفی آن را نشان می دهد.
  2. مجوزهای فایل ها را در نماد نمادین نشان می دهد (برخلاف نمادگذاری حالت فایل مانند 0755). این مجوزها شامل مالک، گروه و سایر مجوزها (به ترتیب) همراه با @ نشان دادن ویژگی های توسعه یافته مانند SELinux.
  3. تعداد کل عناصر فرزند را در زیر هر دایرکتوری زیر دایرکتوری فعلی (pwd) نشان می دهد.
  4. این لیست کاربر و گروهی را که روی فرزند نشان داده شده است (فایل یا dir) نشان می دهد.
  5. آخرین تاریخ/زمان مود برای فایل.

چگونه می کند ls دریافت این اطلاعات؟

  • stat – برای دریافت اطلاعات فایل و دایرکتوری برای هر مورد فهرست شده، حتی با پیوندهای نمادین و عدم استفاده از آن -l گزینه (طولانی لیست).
  • lstat – برای دریافت اطلاعات فراداده برای هنگام استفاده -l (طولان لیست) در انواع فایل پیوند نمادین.

نمونه کد

در تلاش برای پیاده سازی ls با -l پشتیبانی در حال حرکت، در اینجا یک نمونه کد است.

اینجاست stat_t بخش تجزیه:

func New(n string, stat *syscall.Stat_t) Stat {
    var m Stat
    m.BaseName = path.Base(n)
    m.AbsolutePath, _ = filepath.Abs(n)
    if stat.Mode&syscall.S_IFDIR == syscall.S_IFDIR {
        m.Type = "directory"
    } else if stat.Mode&syscall.S_IFREG == syscall.S_IFREG {
        m.Type = "file"
    } else if stat.Mode&syscall.S_IFLNK == syscall.S_IFLNK {
        m.Type = "symlink"
    } else if stat.Mode&syscall.S_IFIFO == syscall.S_IFIFO {
        m.Type = "fifo"
    } else if stat.Mode&syscall.S_IFSOCK == syscall.S_IFSOCK {
        m.Type = "socket"
    } else if stat.Mode&syscall.S_IFCHR == syscall.S_IFCHR {
        m.Type = "character_device"
    } else if stat.Mode&syscall.S_IFBLK == syscall.S_IFBLK {
        m.Type = "block_device"
    } else {
        m.Type = "unknown"
    }
    m.SizeBytes = stat.Size
    m.Mode = stat.Mode
    m.UserID = stat.Uid
    m.GroupID = stat.Gid
    m.LastAccessedTime = time.Unix(stat.Atimespec.Sec, stat.Atimespec.Nsec)
    m.LastModifiedTime = time.Unix(stat.Mtimespec.Sec, stat.Mtimespec.Nsec)
    m.CreateTime = time.Unix(stat.Ctimespec.Sec, stat.Ctimespec.Nsec)
    m.BirthTime = time.Unix(stat.Birthtimespec.Sec, stat.Birthtimespec.Nsec)
    m.BlockSize = uint32(stat.Blksize)
    m.NumBlocks = uint64(stat.Blocks)

    var err error
    u, err := user.LookupId(fmt.Sprintf("%d", stat.Uid))
    if err == nil {
        m.Owner = u.Username
        m.UserName = u.Username
    } else {
        m.Owner = "unknown"
        m.UserName = "unknown"
    }

    u, err = user.LookupId(fmt.Sprintf("%d", stat.Gid))
    if err == nil {
        m.GroupName = u.Username
    } else {
        m.GroupName = "unknown"
    }

    m.HardLinkReferenceCount = uint16(stat.Nlink)

    octalPerm := os.FileMode(stat.Mode) & os.ModePerm
    m.Permissions.Octal = fmt.Sprintf("%o", octalPerm)

    const (
        ownerStatTOffset = 6
        groupStatTOffset = 3
        otherStatTOffset = 1
    )

    // https://man7.org/linux/man-pages/man7/inode.7.html
    // who-has-what-perms section starts at offset 6 and ends at offset 10.

    // The >> operator in Go shifts the bits of a number to the right.
    // Think of the number as a row of lights (1 = on, 0 = off).
    // - >> 1 moves all the lights 1 step to the right, filling empty spaces on the left:
    //   - Positive numbers fill with 0 (e.g., 8 >> 1: 00001000 -> 00000100 = 4).
    //   - Negative numbers fill with 1 to keep the number negative.
    // - Bits that fall off the right edge disappear.
    var (
        ownerPerms = uint8(octalPerm >> ownerStatTOffset)
        groupPerms = uint8(octalPerm >> groupStatTOffset)
        otherPerms = uint8(octalPerm >> otherStatTOffset)
    )
    m.Permissions.Symbolic.Owner = perm.New(ownerPerms)
    m.Permissions.Symbolic.Group = perm.New(groupPerms)
    m.Permissions.Symbolic.Other = perm.New(otherPerms)
    return m
}

و این هم کد تجزیه مجوزها:


func New(mode uint8) SymbolicPermission {
    var (
        read    bool
        write   bool
        execute bool
    )
    const (
        readOffset    = 4
        writeOffset   = 2
        executeOffset = 1
    )

    // bitIsSet determines whether a specific bit is set in an unsigned int.
    // Example:
    //   mode := uint8(5) // Binary: 101
    //   bitIsSet(mode, 4) // Returns true (read bit is set)
    //      0b101 & 0b100 = 0b100 (comparison: 0b100 == 0b100 → true)
    //   bitIsSet(mode, 2) // Returns false (write bit is not set)
    //      0b101 & 0b010 = 0b000 (comparison: 0b000 == 0b010 → false)
    //   bitIsSet(mode, 1) // Returns true (execute bit is set)
    //      0b101 & 0b001 = 0b001 (comparison: 0b001 == 0b001 → true)
    bitIsSet := func(mode, offset uint8) bool {
        return mode&offset == offset
    }
    read = bitIsSet(mode, readOffset)
    write = bitIsSet(mode, writeOffset)
    execute = bitIsSet(mode, executeOffset)

    return SymbolicPermission{
        Read:    read,
        Write:   write,
        Execute: execute,
    }
}

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا