I’m writing some code in c++ that monitors the directory that ubuntu puts files received via bluetooth (~/Downloads). I’m using images as sample files, as the application is opening the images and displaying them.
The code polls the directory every 2 seconds and checks if there’s any files there. If there is, it immediately puts the file into a subdirectory, and loads it. However, it loads the file before the transfer is complete. It sees the file, moves the file, loads the file, and displays a broken image, all while still being transferred.
The subdirectory eventually contains the full image.
I tried using fcntl to lock the file but it locks successfully even while it’s still being written:
#ifndef WIN32
//We have to do a file lock on ubuntu...
/* l_type l_whence l_start l_len l_pid */
struct flock fl = {F_WRLCK, SEEK_SET, 0, 0, 0 };
int fd;
fl.l_pid = getpid();
if((fd = open(newFile.c_str(),O_RDWR)) == -1){
DODEBUG(ALWAYS,("LOCKING FAILED!"));
continue;
}
if (fcntl(fd, F_SETLKW, &fl) == -1) {
DODEBUG(ALWAYS,("LOCKING FAILED!"));
close(fd);
continue;
}
DODEBUG(ALWAYS,("GOT LOCK"));
fl.l_type = F_UNLCK; /* set to unlock same region */
if (fcntl(fd, F_SETLK, &fl) == -1) {
DODEBUG(ALWAYS,("UNLOCKING FAILED!"));
}
close(fd);
#endif
newFile = moveFile(newFile);
const std::string s(newFile);
loadImage(newFIle);
Note that the code I’m writing needs to work on windows and mac also. The windows version already works flawlessly, as the file is not accessible until it is fully received. I haven’t tried mac but I would assume it has the same issues as ubuntu.
A workaround to solve this problem is to maintain a list of structs with the file name and file size. Every time you check the dir get a list of the files, check them against your list, if a file isn’t on your list, add it. If a file is on your list compare the file sizes. If the file sizes are the same, then (assuming the transfer wasn’t interrupted) you know the transfer has completed.