NTFSで一つのファイルに張れるハードリンクは1023個までだよ!! の続き記事です。
1023 個って数字な時点で SAN 値ダダ下がり、もう一歩でソウルジェム真っ黒!!ってところまで来てたものの、自分の用途ならば限界超えてリンクを張るなら一つファイルをコピーしてハードリンク先を半分そっちに割り振ればいいやと思っていたので、そのための検証をしていたらここでもドハマりしたのでこれ以上不幸な(ry
UN*X の場合、ファイルにハードリンクされた数は stat で取得できます。例えば、Python のドキュメントだとこのあたり。ところが、こいつは Windows では正しく動きません。 OKOK。これは想定内。これくらいで動じてたらソウルジェムが幾つあっても足りない。
Windows にはこれらの情報を得るための API 、GetFileInformationByHandle() があります。ハードリンク数を取得するのはこちらが正解。これを使ってリンク数を取得するテストプログラムは以下のとおり
import os
import sys
import stat
import ctypes
import win32file
def CreateHardLink(src, dest):
CreateHardLinkW = ctypes.windll.kernel32.CreateHardLinkW
CreateHardLinkW.argtypes = [ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_int]
ret = CreateHardLinkW(dest, src, 0)
if ret ==0:
print ctypes.FormatError()
print src
print dest
raise
return ret
def getNumHardLink(fileName):
hFile = win32file.CreateFile (
fileName,
win32file.GENERIC_READ,
win32file.FILE_SHARE_READ,
None,
win32file.OPEN_EXISTING,
0,
None
)
(attributes,
created_at, accessed_at, written_at,
volume,
file_hi, file_lo,
n_links,
index_hi, index_lo
) = win32file.GetFileInformationByHandle (hFile)
hFile.Close()
return n_links
d = sys.argv[1]
print d
src = os.path.join(d, 'src.txt')
dest = os.path.join(d, 'dest.txt')
if not os.path.exists(src):
open(src, 'w').close()
CreateHardLink(src, dest)
s = os.stat(src)
if s.st_nlink == 2:
print 'OK by stat'
else:
print ('invalid link count by stat : %d' % s.st_nlink)
n_links = getNumHardLink(src)
if n_links == 2:
print 'OK by API'
else:
print ('invalid link count by API : %d' % n_links)
比較のために stat でも情報を拾っています。
C:\temp>python countLink.py c:\temp
c:\temp
invalid link count by stat : 0
OK by API
ちゃんと動いています。
だがしかし!!ここで一筋縄でいかないのが Windows 様。ネットワーク上のファイルシステムを指定してみると。。。
C:\temp>python countLink.py \\nas01\PJ\test
\\nas01\PJ\test
invalid link count by stat : 0
invalid link count by API : 1
え。。。。
え。。。。。
はい、ちゃんと値が取れません。ちなみに、これもサーバーによるらしく某所ではこの症状が起きてドハマりしました。
ちなみに Windows7+QNAP(Linux) ではきちんと動いているっぽいです。
たまたま外れのサーバーだったのか、それとも Windows ベースのものだったからなのか。。。どなたか他の環境で検証していただけないでしょうか。
この数字が取れないと本当に困るんですけど。。。。
これ以外でハードリンクされているかどうかを確認するには、先ほどの GetFileInformationByHandle() でファイルの ID が取れるので、
それを比較するしかなさそうな予感がします。。。。