Fuck.  For PC support, this must be in the distribution.
diff --git a/Lib/dos_8x3/posixpat.py b/Lib/dos_8x3/posixpat.py
new file mode 100755
index 0000000..d284834
--- /dev/null
+++ b/Lib/dos_8x3/posixpat.py
@@ -0,0 +1,307 @@
+# Module 'posixpath' -- common operations on POSIX pathnames
+
+import posix
+import stat
+
+
+# Normalize the case of a pathname.  Trivial in Posix, string.lower on Mac.
+# On MS-DOS this may also turn slashes into backslashes; however, other
+# normalizations (such as optimizing '../' away) are not allowed
+# (another function should be defined to do that).
+
+def normcase(s):
+	return s
+
+
+# Return wheter a path is absolute.
+# Trivial in Posix, harder on the Mac or MS-DOS.
+
+def isabs(s):
+	return s[:1] == '/'
+
+
+# Join two pathnames.
+# Ignore the first part if the second part is absolute.
+# Insert a '/' unless the first part is empty or already ends in '/'.
+
+def join(a, b):
+	if b[:1] == '/': return b
+	if a == '' or a[-1:] == '/': return a + b
+	# Note: join('x', '') returns 'x/'; is this what we want?
+	return a + '/' + b
+
+
+# Split a path in head (everything up to the last '/') and tail (the
+# rest).  If the path ends in '/', tail will be empty.  If there is no
+# '/' in the path, head  will be empty.
+# Trailing '/'es are stripped from head unless it is the root.
+
+def split(p):
+	import string
+	i = string.rfind(p, '/') + 1
+	head, tail = p[:i], p[i:]
+	if head and head <> '/'*len(head):
+		while head[-1] == '/':
+			head = head[:-1]
+	return head, tail
+
+
+# Split a path in root and extension.
+# The extension is everything starting at the first dot in the last
+# pathname component; the root is everything before that.
+# It is always true that root + ext == p.
+
+def splitext(p):
+	root, ext = '', ''
+	for c in p:
+		if c == '/':
+			root, ext = root + ext + c, ''
+		elif c == '.':
+			if ext:
+				root, ext = root + ext, c
+			else:
+				ext = c
+		elif ext:
+			ext = ext + c
+		else:
+			root = root + c
+	return root, ext
+
+
+# Split a pathname into a drive specification and the rest of the
+# path.  Useful on DOS/Windows/NT; on Unix, the drive is always empty.
+
+def splitdrive(p):
+	return '', p
+
+
+# Return the tail (basename) part of a path.
+
+def basename(p):
+	return split(p)[1]
+
+
+# Return the head (dirname) part of a path.
+
+def dirname(p):
+	return split(p)[0]
+
+
+# Return the longest prefix of all list elements.
+
+def commonprefix(m):
+	if not m: return ''
+	prefix = m[0]
+	for item in m:
+		for i in range(len(prefix)):
+			if prefix[:i+1] <> item[:i+1]:
+				prefix = prefix[:i]
+				if i == 0: return ''
+				break
+	return prefix
+
+
+# Is a path a symbolic link?
+# This will always return false on systems where posix.lstat doesn't exist.
+
+def islink(path):
+	try:
+		st = posix.lstat(path)
+	except (posix.error, AttributeError):
+		return 0
+	return stat.S_ISLNK(st[stat.ST_MODE])
+
+
+# Does a path exist?
+# This is false for dangling symbolic links.
+
+def exists(path):
+	try:
+		st = posix.stat(path)
+	except posix.error:
+		return 0
+	return 1
+
+
+# Is a path a posix directory?
+# This follows symbolic links, so both islink() and isdir() can be true
+# for the same path.
+
+def isdir(path):
+	try:
+		st = posix.stat(path)
+	except posix.error:
+		return 0
+	return stat.S_ISDIR(st[stat.ST_MODE])
+
+
+# Is a path a regular file?
+# This follows symbolic links, so both islink() and isfile() can be true
+# for the same path.
+
+def isfile(path):
+	try:
+		st = posix.stat(path)
+	except posix.error:
+		return 0
+	return stat.S_ISREG(st[stat.ST_MODE])
+
+
+# Are two filenames really pointing to the same file?
+
+def samefile(f1, f2):
+	s1 = posix.stat(f1)
+	s2 = posix.stat(f2)
+	return samestat(s1, s2)
+
+
+# Are two open files really referencing the same file?
+# (Not necessarily the same file descriptor!)
+# XXX Oops, posix.fstat() doesn't exist yet!
+
+def sameopenfile(fp1, fp2):
+	s1 = posix.fstat(fp1)
+	s2 = posix.fstat(fp2)
+	return samestat(s1, s2)
+
+
+# Are two stat buffers (obtained from stat, fstat or lstat)
+# describing the same file?
+
+def samestat(s1, s2):
+	return s1[stat.ST_INO] == s2[stat.ST_INO] and \
+		s1[stat.ST_DEV] == s2[stat.ST_DEV]
+
+
+# Is a path a mount point?
+# (Does this work for all UNIXes?  Is it even guaranteed to work by POSIX?)
+
+def ismount(path):
+	try:
+		s1 = posix.stat(path)
+		s2 = posix.stat(join(path, '..'))
+	except posix.error:
+		return 0 # It doesn't exist -- so not a mount point :-)
+	dev1 = s1[stat.ST_DEV]
+	dev2 = s2[stat.ST_DEV]
+	if dev1 != dev2:
+		return 1		# path/.. on a different device as path
+	ino1 = s1[stat.ST_INO]
+	ino2 = s2[stat.ST_INO]
+	if ino1 == ino2:
+		return 1		# path/.. is the same i-node as path
+	return 0
+
+
+# Directory tree walk.
+# For each directory under top (including top itself, but excluding
+# '.' and '..'), func(arg, dirname, filenames) is called, where
+# dirname is the name of the directory and filenames is the list
+# files files (and subdirectories etc.) in the directory.
+# The func may modify the filenames list, to implement a filter,
+# or to impose a different order of visiting.
+
+def walk(top, func, arg):
+	try:
+		names = posix.listdir(top)
+	except posix.error:
+		return
+	func(arg, top, names)
+	exceptions = ('.', '..')
+	for name in names:
+		if name not in exceptions:
+			name = join(top, name)
+			if isdir(name) and not islink(name):
+				walk(name, func, arg)
+
+
+# Expand paths beginning with '~' or '~user'.
+# '~' means $HOME; '~user' means that user's home directory.
+# If the path doesn't begin with '~', or if the user or $HOME is unknown,
+# the path is returned unchanged (leaving error reporting to whatever
+# function is called with the expanded path as argument).
+# See also module 'glob' for expansion of *, ? and [...] in pathnames.
+# (A function should also be defined to do full *sh-style environment
+# variable expansion.)
+
+def expanduser(path):
+	if path[:1] <> '~':
+		return path
+	i, n = 1, len(path)
+	while i < n and path[i] <> '/':
+		i = i+1
+	if i == 1:
+		if not posix.environ.has_key('HOME'):
+			return path
+		userhome = posix.environ['HOME']
+	else:
+		import pwd
+		try:
+			pwent = pwd.getpwnam(path[1:i])
+		except KeyError:
+			return path
+		userhome = pwent[5]
+	if userhome[-1:] == '/': i = i+1
+	return userhome + path[i:]
+
+
+# Expand paths containing shell variable substitutions.
+# This expands the forms $variable and ${variable} only.
+# Non-existant variables are left unchanged.
+
+_varprog = None
+
+def expandvars(path):
+	global _varprog
+	if '$' not in path:
+		return path
+	if not _varprog:
+		import regex
+		_varprog = regex.compile('$\([a-zA-Z0-9_]+\|{[^}]*}\)')
+	i = 0
+	while 1:
+		i = _varprog.search(path, i)
+		if i < 0:
+			break
+		name = _varprog.group(1)
+		j = i + len(_varprog.group(0))
+		if name[:1] == '{' and name[-1:] == '}':
+			name = name[1:-1]
+		if posix.environ.has_key(name):
+			tail = path[j:]
+			path = path[:i] + posix.environ[name]
+			i = len(path)
+			path = path + tail
+		else:
+			i = j
+	return path
+
+
+# Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
+# It should be understood that this may change the meaning of the path
+# if it contains symbolic links!
+
+def normpath(path):
+	import string
+	# Treat initial slashes specially
+	slashes = ''
+	while path[:1] == '/':
+		slashes = slashes + '/'
+		path = path[1:]
+	comps = string.splitfields(path, '/')
+	i = 0
+	while i < len(comps):
+		if comps[i] == '.':
+			del comps[i]
+		elif comps[i] == '..' and i > 0 and \
+					  comps[i-1] not in ('', '..'):
+			del comps[i-1:i+1]
+			i = i-1
+		elif comps[i] == '' and i > 0 and comps[i-1] <> '':
+			del comps[i]
+		else:
+			i = i+1
+	# If the path is now empty, substitute '.'
+	if not comps and not slashes:
+		comps.append('.')
+	return slashes + string.joinfields(comps, '/')