The Awesome Factor

Files and file-systems in Factor, part 1

Friday, January 9, 2009

#files #symlinks

Factor now has an easy way access to get information about files and file-systems in a high-level way across all the platforms that it supports. The API is really simple – pass a pathname and get information back about the file or file-system as a tuple. The second part of this post will demonstrate a clone of the Unix tools ls, for listing files, and df, for listing file-systems.

File-info

There are now words to get information about files and symlinks, using file-info and link-info which map to C system calls stat and lstat. Some slots are shared across all platforms while others are only present on a particular platform. There are symbols representing all of the file types, like +regular-file+, +directory+, and +symbolic-link+. Here are some examples.
MacOSX

( scratchpad ) "resource:license.txt" file-info .
T{ bsd-file-info
    { type +regular-file+ }
    { size 1252 }
    { permissions 33188 }
    { created
        T{ timestamp
            { year 2008 }
            { month 11 }
            { day 17 }
            { hour 23 }
            { minute 34 }
            { second 5 }
            { gmt-offset T{ duration { hour -6 } } }
        }
    }
    { modified
        T{ timestamp
            { year 2008 }
            { month 11 }
            { day 17 }
            { hour 23 }
            { minute 34 }
            { second 5 }
            { gmt-offset T{ duration { hour -6 } } }
        }
    }
    { accessed
        T{ timestamp
            { year 2008 }
            { month 12 }
            { day 9 }
            { hour 12 }
            { minute 34 }
            { second 8 }
            { gmt-offset T{ duration { hour -6 } } }
        }
    }
    { uid 501 }
    { gid 20 }
    { dev 234881026 }
    { ino 992362 }
    { nlink 1 }
    { rdev 0 }
    { blocks 8 }
    { blocksize 4096 }
    { birth-time
        T{ timestamp
            { year 2008 }
            { month 11 }
            { day 17 }
            { hour 23 }
            { minute 34 }
            { second 5 }
            { gmt-offset T{ duration { hour -6 } } }
        }
    }
    { flags 0 }
    { gen 0 }
}

Windows XP

( scratchpad ) "resource:license.txt" file-info .
T{ windows-file-info
    { type +regular-file+ }
    { size 1252 }
    { permissions 32 }
    { created
        T{ timestamp
            { year 2008 }
            { month 3 }
            { day 23 }
            { hour 23 }
            { minute 28 }
            { second 12 }
        }
    }
    { modified
        T{ timestamp
            { year 2008 }
            { month 3 }
            { day 27 }
            { hour 23 }
            { minute 24 }
            { second 12 }
        }
    }
    { accessed
        T{ timestamp
            { year 2008 }
            { month 9 }
            { day 19 }
            { hour 23 }
            { minute 8 }
            { second 41 }
        }
    }
    { attributes { +archive+ } }
}

FreeBSD

( scratchpad ) "resource:license.txt" file-info .
T{ bsd-file-info
    { type +regular-file+ }
    { size 1252 }
    { permissions 33188 }
    { created
        T{ timestamp
            { year 2008 }
            { month 4 }
            { day 6 }
            { hour 12 }
            { minute 6 }
            { second 53 }
            { gmt-offset T{ duration { hour -6 } } }
        }
    }
    { modified
        T{ timestamp
            { year 2008 }
            { month 4 }
            { day 6 }
            { hour 12 }
            { minute 6 }
            { second 53 }
            { gmt-offset T{ duration { hour -6 } } }
        }
    }
    { accessed
        T{ timestamp
            { year 2008 }
            { month 4 }
            { day 6 }
            { hour 12 }
            { minute 6 }
            { second 59 }
            { gmt-offset T{ duration { hour -6 } } }
        }
    }
    { uid 1002 }
    { gid 1002 }
    { dev 89 }
    { ino 343452 }
    { nlink 1 }
    { rdev 1348575 }
    { blocks 4 }
    { blocksize 4096 }
    { birth-time
        T{ timestamp
            { year 2008 }
            { month 4 }
            { day 6 }
            { hour 12 }
            { minute 6 }
            { second 53 }
            { gmt-offset T{ duration { hour -6 } } }
        }
    }
    { flags 0 }
    { gen 0 }
}

File Systems

The file-system utility word above works on file-system tuples that contain cross-platform information like the device name, the mount point, the number of free, used, and total bytes. A file-system tuple on Unix has all of the file-system information found in both statfs and statvfs while a Windows file-system object has the device-id, volume name, and byte usage slots. There is not a single win32 API call that gives as much information as on Unix systems – instead I call a combination of GetDiskFreeSpaceEx, FindFirstVolume, GetVolumePathNamesForVolumeName, GetVolumeInformation.
On every Unix besides Linux, there is a member of the statfs or statvfs structure that gives you the file-system that contains the file. So, I had to roll my own for it to work the same way across all platforms. The algorithm is pretty simple: the follow-links word follows links up to 10 times (configurable) and once it stops, finds the parent directory and follows the links again until the directory is a member of the directories in the /etc/mtab file. If there is circularity or a broken link, it throws an error.

FreeBSD

( scratchpad ) "/" file-system-info .
T{ freebsd-file-system-info
    { device-name "/dev/da0s1a" }
    { mount-point "/" }
    { type "ufs" }
    { available-space 368117760 }
    { free-space 409702400 }
    { used-space 110110720 }
    { total-space 519813120 }
    { block-size 2048 }
    { preferred-block-size 2048 }
    { blocks 253815 }
    { blocks-free 200050 }
    { blocks-available 179745 }
    { files 65790 }
    { files-free 61501 }
    { files-available 61501 }
    { name-max 255 }
    { flags 20480 }
    { id { 0 0 } }
    { version 537068824 }
    { io-size 16384 }
    { owner 0 }
    { syncreads 0 }
    { syncwrites 0 }
    { asyncreads 0 }
    { asyncwrites 0 }
}

Windows XP 64

( scratchpad ) "k:\\" file-system-info .
T{ win32-file-system-info
    { device-name "" }
    { mount-point "k:\\" }
    { type "NTFS" }
    { available-space 174530142208 }
    { free-space 174530142208 }
    { used-space 225547444224 }
    { total-space 400077586432 }
    { max-component 255 }
    { flags 459007 }
    { device-serial 3695676537 }
}

The Factor build farm will start using file-system-info to report when a drive fills up pretty soon.