Fuser

fuser is a tool that will try and find out which program is using/locking a file.

Script
 /* fuser.cmd - finds user(s) of an open file

D C Saville September 2003 dave@deezee.org

Have you ever tried to do something to a file only to get a message saying "File in use by another programme"?

Fine but *which* programme.

fuser will try and find out. Sometimes it can't, in which case you will get no output, but often it will find who or what has the file open.



Parse Upper Arg file '¬' rest

If file = "" Then Do Say "Usage: fuser " Exit End

file = Translate(file, "\", "/") /* just in case the file has forward slashes */

psfiles_q = RxQueue( "create" ) pstat_q = RxQueue( "create" ) OldQueue = RxQueue( "set", psfiles_q ) "@psfiles | RXQUEUE" psfiles_q

Do Queued Parse Pull pid Hdl SFN refs flags mode size hvpb attr file_name

If Pos(file, file_name) > 0 Then Do   Say "pid  Hdl  SFN  refs flags    mode     size     hvpb attr name" Say pid Hdl SFN refs flags mode size hvpb attr file_name FILE_NORMAL   = X2B("0000") FILE_READONLY = X2B("0001") FILE_HIDDEN   = X2B("0002") FILE_SYSTEM   = X2B("0004") FILE_DIRECTORY = X2B("0010") FILE_ARCHIVED = X2B("0020") File_attr = "File attr: " attr = X2B(attr)

If BitAnd(attr, FILE_READONLY) = FILE_READONLY Then File_attr = File_attr||"Read_Only " If BitAnd(attr, FILE_HIDDEN) = FILE_HIDDEN Then File_attr = File_attr||"Hidden " If BitAnd(attr, FILE_SYSTEM) = FILE_SYSTEM Then File_attr = File_attr||"System " If BitAnd(attr, FILE_DIRECTORY) = FILE_DIRECTORY Then File_attr = File_attr||"Directory " If BitAnd(attr, FILE_ARCHIVED) = FILE_ARCHIVED Then File_attr = File_attr||"Archived " Say file_attr

OPEN_FLAGS_NOINHERIT    = X2B("00000080") OPEN_FLAGS_NO_LOCALITY  = X2B("00000000") OPEN_FLAGS_NO_SEQUENTIAL = X2B("00000100") OPEN_FLAGS_NO_RANDOM    = X2B("00000200") OPEN_FLAGS_NO_RANDOMSEQUENTIAL = X2B("00000200") OPEN_FLAGS_NOCACHE      = X2B("00001000") OPEN_FLAGS_FAIL_ON_ERROR = X2B("00002000") OPEN_FLAGS_WRITE_THROUGH = X2B("00004000") OPEN_FLAGS_DASD         = X2B("00008000") OPEN_FLAGS_NONSPOOLED   = X2B("00040000") OPEN_FLAGS_PROTECTED_HANDLE = X2B("40000000")

OPEN_SHARE_DENYLEGACY   = X2B("10000000") OPEN_SHARE_DENYREADWRITE = X2B("00000010") OPEN_SHARE_DENYWRITE    = X2B("00000020") OPEN_SHARE_DENYREAD     = X2B("00000030") OPEN_SHARE_DENYNONE     = X2B("00000040")

OPEN_ACCESS_READONLY    = X2B("00000000") OPEN_ACCESS_WRITEONLY   = X2B("00000001") OPEN_ACCESS_READWRITE   = X2B("00000002")

file_mode = "File mode: " mode = X2B(mode)

If BitAnd(mode, OPEN_FLAGS_NOINHERIT) = OPEN_FLAGS_NOINHERIT Then file_mode = file_mode||"private. " Else file_mode = file_mode||"inherited from DosExecPgm. "

file_mode = file_mode||"Share: "

If BitAnd(mode, OPEN_SHARE_DENYNONE) = OPEN_SHARE_DENYNONE Then file_mode = file_mode||"deny none. "

If BitAnd(mode, OPEN_SHARE_DENYREAD) = OPEN_SHARE_DENYREAD Then file_mode = file_mode||"deny read. " Else Do

If BitAnd(mode, OPEN_SHARE_DENYWRITE) = OPEN_SHARE_DENYWRITE Then file_mode = file_mode||"deny write. "

If BitAnd(mode, OPEN_SHARE_DENYREADWRITE) = OPEN_SHARE_DENYREADWRITE Then file_mode = file_mode||"deny read & write " End file_mode = file_mode||"Opened for: "

If BitAnd(mode, OPEN_ACCESS_READWRITE) = OPEN_ACCESS_READWRITE Then file_mode = file_mode||"read & write. " If BitAnd(mode, OPEN_ACCESS_WRITEONLY) = OPEN_ACCESS_WRITEONLY Then file_mode = file_mode||"write only. "

If BitAnd(mode, BitOr(OPEN_ACCESS_WRITEONLY, OPEN_ACCESS_READWRITE)) = OPEN_ACCESS_READONLY Then file_mode = file_mode||"read only. " If BitAnd(mode, OPEN_FLAGS_WRITE_THROUGH) = OPEN_FLAGS_WRITE_THROUGH Then file_mode = file_mode||"synchronous. "

Say file_mode

If pid <> 0 Then Do     Call RxQueue "set", pstat_q

"@pstat /P:"||pid||" | RXQUEUE" pstat_q

Do Queued Parse Pull stuff If Translate(SubStr(stuff, 1, 4)) = Translate(pid) Then Do         p1 = Pos(":", stuff) p2 = Pos(" ", SubStr(stuff, p1 + 1)) /*prog_name = Strip(SubStr(stuff, p1 - 1, p2 + 1))*/

Say "Program: "||word(stuff, 4) End End

Call RxQueue "set", psfiles_q /* restore pfiles queue */ End Else Say "Program: System, DLL or Zombie" Say End End

CALL RxQueue "Delete", pstat_q /* don't need our queue anymore */ CALL RxQueue "Delete", psfiles_q /* don't need our queue anymore */ CALL RxQueue "Set", OldQueue  /* restore old queue */

