PDA

View Full Version : Restrict user to open the same file



vermarajeev
16th May 2007, 12:27
Hi all,
How can I restrict a user to open the same file on multiple instances of the same application???? If you have word installed, then open multiple instances of it and try opening the same file on all the application...The user is restricted. How can I achieve this???

Thanks

wysota
16th May 2007, 12:38
It's called mandatory locking. AFAIK Windows uses it by default. It's not advised though. You can also use advisory locks. For example see "man 2 flock" or simmilar.

vermarajeev
16th May 2007, 14:16
It's called mandatory locking. AFAIK Windows uses it by default. It's not advised though. You can also use advisory locks. For example see "man 2 flock" or simmilar.

Hi wysota,
Thanks for your reply.

I am working on an application where I can open multiple instances of same aplication (Qt). Presently the user is able to open the same file in any instances. The files are in text format. Can you provide me with some resources or something that can help me.

The solution should be portable.
Waiting eagerly

marcel
16th May 2007, 14:21
Try searching MSDN.

wysota
16th May 2007, 14:33
Or use flock() or lockf().

marcel
16th May 2007, 14:43
Or use flock() or lockf().
These are perfect as long as you don't use them on samba shares ( possibly other types of shares ).

vermarajeev
16th May 2007, 15:09
Or use flock() or lockf().

wysota-->
Does flock works on windows??? I'm googling but just get links telling flock on linux...etc etc

marcel-->msdn doesnt show me anything related to file locking. It shows stuffs related to locking buffers, locking controls etc etc

Thanks

marcel
16th May 2007, 15:15
http://msdn2.microsoft.com/en-us/library/8w5bsb4f(VS.80).aspx

wysota
16th May 2007, 17:44
These are perfect as long as you don't use them on samba shares ( possibly other types of shares ).

This is in general true for all locks, not only the ones mentioned here. Locks should in general be avoided if it's possible.

vermarajeev
18th May 2007, 04:26
http://msdn2.microsoft.com/en-us/library/8w5bsb4f(VS.80).aspx

Hi Marcel,
The link only uses FILE* to lock and unlock the file. Is there a way by which I can use fstream or ifstream to lock a file. I read some basics to know what is locking about and have basic idea now. I tried out the solution but is not useful to me. My application uses ifstream to open and read the file. Since the application is developed using Qt, I'm looking for a portable solution.

Wysota-->
I too tried flock() and lockf(), and came to the conclusion that it works only on linux....Can you suggest some solution which runs both on windows and linux.

By the way dont QFile or QIODevice provide functionality to lock and unlock the files...Or isnt there any means I can use Qt to do that stuff.

Thanks

marcel
18th May 2007, 05:25
You cannot do that with Qt and there is no portable solution. If you want something portable, do it yourself, using platform dependent API.

I have recently done something similar at work, but unfortunately I also needed to lock files on samba shares, therefore the platform API functions were of no use ( on Mac and Win ) and I did a custom locking mechanism.

If you only need to lock local files, go ahead and use system API.
It is not necessary to have #ifdef's all over your app, just where you implement the functionality - for example the function(s) will be called the same and will take the same number of params both on Win and Linux.

Regards

wysota
18th May 2007, 09:46
You can get a FILE* from a C++ stream, you know... And then both flock and _lock_file will work.

vermarajeev
18th May 2007, 10:51
You can get a FILE* from a C++ stream, you know... And then both flock and _lock_file will work.

While just implementing locking mechanism, I got one more idea.

Since the locking is to be restricted for the same application I can (I think)achieve this simply by associating an integer variable for each opened file, or just one array(or other appropiate data structure) for all opened files. for this I can make use of QStringList. If the same file is opened twice check in QStringList to see if file already present if so display some message to user "File already opened" if not open the file.

Will it not be feasible to implement the above said logic.
Thanks

wysota
18th May 2007, 10:53
What if one of the instances of the application crashes?

vermarajeev
18th May 2007, 11:38
What if one of the instances of the application crashes?

Crashes :crying: When??? I think it can happen only while loading the file. If it crashes my program closes that application. The previous instance remains as it is....

wysota
18th May 2007, 18:22
Crashes = gets killed

If you kill the application before releasing the pseudolock, you won't be able to open the same file again. You have to have some safetly mechanism to prevent that.

vermarajeev
21st May 2007, 04:00
Crashes = gets killed

If you kill the application before releasing the pseudolock, you won't be able to open the same file again.

Ok, so it can be dangerous. What do you mean when you talk pseudolock???

You have to have some safetly mechanism to prevent that
Can I provide some safety mechanism using the above specified solution by me???

The solution I'm looking should be portable and as per my searching I didnt get any. I came across semaphores too but found that it works for linux.

As Marcel says, I need to use some system dependent API's... What API's????

I'll try out the solution and let you know the status....

Thanks

wysota
21st May 2007, 08:04
What do you mean when you talk pseudolock???
Well, the mechanism you describe doesn't do any locking, so I called it a pseudolock.


Can I provide some safety mechanism using the above specified solution by me???
If you can get some process identifier on Windows then yes. Store the PID along the filename which the particular process handles in your lock data and then when you want to open the same file check if a process with this identifier exists. If not, it means that the entry is stale and can be removed.


The solution I'm looking should be portable and as per my searching I didnt get any. I came across semaphores too but found that it works for linux.
You can use different mechanisms on different platforms.


What API's????

http://en.wikipedia.org/wiki/API

vermarajeev
21st May 2007, 13:31
You can get a FILE* from a C++ stream, you know... And then both flock and _lock_file will work.

How to convert C++ stream to FILE*......:(

wysota
21st May 2007, 14:14
You'll have to search through available documentation of ostream probably. There should be a way to access the buffer which you can then associate with a file descriptor or file handler or whatever.

vermarajeev
22nd May 2007, 07:24
You'll have to search through available documentation of ostream probably. There should be a way to access the buffer which you can then associate with a file descriptor or file handler or whatever.

So far so good.
I have written a sample to lock a file on windows. On linux there are some problems. Please help me to make the below code work on linux too.


int main ( )
{
FILE *pFile = NULL;
char *fileName = "Logfile.log";

// Open the file in write mode
#ifdef win32
fopen_s(&pFile, fileName ,"r");
#else
pFile = fopen( fileName ,"r");

if (!pFile)
{
printf("Error opening file %s!\n", fileName);
exit(1);
}

// Lock the file.
#ifdef win32
_lock_file(pFile);
#else
//lock file on linux

printf("Locking the file %s.\n", fileName);

ifstream ifs( pFile ); //This doesnt work on linux why???
char line[255];
ifs.seekg( 0 );
while( !ifs.eof() )
{
ifs.getline( line, sizeof( line ) );
cout<<line;
}
return 0;
}

Thanks

wysota
22nd May 2007, 10:16
I don't see any "#endif" lines...

vermarajeev
22nd May 2007, 10:39
I don't see any "#endif" lines...

Ok, I think I copied the wrong program....
There has to be #endif but still it doesnt work...

wysota
22nd May 2007, 10:59
What errors do you get?

veda
22nd May 2007, 11:55
Where is the error?????

vermarajeev
22nd May 2007, 11:57
What errors do you get?

Ok, First the sample

int main (){
FILE *pFile = NULL;
char *fileName = "Logfile.log";

// Open the file in read mode
#ifdef win32
fopen_s(&pFile, fileName ,"r");
#else
pFile = fopen( fileName ,"r");
#endif

if (!pFile){
printf("Error opening file %s!\n", fileName);
exit(1);
}

// Lock the file.
#ifdef win32
_lock_file(pFile);
#else
flockfile(pFile);
#endif

printf("Locking the file %s.\n", fileName);
ifstream ifs( pFile ); //This doesnt work on linux why???
char line[255];
ifs.seekg( 0 );
while( !ifs.eof() ){
ifs.getline( line, sizeof( line ) );
cout<<line;
}

//unlock the file after the instance is closed
return 0;
}

I get error on line 25 on linux machine. The compiler says there is no constructor defined.
There is no problem on windows.

I tried using both gcc and g++ compilers
Thanks

wysota
22nd May 2007, 12:11
Could we see the exact message? It probably suggest other constructors.

vermarajeev
22nd May 2007, 12:44
Could we see the exact message? It probably suggest other constructors.

Here it goes


/Desktop/fileLock/lock/src/lock.cpp:77: error: no matching function
for call to ‘std::basic_ifstream<char, std::char_traits<char>
>::basic_ifstream(FILE*&)’
/usr/lib/gcc/i386-redhat-linux/4.0.0/../../../../include/c++/4.0.0/fstream:442:
note: candidates are: std::basic_ifstream<_CharT,
_Traits>::basic_ifstream(const char*, std::_Ios_Openmode) [with _CharT =
char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.0/../../../../include/c++/4.0.0/fstream:428:
note: std::basic_ifstream<_CharT, _Traits>::basic_ifstream() [with
_CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i386-redhat-linux/4.0.0/../../../../include/c++/4.0.0/iosfwd:89:
note: std::basic_ifstream<char, std::char_traits<char>
>::basic_ifstream(const std::basic_ifstream<char,
std::char_traits<char> >&)
*** Exited with status: 2 ***

wysota
22nd May 2007, 13:19
Seems it won't be that easy. You'd probably have to dig into the base class and find a way to initialise the object properly. It'd be much faster if you got rid of C++ streams and used stdio or if you used Qt streaming classes and files.

vermarajeev
22nd May 2007, 13:27
Seems it won't be that easy. You'd probably have to dig into the base class and find a way to initialise the object properly.

But the same constructor works fine on windows. According to me since it is a C++ stream, it should work.


It'd be much faster if you got rid of C++ streams and used stdio or if you used Qt streaming classes and files.

But then I need to change a lot of code then and you know it is really overhead.

There has to be some way...Isnt it???

wysota
22nd May 2007, 14:25
Sure there is a way. Dig into ios::base and find a way to use your FILE* as the appropriate buffer for the stream. That's quite time consuming, so that's why I suggested to find an alternative. Substituting using Qt streams should be quite quick using search&replace tools.

vermarajeev
24th May 2007, 10:27
Sure there is a way. Dig into ios::base and find a way to use your FILE* as the appropriate buffer for the stream. That's quite time consuming, so that's why I suggested to find an alternative. Substituting using Qt streams should be quite quick using search&replace tools.

OH!!! File locking doesnt work on windows. I'm surprised..Might be i'm doing somethig wrong..

Firstly

void _lock_file(
FILE* file
);

doesnt work on Microsoft Visual Studio .NET 2003. It works on only Microsoft Visual Studio 2005/.NET Framework 2.0.

I use Microsoft Visual Studio .NET 2003. Can people there tell me how to lock a file on windows (Microsoft Visual Studio .NET 2003 ) such that, it should be shared locking not exclusive. i.e the file should be locked to prevent other processes to read the same file.

Thanks.
Marcel, looking for some other links...
Thanks

sunil.thaha
25th May 2007, 06:21
If you are using the Qt 4 Commercial edition. I think you are entitled to use the QtFileLock in the Qt Solutoins

Just have a look at these
http://trolltech.com/products/qt/addon/solutions/catalog/4
http://trolltech.com/products/qt/addon/solutions/catalog/4/Utilities/qtlockedfile/
http://doc.trolltech.com/solutions/4/qtlockedfile/qtlockedfile.html

vermarajeev
25th May 2007, 08:15
If you are using the Qt 4 Commercial edition. I think you are entitled to use the QtFileLock in the Qt Solutoins

Just have a look at these
http://trolltech.com/products/qt/addon/solutions/catalog/4
http://trolltech.com/products/qt/addon/solutions/catalog/4/Utilities/qtlockedfile/
http://doc.trolltech.com/solutions/4/qtlockedfile/qtlockedfile.html

Hi sunil,
Thanks for the links. I'll try downloading and see how it works...