def ds3_lock_readlckd(self, fstype): testdir = self.mkworkdir('d') self.mkfile("testit.bat", """\ d: %s c:\\lckreadl primary rem end """ % ("rem Internal share" if self.version == "FDPP kernel" else "c:\\share"), newline="\r\n") # compile sources self.mkexe_with_djgpp("lckreadl", r""" #include #include #include #include #include #include #include #include #define FNAME "FOO.DAT" #define FDATA "0123456789abc" #define FDAT2 "01234 89abc" #define ACCESS_DENIED 5 int main(int argc, char *argv[]) { int handle; int ret, rc; int primary = -1; if (argc < 2) { printf("FAIL: Missing argument (primary|secondary)\n"); return -2; } if (strcmp(argv[1], "primary") == 0) primary = 1; if (strcmp(argv[1], "secondary") == 0) primary = 0; if (primary < 0) { printf("FAIL: Invalid argument (primary|secondary)\n"); return -2; } if (primary) { unsigned int attr; if (_dos_creatnew(FNAME, 0, &handle) != 0) { printf("FAIL: %s: Couldn't create '%s'\n", argv[1], FNAME); return -1; } if (_dos_write(handle, FDATA, strlen(FDATA), &rc) != 0) { printf("FAIL: %s: Couldn't write to '%s'\n", argv[1], FNAME); _dos_close(handle); return -1; } if (_dos_close(handle) != 0) { printf("FAIL: %s: Couldn't close '%s'\n", argv[1], FNAME); return -1; } if (_dos_getfileattr(FNAME, &attr)) { printf("FAIL: %s: Couldn't getfileattr() for '%s'\n", argv[1], FNAME); return -1; } if (attr != _A_ARCH) { printf("FAIL: %s: Incorrect attrs on '%s'\n", argv[1], FNAME); printf(" Attrs are: (0x%02x)\n", attr); if (attr & _A_ARCH) printf(" Archive\n"); if (attr & _A_RDONLY) printf(" Read only\n"); if (attr & _A_HIDDEN) printf(" Hidden\n"); if (attr & _A_SYSTEM) printf(" System\n"); if (attr & _A_VOLID) printf(" Volume ID\n"); if (attr & _A_SUBDIR) printf(" Directory\n"); return -1; } ret = _dos_open(FNAME, O_RDONLY, &handle); if (ret != 0) { printf("FAIL: %s: Couldn't open '%s' (%d)\n", argv[1], FNAME, ret); return -1; } printf("OKAY: %s: Opened file '%s'\n", argv[1], FNAME); if (_dos_lock(handle, 5, 3) != 0) { // somewhere in the middle printf("FAIL: %s: Could not get lock\n", argv[1]); _dos_close(handle); return -1; } printf("OKAY: %s: 5,3 Acquired lock'\n", argv[1]); // Now start second copy spawnlp(P_WAIT, argv[0], argv[0], "secondary", NULL); _dos_unlock(handle, 5, 3); _dos_close(handle); } else { // secondary char buf[80]; ret = _dos_open(FNAME, O_RDONLY, &handle); if (ret != 0) { printf("FAIL: %s: Couldn't open file '%s' err=(%d)\n", argv[1], FNAME, ret); return -1; } printf("OKAY: %s: Opened file '%s'\n", argv[1], FNAME); // Check what was written by primary process // partially overlapping range prior to lock (should fail, but may succeed due to extension) memset(buf, ' ', strlen(FDATA)); ret = _dos_read(handle, buf, 6, &rc); if (ret == 0) { if (rc != 5) { printf("FAIL: %s: 0,6 overlap conflict(1) read by mistake cnt = %d\n", argv[1], rc); _dos_close(handle); return -1; } // Stas wants to allow this 'enhancement', so reset the file position printf("INFO: %s: 0,6 overlap conflict(1) partial read enhancement cnt = %d\n", argv[1], rc); if (llseek(handle, 0, SEEK_SET) != 0) { printf("FAIL: %s: Seek 0 failed\n", argv[1]); _dos_close(handle); return -1; } } else if (ret != ACCESS_DENIED) { printf("FAIL: %s: 0,6 overlap conflict(1) read return (err=%d != 5)\n", argv[1], ret); _dos_close(handle); return -1; } else { printf("OKAY: %s: 0,6 overlap conflict(1) read returned err=0x%02x, cnt=%d\n", argv[1], ret, rc); } // adjacent range prior to lock (should succeed) memset(buf, ' ', strlen(FDATA)); ret = _dos_read(handle, buf, 5, &rc); if (ret != 0) { printf("FAIL: %s: 0,5 adjacent range prior to lock not read back(1) err=0x%02x\n", argv[1], ret); _dos_close(handle); return -1; } else if (rc != 5) { printf("FAIL: %s: 0,5 adjacent range prior to lock num read back(1) incorrect(%d)\n", argv[1], rc); _dos_close(handle); return -1; } else { printf("OKAY: %s: 0,5 adjacent range prior to lock read returned err=0x%02x, cnt=%d\n", argv[1], ret, rc); } buf[strlen(FDATA)] = 0; if (strncmp(buf, FDATA, 5) != 0) { printf("FAIL: %s: Mismatch, expected first 5 chars of '%s', got '%s'\n", argv[1], FDATA, buf); _dos_close(handle); return -1; } // exact match conflict (should fail) ret = _dos_read(handle, buf + 5, 3 , &rc); if (ret == 0) { printf("FAIL: %s: 5,3 exact conflict read by mistake cnt = %d\n", argv[1], rc); _dos_close(handle); return -1; } else if (ret != ACCESS_DENIED) { printf("FAIL: %s: 5,3 exact conflict read return (err=%d != 5)\n", argv[1], ret); _dos_close(handle); return -1; } else { printf("OKAY: %s: 5,3 exact conflict read returned err=0x%02x, cnt=%d\n", argv[1], ret, rc); } // adjacent range after lock (read should succeed) if (llseek(handle, 8, SEEK_SET) != 8) { printf("FAIL: %s: Seek 8 failed\n", argv[1]); _dos_close(handle); return -1; } ret = _dos_read(handle, buf + 8, 5 , &rc); if (ret != 0) { printf("FAIL: %s: 8,5 adjacent range after lock not read back(2) err=0x%02x\n", argv[1], ret); _dos_close(handle); return -1; } else if (rc != 5) { printf("FAIL: %s: 8,5 adjacent range after lock num read back(2) incorrect(%d)\n", argv[1], rc); _dos_close(handle); return -1; } else { printf("OKAY: %s: 8,5 adjacent range after lock read returned err=0x%02x, cnt=%d\n", argv[1], ret, rc); } buf[strlen(FDAT2)] = 0; if (strcmp(buf, FDAT2) != 0) { printf("FAIL: %s: Mismatch, expected '%s', got '%s'\n", argv[1], FDAT2, buf); _dos_close(handle); return -1; } // partially overlapping range after lock (read should fail) if (llseek(handle, 7, SEEK_SET) != 7) { printf("FAIL: %s: Seek 7 failed\n", argv[1]); _dos_close(handle); return -1; } memset(buf, ' ', strlen(FDATA)); ret = _dos_read(handle, buf + 7, 6, &rc); if (ret == 0) { printf("FAIL: %s: 7,6 overlap conflict(2) read by mistake cnt = %d\n", argv[1], rc); _dos_close(handle); return -1; } else if (ret != ACCESS_DENIED) { printf("FAIL: %s: 7,6 overlap conflict(2) read return (err=%d != 5)\n", argv[1], ret); _dos_close(handle); return -1; } else { printf("OKAY: %s: 7,6 overlap conflict(2) read returned err=0x%02x, cnt=%d\n", argv[1], ret, rc); } printf("PASS: %s: all tests okay\n", argv[1]); _dos_close(handle); } return 0; } """) if fstype == "MFS": config="""\ $_hdimage = "dXXXXs/c:hdtype1 dXXXXs/d:hdtype1 +1" $_floppy_a = "" """ else: # FAT name = self.mkimage("12", cwd=testdir) config="""\ $_hdimage = "dXXXXs/c:hdtype1 %s +1" $_floppy_a = "" """ % name results = self.runDosemu("testit.bat", config=config) self.assertNotIn("FAIL:", results) self.assertIn("PASS:", results)