#include "memory.h"

  typedef struct {
	  struct Node Node;
	  ULONG LockCount;
  }
LockNode_t;

BOOL __saveds __asm LockFile(register __a0 PagerHandle_t * ph, register __a1 STRPTR fileName)
{
	STRPTR ptr;
	LockNode_t *node, *n;

	ptr = FilePart(fileName);

	if (node = MyAllocVec(sizeof(LockNode_t) + strlen(ptr) + 16)) {
		node->Node.ln_Name = (char *)&node[1];

		strcpy(node->Node.ln_Name, ptr);
		strcat(node->Node.ln_Name, ".LOCK");

		ObtainSemaphore(&ph->ph_Sema);

		for (n = (LockNode_t *) ph->ph_LockList.lh_Head;
		     n->Node.ln_Succ;
		     n = (LockNode_t *) n->Node.ln_Succ)
			if (stricmp(node->Node.ln_Name, n->Node.ln_Name) == 0) {
				n->LockCount++;
				MyFreeVec(node);
				ReleaseSemaphore(&ph->ph_Sema);
				return TRUE;
			}

		if (ptr = LockDevUnit(node->Node.ln_Name, 0, ph->ph_LogProgram, 0)) {
			ULog(ph, -1, "LockDevUnit() failed: %s", ptr);
		}

		node->LockCount = 1;
		AddTail(&ph->ph_LockList, &node->Node);

		ReleaseSemaphore(&ph->ph_Sema);

		return TRUE;
	}

	ReleaseSemaphore(&ph->ph_Sema);

	return FALSE;
}

static void __inline FreeLockNode(LockNode_t * node)
{
	Remove(&node->Node);

	FreeDevUnit(node->Node.ln_Name, 0);

	MyFreeVec(node);
}

void __saveds __asm UnLockFile(register __a0 PagerHandle_t * ph, register __a1 STRPTR fileName)
{
	STRPTR ptr;
	int ptrLen;
	LockNode_t *n;

	ptr = FilePart(fileName);
	ptrLen = strlen(ptr);

	ObtainSemaphore(&ph->ph_Sema);

	for (n = (LockNode_t *) ph->ph_LockList.lh_Head;
	     n->Node.ln_Succ;
	     n = (LockNode_t *) n->Node.ln_Succ)
		if ((strnicmp(ptr, n->Node.ln_Name, ptrLen) == 0) && (strcmp(".LOCK", &n->Node.ln_Name[ptrLen]) == 0)) {
			if (--n->LockCount == 0)
				FreeLockNode(n);

			break;
		}

	ReleaseSemaphore(&ph->ph_Sema);
}

void __saveds __asm UnLockFiles(register __a0 PagerHandle_t * ph)
{
	LockNode_t *n;

	ObtainSemaphore(&ph->ph_Sema);

	while ((n = (LockNode_t *) ph->ph_LockList.lh_Head) != (LockNode_t *) & ph->ph_LockList.lh_Tail)
		FreeLockNode(n);

	ReleaseSemaphore(&ph->ph_Sema);
}
