- /** Implements the F_GETLK and F_SETLK cases of fcntl syscall.
- * If l_start = 0 and l_len = 0 the lock refers to the entire file.
- struct flock {
- short l_type; // lock type: F_UNLCK, F_RDLCK, F_WRLCK
- short l_whence; // type of l_start: SEEK_SET, SEEK_CUR, SEEK_END
- long l_start; // starting offset, bytes
- long l_len; // len = 0 means until EOF
- short l_pid; // lock owner
- short l_xxx; // padding
- };
- */
- private int sys_fcntl_lock(FD fd, int cmd, int arg)
- throws FaultException, IOException {
- if (arg == 0) { System.out.println("BAD ARG"); return -EINVAL; }
- int word = memRead(arg);
- int l_start = memRead(arg+4);
- int l_len = memRead(arg+8);
- int l_type = word>>16;
- int l_whence = word&0x00ff;
-
- Seekable s = fd.seekable();
- if (s == null) return -EINVAL;
-
- switch (l_whence) {
- case SEEK_SET: break;
- case SEEK_CUR: l_start += s.pos(); break;
- case SEEK_END: l_start += s.length(); break;
- default: return -1;
- }
-
- if (cmd != F_GETLK && cmd != F_SETLK) return -EINVAL;
-
- if (cmd == F_GETLK) {
- // Check if an l_type lock can be aquired. The only way to
- // do this within the Java API is to try and create a lock.
- Seekable.Lock lock = s.lock(l_start, l_len, l_type == F_RDLCK);
-
- if (lock != null) {
- // no lock exists
- memWrite(arg, SEEK_SET|(F_UNLCK<<16));
- lock.release();
- }
-
- return 0;
- }
-
- // now processing F_SETLK
- if (cmd != F_SETLK) return -EINVAL;
-
- if (l_type == F_UNLCK) {
- // release all locks that fall within the boundaries given
- for (int i=0; i < LOCK_MAX; i++) {
- if (locks[i] == null || !s.equals(locks[i].seekable()))
- continue;
-
- int pos = (int)locks[i].position();
- if (pos < l_start) continue;
- if (l_start != 0 && l_len != 0) // start/len 0 means unlock all
- if (pos + locks[i].size() > l_start + l_len)
- continue;
-
- locks[i].release();
- locks[i] = null;
- }
- return 0;
-
- } else if (l_type == F_RDLCK || l_type == F_WRLCK) {
- // first see if a lock already exists
- for (int i=0; i < LOCK_MAX; i++) {
- if (locks[i] == null || !s.equals(locks[i].seekable()))
- continue;
- int pos = (int)locks[i].position();
- int size = (int)locks[i].size();
- if (l_start < pos && pos + size < l_start + l_len) {
- // found a lock contained in the new requested lock
- locks[i].release();
- locks[i] = null;
-
- } else if (l_start >= pos && pos + size >= l_start + l_len) {
- // found a lock that contains the requested lock
- if (locks[i].isShared() == (l_type == F_RDLCK)) {
- memWrite(arg+4, pos);
- memWrite(arg+8, size);
- return 0;
- } else {
- locks[i].release();
- locks[i] = null;
- }
- }
- }
-
- // create the lock
- Seekable.Lock lock = s.lock(l_start, l_len, l_type == F_RDLCK);
- if (lock == null) return -EAGAIN;
-
- int i;
- for (i=0; i < LOCK_MAX; i++)
- if (locks[i] == null) break;
- if (i == LOCK_MAX) return -ENOLCK;
- locks[i] = lock;
- return 0;
-
- } else {
- return -EINVAL;
- }
- }
-
-