Friday, January 09, 2009

Files and file-systems in Factor, part 1

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.

No comments: