Is there a way for me to tell if a particular file is open in another application?
I have a feature I'd like to provide before opening a file in my application, i want to know whether the file is already opened or not.
I want to put the functionality that if its already opened in another application then my application restrict the file to open it again to save the loss of information.
thanks in advance...
There is file locking for this kind of tasks:
http://linux.die.net/man/2/flock
On Linux, you can use "lsof" to see if the file is open.
http://linux.about.com/library/cmd/blcmdl8_lsof.htm
You must have implemented some solution by now but, the way i understand your design, I suggest against your it.
You should allow the user to open the file and check the for time stamps to find out if its been modified before allowing user to save the file (may be ask user whether to overwrite the file or save it as new file etc.).
Look at stat() API.
-Before you open the file note down the timestamp (st_mtime, see structure below)
-Let users modify the file.
-Before user saves the file check the timestamp of the file again st_mtime and if it differs then ask questions to the user.
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
Related
I have to look at PCAPs that are quite large, around 40GB. What I'm doing right now is using PCAP++ to parse the PCAPs one at a time and process the data inside them. That data is placed into a buffer for it to be viewed. To save memory, I throw out the old data as you continue through the PCAP. This allows me to only use about 150MBs at a time. However, if the user wants to go back and view the data too far back, they can't because it's been thrown out.
Is there any way I can look at the PCAP file and go to the packets in which the data was stored and reprocess the data if the user wants to look back? It seems that if I want to get certain packets I would have to reload the file and look through it all again for each and every single section of data or split up the pcap file into a ton of bite size chunks.
So I figured it out and short answer is no. PCAP++ doesn't support any functionality that could index, or mimic indexing, on a pcap file. I switched back to libpcap, (this also should work in windows with winpcap but I haven't tested it yet) in order to use a different library to help sort out what needed to be done. To do this properly you need to use file pointers that point to the critical packets (or all packets, depending on what you want) in your pcap file. Here's how it works:
#ifdef _MSC_VER
pcap_t *pcap = pcap_open_offline((pcapPath.string()).c_str(), errbuf);
#else
pcap_t *pcap = pcap_open_offline(pcapPath.c_str(), errbuf);
#endif
//-----------------------------
//... General Packet setup ...
//-----------------------------
vector<fpos_t*> pcapIndexer;
while(/*Get Next Packet*/){
//Parse the packet and get required flag
//to know if it is a critical packet
if(/*Check some condition from the data*/){
fpos_t* position;
#ifdef _MSC_VER
pcap_fgetpos(pcap, position);
#else
FILE* f = pcap_file(pcap);
fgetpos(f, position);
#endif
pcapIndexer.push_back(position);
}
}
From the above code, you would go through each packet and depending on the data in the packet, you would add that file pointer to the vector of file pointers. Then once you need to load a packet, you create a new pcap_t pointer and use this:
#ifdef _MSC_VER
pcap_fsetpos(pcap, pcapIndexer[x]);
#else
FILE* f = pcap_file(pcap);
fsetpos(f, pcapIndexer[x]);
#endif
You can then read as normal from that point. Note that you will have to run through the entire pcap file in order to fill out this vector of file pointers however if you use multi threading you can use some of the data that is in the earlier packets while the rest of the pcap file is being read through and added to the vector. This allows you to load in a select amount of data and then be able to jump back and forth to grab data from elsewhere in the pcap file. I hope this helps someone else in this situation.
I have the details of the mount path (specifically mount prefix) as obtained using getmntent
in the structure as defined below:
struct mntent {
char *mnt_fsname; /* name of mounted file system */
char *mnt_dir; /* file system path prefix */
char *mnt_type; /* mount type (see mntent.h) */
char *mnt_opts; /* mount options (see mntent.h) */
int mnt_freq; /* dump frequency in days */
int mnt_passno; /* pass number on parallel fsck */
};
Using mnt_dir I want to check if the mount path is still mounted after a while as it is possible that before some processing is done on it, it might have been unmounted.
What is the most efficient way to check if the path is still mounted?
Also Is there a way to get callback in case the path gets unmounted?
I'd say that the most efficient way is to cache st_dev and st_ino returned by stat() (although probably caching just st_dev should be enough).
If the volume gets unmounted, the mount point reverts to the empty subdirectory in the parent filesystem where the volume was originally mounted, and stat() will return a different device+inode, for the same file path.
As far as being notified, poke around the inotify(7) interface, paying attention to the IN_UNMOUNT event.
When Using Windows I can get a (more or less unique) serial number of a HDD partition by using command
GetVolumeInformation()
My question: is there something similar available for Linux? Means a number that would change only when somebody formats a partition and that can be retrieved programmatically?
Thanks!
In linux, you could use the blkid command to get the UUID of the partition:
# blkid /dev/sda1
/dev/sda1: UUID="15677362-cef3-4a53-aca3-3bace1b0d92a" TYPE="ext4"
This info is stored in the formatting of specific partition types like ext4, xfs and changes when reformatted. There is no info available for unformatted partitions.
If you need to call it from code, calling out to a shell to run this command isn't exactly the prettiest way to do it, but it could work:
#include <stdio.h>
int main(int argc,char ** argv) {
/* device you are looking for */
char device[]="/dev/sda1";
/* buffer to hold info */
char buffer[1024];
/* format into a single command to be run */
sprintf(buffer,"/sbin/blkid -o value %s",device);
/* run the command via popen */
FILE *f=popen(buffer,"r");
/* probably should check to make sure f!=null */
/* read the first line of output */
fgets(buffer,sizeof(buffer),f);
/* print the results (note, newline is included in string) */
fprintf(stdout,"uuid is %s",buffer);
}
You can use udev to get the serial number of the device. (You'll need to know the device name though)
struct udev *context = udev_new();
struct udev_device *device = udev_device_new_from_syspath(context, "/sys/block/sda");
const char *id = udev_device_get_property_value(device, "ID_SERIAL");
// Cleanup
udev_device_unref(device);
udev_unref(context);
Partitions have (at least) three identities in linux:
The raw device identifier (think cat /proc/partitions) - this is not a unique serial number
The UUID of the partition - can be found with blkid, and stored within the partition itself. You can also manually parse /dev/.blkid.tab - the format being obvious.
The disk label - also stored within the partition. EG:
lsblk -o name,mountpoint,label,uuid
NAME MOUNTPOINT LABEL UUID
sda
├─sda1 / 315eaf50-adcc-4f0d-b767-f008f3f1c194
├─sda2
└─sda5 [SWAP] 1ff31705-f488-44a4-ba5f-e2fe9eff4b96
sr0
Of these, the second is closest to what you want. To read it programatically, use libblkid.
I'm trying to monitor a directory using ReadDirectoryChangesW. Whenever a new file is added to the directory I monitor the application should print it's name. The application works fine if I copy one file at a time, but if I try,lets say 2 files at a time, it recognize only one of them.
I'm using this function synchronously.
Here is the code:
The handle to the directory:
HANDLE hDir = CreateFile(
"d:\\Detect", /* pointer to the file name */
FILE_LIST_DIRECTORY, /* access (read-write) mode */
FILE_SHARE_READ|FILE_SHARE_DELETE, /* share mode */
NULL, /* security descriptor */
OPEN_EXISTING, /* how to create */
FILE_FLAG_BACKUP_SEMANTICS, /* file attributes */
NULL /* file with attributes to copy */
);
And ReadDirectoryChangesW:
ReadDirectoryChangesW(hDir,&Buffer,sizeof(Buffer),FALSE,
FILE_NOTIFY_CHANGE_SECURITY|
FILE_NOTIFY_CHANGE_CREATION|
FILE_NOTIFY_CHANGE_LAST_ACCESS|
FILE_NOTIFY_CHANGE_LAST_WRITE|
FILE_NOTIFY_CHANGE_SIZE|
FILE_NOTIFY_CHANGE_ATTRIBUTES|
FILE_NOTIFY_CHANGE_DIR_NAME|
FILE_NOTIFY_CHANGE_FILE_NAME,&bytesReturned,NULL,NULL);
I am looking at I/O operations in C++ and I have a question.
When opening a file like:
#include <fcntl.h>
int main() {
unsigned char buffer[16];
int fd = open (argv[1], O_RDONLY);
read(fd, buffer, sizeof(buffer));
return 0;
}
How can the variable fd represent a file as an integer when passing it to the open method? Is it repesenting a file in current folder? If I print the ´fd´variable, it prints 3. What does that mean?
Ps. I know there are several other ways to handle files, like stdio.h, fstream etc but that is out of the scope of this question. Ds.
How can the variable fd represent a file as an integer when passing it to the open method?
It's a handle that identifies the open file; it's generally called a file descriptor, hence the name fd.
When you open the file, the operating system creates some resources that are needed to access it. These are stored in some kind of data structure (perhaps a simple array) that uses an integer as a key; the call to open returns that integer so that when you pass it read, the operating system can use it to find the resources it needs.
Is it repesenting a file in current folder?
It's representing the file that you opened; its filename was argv[1], the first of the arguments that was passed to the program when it was launched. If that file doesn't exist, or open failed for some reason, then it has the value -1 and doesn't represent any file; you really should check for that before you try to do anything with it.
If I print the fd variable, it prints 3. What does that mean?
It doesn't have any particular meaning; but it has that value because it was the fourth file (or file-like thing) that was opened, after the input (0), output (1) and error (2) streams that are used by cin, cout and cerr in C++.
Because that is the index of the table of resources stored for your current process.
Each process has it own resources table, so you just need to pass the index to read/write/etc function
Generally, a file descriptor is an index for an entry in a kernel-resident data structure containing the details of all open files. In POSIX this data structure is called a file descriptor table, and each process has its own file descriptor table. The user application passes the abstract key to the kernel through a system call, and the kernel will access the file on behalf of the application, based on the key. The application itself cannot read or write the file descriptor table directly.
from: http://en.wikipedia.org/wiki/File_descriptor
open() returns the file descriptor of the file which is the C type int. To know more about File Descriptor refer http://en.wikipedia.org/wiki/File_descriptor.
"fd" stands for file descriptor. It is a value identifying a file. It is often an index (in the global table), an offset, or a pointer. Different APIs use different types. WinAPI, for example, uses different types of handles (HANDLE, HGDI, etc.), which are essentially typedefs for int/void*/long, and so on.
Using naked types like "int" is usually not a good idea, but if the implementation tells you to do so (like POSIX in this case), you should keep it.
The simplified answer is that fd is just an index into some array of file descriptors.
When most processes are started, they are given three open file descriptors to begin with: stdin (0), stdout (1), and stderr (2). So when you open your first file, the next available array entry is 3.