# fsize --- program to size file structures include LIBRARY_DEFS include PRIMOS_KEYS include PRIMOS_ERRD include ARGUMENT_DEFS ARG_DECL character path (MAXPATH) integer state (4), record_size integer gfnarg, equal, gtrcsz longint size longint fsize$ PARSE_COMMAND_LINE ("vfrwn"s, "Usage: fsize [-{f|r|v|w}] { }"s) if (ARG_PRESENT (r) && ARG_PRESENT (w)) call error ("-r and -w are mutually exclusive."s) state (1) = 1 while (gfnarg (path, state) ~= EOF) { if (equal (path, "/dev/stdin1"s) == YES) path (1) = EOS # case for no args, default to current dir record_size = gtrcsz (path) if (record_size == ERR) call print (ERROUT, "*s: can't get record size*n"s, path) else { size = fsize$ (path, ARG_PRESENT (f), record_size) if (size == ERR) call print (ERROUT, "*s: can't determine size*n"s, path) else { if (ARG_PRESENT (w)) # default to size in records size *= record_size call print (STDOUT, "*6l"s, size) if (ARG_PRESENT (v)) call print (STDOUT, " | *s"s, path) call print (STDOUT, "*n"s) } } } stop end # fsize$ --- return the size of any file system structure longint function fsize$ (path, force, record_size) character path (MAXPATH) bool force integer record_size define (MAX_LEVEL,128) # maximum nesting level for tscan$ define (BIG_VALUE,:17777777777) define (READPROT,:100000000) # SATR$$: set r/ protection define (MULTREAD,:400000) # SATR$$: set n+1 read/write lock integer code, code2, fd, junk, level, type integer entry (MAXDIRENTRY), fname (16), passwd (3) integer getto, tscan$ bool nameqv longint size longint szfil$ procedure freak forward procedure accumulate forward procedure force_open forward ### See if this is a valid pathname: if (getto (path, fname, passwd, junk) == ERR) freak ### First, we see what type of beastie we're dealing with. ### If it's in use or not readable then we have to do awful ### things to try and force it open. size = 0 if (path (1) == EOS) call srch$$ (KREAD + KGETU, KCURR, 0, fd, type, code) else { call srch$$ (KREAD + KGETU, fname, 32, fd, type, code) if (force && (code == EFIUS || code == ENRIT)) { # in use/unreadable? call srch$$ (KREAD + KGETU, KCURR, 0, fd, type, junk) call rden$$ (KNAME, fd, entry, MAXDIRENTRY, junk, fname, 32, code2) call srch$$ (KCLOS, 0, 0, fd, 0, junk) if (code2 == 0) force_open } } if (code ~= 0) freak else accumulate if (type ~= 4) { # if not a directory call follow (EOS, 0) return (size) } if (path (1) ~= EOS) { call at$swt (fname, 32, 0, passwd, KICUR, code) if (code ~= 0) { call follow (EOS, 0) call print (ERROUT, "*s: can't size directory contents*n"s, path) return (size) } } level = 0 repeat select (tscan$ (path, entry, level, MAX_LEVEL, PREORDER)) when (ERR) call print (ERROUT, "*s: can't size directory contents*n"s, path) when (OK) { if (and (entry (20), 8r10000) ~= 0 && nameqv (entry (2), "MFD ")) next # we have already sized the MFD call srch$$ (KREAD + KGETU, entry (2), 32, fd, type, code) if (force && (code == EFIUS || code == ENRIT)) force_open if (code ~= 0) call print (ERROUT, "*s: can't determine size*n"s, path) else accumulate } when (EOF) { call follow (EOS, 0) return (size) } # freak --- clean up and return with error status procedure freak { call srch$$ (KCLOS, 0, 0, fd, 0, junk) call follow (EOS, 0) return (ERR) } # force_open --- try to force-open a file procedure force_open { local changes integer changes changes = 0 # indicate no changes made call break$ (DISABLE) repeat { select (code) when (ENRIT) { # failed because of insufficient rights call satr$$ (KPROT, entry (2), 32, READPROT, code) if (code ~= 0) break changes |= 1 # indicate we changed the protection } when (EFIUS) { call satr$$ (KRWLK, entry (2), 32, MULTREAD, code) if (code ~= 0) break changes |= 2 # indecate we changed the read/write lock } else break call srch$$ (KREAD + KGETU, entry (2), 32, fd, type, code) } if (and (changes, 1) ~= 0) { # need to reset protection entry (19) = 0 call satr$$ (KPROT, entry (2), 32, entry (18), junk) } if (and (changes, 2) ~= 0) { # need to reset read/write lock entry (21) = 0 entry (20) = rs (and (entry (20), 8r6000), 10) call satr$$ (KRWLK, entry (2), 32, entry (20), junk) } call break$ (ENABLE) } # accumulate --- add size of current file to total procedure accumulate { local temp longint temp select (type) when (0, 1) # SAM or DAM file temp = szfil$ (fd, type, record_size) when (2, 3) # SAM or DAM segment directory call szseg$ (temp, fd, type, record_size) when (4) { call rden$$ (KUPOS, fd, 0, 0, 0, BIG_VALUE, 0, code) call rden$$ (KGPOS, fd, 0, 0, 0, temp, 0, code) if (code ~= 0) temp = ERR else temp = (temp + record_size - 1) / record_size } if (temp == ERR) freak else size += temp call srch$$ (KCLOS, 0, 0, fd, 0, code) } end # szfil$ --- find number of records in a file longint function szfil$ (fd, type, record_size) integer fd, type, record_size integer code, junk longint size repeat call prwf$$ (KPOSN + KPRER, fd, loc (0), 0, BIG_VALUE, junk, code) until (code ~= 0) if (code ~= EEOF) # encountered some error besides EOF return (ERR) call prwf$$ (KRPOS, fd, loc (0), 0, size, junk, code) size = (size + record_size - 1) / record_size if (size == 0) # every file has at least one data record size = 1 if (type == 1) # DAM file; include index records size += 1 + (2 * size - 1) / record_size return (size) end # szseg$ --- find number of records in a segment directory subroutine szseg$ (size, fd, type, record_size) longint size integer fd, type, record_size integer entry_a, entry_b, nfd, ntype, code longint temp longint szfil$ size = ERR call sgdr$$ (KGOND, fd, entry_a, entry_b, code) call sgdr$$ (KSPOS, fd, 0, entry_a, code) if (code ~= 0) return if (entry_b == 0) size = 1 else size = (entry_b + record_size - 1) / record_size if (type == 3) # DAM segment directory; include index records size += 1 + (2 * entry_b - 1 ) / record_size ### now size the contents of the segment directory: entry_b = -1 repeat { entry_a = entry_b + 1 call sgdr$$ (KFULL, fd, entry_a, entry_b, code) if (entry_b == -1 || code ~= 0) break call srch$$ (KREAD + KGETU + KISEG, fd, 0, nfd, ntype, code) if (code ~= 0) { size = ERR return } select (ntype) when (0, 1) # SAM or DAM file temp = szfil$ (nfd, ntype, record_size) when (2, 3) # SAM or DAM segment directory call szseg$ (temp, nfd, ntype, record_size) if (temp == ERR) { size = ERR return } else size += temp call srch$$ (KCLOS, 0, 0, nfd, 0, code) } return end # gtrcsz --- find the record size of the device containing path integer function gtrcsz (path) character path (ARB) integer code, fd, junk, nwr, entry (24), fname (16), passwd (3) integer getto ### open the MFD of the disk containing path: if (getto (path, fname, passwd, junk) == ERR) return (ERR) call at$swt ("MFD", 3, KCURR, "XXXXXX", KIMFD, code) if (code ~= 0) return (ERR) call srch$$ (KREAD + KGETU, KCURR, 0, fd, junk, code) if (code ~= 0) return (ERR) ### read the entry for the disk record availability table: call rden$$ (KREAD, fd, entry, MAXDIRENTRY, nwr, 0, 0, code) call srch$$ (KCLOS, 0, 0, fd, 0, junk) if (code ~= 0 || nwr < 20) return (ERR) nwr = 440 # start by assuming a standard disk if (entry (20) < 0) # msb of type word is set on storage modules nwr = 1024 call follow (EOS, 0) return (nwr) end