Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
-- effecient replacement for "... | xargs ar q libfoo.a"
-- usage:
-- find -name '*.o' | arq libfoo.a
import System.Environment (getArgs)
import System.IO
import Monad (liftM, unless, when)
import qualified System.Posix.Types as Posix
import qualified System.Posix.Files as Posix
import Foreign (allocaBytes)
import Numeric (showOct)
data ArEntryHeader = ArEntryHeader {
fileName :: String, -- 0 15 File name ASCII
fileDate :: Posix.EpochTime, -- 16 27 File date Decimal
ownerID :: Posix.UserID, -- 28 33 Owner ID Decimal
groupID :: Posix.GroupID, -- 34 39 Group ID Decimal
fileMode :: Posix.FileMode, -- 40 47 File mode Octal
fileSize :: Posix.FileOffset -- 48 57 File size Decimal
-- 58 59 Header magic "`\n"
--fileData -- 60 60+size File data
}
main = do
[arFile] <- getArgs
oFiles <- liftM words getContents
hnd <- openBinaryFile arFile WriteMode
hPutStr hnd "!\n"
let extendedFileNames = filter ((>15) . length) (map basenameOf oFiles)
unless (null extendedFileNames) $ do
let sectionSize = sum (map ((+2) . length) extendedFileNames)
content [] = ""
content (f:fs) = f ++ '/' : '\n' : content fs
hPutChars hnd 48 "//"
hPutChars hnd 10 (show sectionSize)
hPutChar hnd '`'
hPutChar hnd '\n'
hPutStr hnd (content extendedFileNames)
when (sectionSize `mod` 2 == 1)
(hPutChar hnd '\n')
let loop _ [] = return ()
loop offset (fname:fnames) = do
let basename = basenameOf fname
status <- Posix.getFileStatus fname
file <- openBinaryFile fname ReadMode
hPutArEntryHeader hnd ArEntryHeader {
fileName = if length basename > 15
then '/' : show offset
else basename ++ "/",
fileDate = Posix.modificationTime status,
ownerID = Posix.fileOwner status,
groupID = Posix.fileGroup status,
fileMode = Posix.fileMode status,
fileSize = Posix.fileSize status
}
hCopy hnd file
when (Posix.fileSize status `mod` 2 == 1)
(hPutChar hnd '\n')
hClose file
let offset' | length basename > 15 = offset + 2 + length basename
| otherwise = offset
loop offset' fnames
loop 0 oFiles
hClose hnd
basenameOf = reverse . (takeWhile (/='/')) . reverse
hPutArEntryHeader hnd entry = do
hPutChars hnd 16 (fileName entry)
hPutChars hnd 12 (show (fileDate entry))
hPutChars hnd 6 (show (ownerID entry))
hPutChars hnd 6 (show (groupID entry))
hPutChars hnd 8 (showOct (fileMode entry) [])
hPutChars hnd 10 (show (fileSize entry))
hPutChar hnd '`'
hPutChar hnd '\n'
hPutChars hnd n str | length str <= n = hPutStr hnd (take n (str ++ repeat ' '))
hCopy :: Handle -> Handle -> IO ()
hCopy oh ih =
let blockSize = 1024 * 16 in
allocaBytes blockSize $ \buf -> do
let loop = do
bytes <- hGetBuf ih buf blockSize
hPutBuf oh buf bytes
when (bytes == blockSize) loop
loop