NSFileManager removeItemAtPath:error: does not respect POSIX permissions - macos

I have some code that checks for the existence of a file and, if it is present, deletes it. The problem is, I am unable to get it to fail even if the file should not be writeable. My code looks like:
if([theManager fileExistsAtPath:savingAs isDirectory:&destIsDir])
{
BOOL itemRemoved=[theManager removeItemAtPath:savingAs error:&err];
if(!itemRemoved)
{
// why?
NSAlert *rebuildAlert=[NSAlert alertWithMessageText:#"Error removing item"
defaultButton:nil alternateButton:nil otherButton:nil
informativeTextWithFormat:#"%#",[err localizedDescription]];
[rebuildAlert runModal];
proceed=NO;
}
}
Even if I set ownership to root:wheel and mode to 000 (i.e. not readable, writeable or executable by anyone) the file is still silently deleted. The account I'm running this from is a user account with Admin privileges but even so, being able to kill files owned by root doesn't seem very safe. The only way to throw an error is to lock the file using chflags uchg filename. I have also implemented (as a stub for now) the fileManager:shouldRemoveItemAtPath: delegate method where I could check permissions if necessary. The problem is that returning NO from this method does not cause removeItemAtPath: to return an error. Re-checking with fileExistsAtPath: seems cumbersome. Finally, there doesn't seem to be a simple method of disambiguating which instance of NSFileManager is issuing the call to removeItemAtPath: in the delegate method. Typically these instances are transitory objects so their id's are not valid for any significant length of time. I could sub-class NSFileManager and add a tag instance variable but that seems like a sledgehammer to crack a nut.
In summary:
1) is it correct behaviour for removeItemAtPath to ignore files it does not own?
2) disallowing file deletion in the delegate method is not communicated back to the caller of removeItemAtPath
3) determining which invocation is calling the delegate method is hard

This is the correct behavior. Erasing a file does not require read access to the file, only the directory containing it. Think of a directory as a list of files, and erasing a file as simply removing it from that list, and it will all make sense.

Related

Chef Recipe How To Check If File Exists

I just started using Chef and I'm trying to figure out how to first check if a file exists before doing anything.
I have the file part down for my current use case, where I'm removing a login file for the production server, ex:
file '/var/www/html/login.php' do
action :delete
end
However, I'd like the abilty to first check if the file exists, ex.
if (file_exists === true)
file '/var/www/html/login.php' do
action :delete
end
end
As mentioned in the comments, for a deletion action, the if statement is unnecessary, as mentioned, because if chef doesn't find the file to be deleted, it will assume it was already deleted.
Otherwise, you generally want to use guard properties in the resource (available for all resources), rather than wrapping a resource in an if-then.
file '/var/www/html/login.php' do
only_if { ::File.exist?('/var/www/html/login.php') }
action :touch
end
And you probably also want to familiarize yourself with the Ruby File class methods.
The basic idea of Chef is that you state the desired state of the system, and then Chef compares that to the actual state, and makes any changes needed to bring the system into the desired state. You do not need to have an if statement to check if the file exists before deleting it; Chef itself should check if the file exists if I'm not mistaken.

PFUser currentUser saveInBackgroundWithBlock completes succeeded without even trying

I am trying to alter the logged in user. I make my changes as usual, and I call:
[[PFUser currentUser] saveInBackgroundWithBlock:^(BOOL succeeded, NSError *PF_NULLABLE_S error){
if(succeeded){
NSLog(#"Saved user successfully.");
}else{
NSLog(#"Unable to save user: %#", error);
}
}];
It saves successfully, but my changes are gone. Just before saving, my user objects has this key:
.meta.acceptsAllMessages = 1. The moment save completion block returns, that key is gone. `(meta is my generic JSON object at user, and other values in meta key are retained with no problem). My changes aren't also reflect to the server side too.
The first suspect was the beforeSave trigger, however there's absolutely nothing related to meta keys in my trigger, so that's not the case. Why would this happen?
UPDATE: There seems to be a problem deeper down. I was saving something else entirely, and ran into the same issue. I've enabled airplane mode, and I wanted to save my current user, and it called the completion handler immediately, with succeeded set to YES and error set to nil without an internet connection. I've double checked that I'm using saveInBackgroundWithBlock: and not saveEventually. Why does this happen?
Okay, I've found the solution.
I was adding an object to the array inside my user object, without assigning the property itself. In the latest instance, I was doing something like:
[[PFUser currentUser][#"myArray"] addObject:#"something"];
[[PFUser currentUser] saveInBackground...];
Because I was not assigning any object itself, [my assumption is that] Parse thought that my user object was not dirty, and it completed immediately without even trying to save. I've solved the problem like this:
NSMutableArray *array = [PFUser currentUser][#"myArray"];
[array addObject:#"something"];
[PFUser currentUser][#"myArray"] = array;
The last line is the key. I'm assigning to the "myArray" field of Parse object, which causes Parse to mark my user dirty. Then, when I save, because it is dirty, it actually saves my user to the server, and it works.

NSFileWrapper returns nil, sometimes

I'm using NSFileWrapper for my package document. Sometimes, when I request the data of a file inside the package I get nil.
This is how I query the data of a file inside the package:
- (NSData*) dataOfFile(NSString*)filename {
NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
return fileWrapper.regularFileContents; // This returns nil sometimes. Why?
}
This method eventually starts returning nil for some files (not all). Sadly, I haven't managed to reproduce the problem consistently.
In case it helps, this is how I open the package:
- (BOOL) readFromFileWrapper:(NSFileWrapper *)fileWrapper ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
self.documentFileWrapper = fileWrapper;
return YES;
}
This is how I update the data of a file inside the package:
- (void) updateFile:(NSString*)filename withData:(NSData*)data {
SBFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
if (fileWrapper) {
[self.documentFileWrapper removeFileWrapper:fileWrapper];
}
NSFileWrapper *fileWrapper = [[SBFileWrapper alloc] initRegularFileWithContents:data ];
fileWrapper.preferredFilename = filename;
[self.documentFileWrapper addFileWrapper:fileWrapper];
}
This is how I save the package:
- (NSFileWrapper*) fileWrapperOfType:(NSString *)typeName error:(NSError *__autoreleasing *)outError {
return self.documentFileWrapper;
}
Why can this be happening? Is there a way to prevent it?
The documentation of regularFileContents appears to talk about this problem:
This method may return nil if the user modifies the file after you
call readFromURL:options:error: or initWithURL:options:error: but
before NSFileWrapper has read the contents of the file. Use the
NSFileWrapperReadingImmediate reading option to reduce the likelihood
of that problem.
But I don't understand what has to be changed in the code above to prevent this situation.
Failed Experiments
I tried saving the document if regularFileContents return nil but it still returns nil afterwards. Like this:
- (NSData*) dataOfFile(NSString*)filename {
NSFileWrapper *fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
NSData *data = fileWrapper.regularFileContents;
if (!data) {
[self saveDocument:nil];
fileWrapper = [self.documentFileWrapper.fileWrappers objectForKey:filename];
data = fileWrapper.regularFileContents;
}
return data;
}
There is not enough code to see what's really going on. However the root cause is that NSFileWrapper is just what its name implies: an object that represents a file or directory. Therefore, the actual file or directory can easily get "out of synch" with the object, which lives in memory. Whenever NSFileWrapper determines that this has occurred, it returns nil for certain operations. The solution is to make NSFileWrapper objects short-lived. Create and open just when you need them and then save and close as soon as possible.
In particular, it looks like your code is keeping a pointer to a package directory wrapper around for a long time and assuming that it's always valid. If the directory changes for any reason, this isn't the case. Recode so that you get a fresh package directory wrapper each time you need it, and the problem ought to go away.
If the file changes on disk then you'll get nil (as #Gene says). However, you can check this by using matchesContentsOfURL: method which:
determines whether a disk representation may have changed, based on the file attributes stored the last time the file was read or written. If the file wrapper’s modification time or access permissions are different from those of the file on disk, this method returns YES. You can then use readFromURL:options:error:
This from Working with File Wrappers Apple documentation.
Note this from the intro to that section:
Because the purpose of a file wrapper is to represent files in memory, it’s very loosely coupled to any disk representation. A file wrapper doesn’t record the path to the disk representation of its contents. This allows you to save the same file wrapper with different URLs, but it also requires you to record those URLs if you want to update the file wrapper from disk later.
So you'll have to save the url to the original file if you want/need to re-read it.
Be interesting to hear what matchesContentsofURL: returns when you're seeing nil results.

QTP - if object exists in object repository

In QTP is there any way in the code to check to see if a specific object exists in the object repository. I have tried the following code:
If JavaWindow(className).JavaDialog(dialogName).Exist Then
doThisStuff
Else
doThisStuffInstead
End If
But from what I have gleamed from the Internets, this is similar to a isVisible method, only resulting in true if the specified object is currently visible. When I use the above code I receive a "JavaDialog object was not found in the Object Repository." Is there a method or any way to prevent this very error and check to see if the object does indeed exist?
Thank you for your time
I'm not sure what you're trying to accomplish here, one typically knows if an object exists in the object repository before using it. The doubt is usually whether there is a corresponding control in the AUT (Application Under Test).
If you really face the situation that sometimes the object is in the repository and sometimes it isn't (I can think of several ways for this to happen but none of them make much sense) then you can use VBScript's error handling mechanism.
On Error Resume Next ' Turn off error handling
' Just check if object is in repository, there's no need to do anything with it
Dim Exists: Exists=JavaWindow(className).JavaDialog(dialogName).Exist
If Err.Number <> 0 Then
doThisStuff 'Exists is still empty
Else
doThisStuffInstead ' Exists is properly set
End If
On Error Goto 0 ' Resume regular error handling
So, from the error you get, either the dialog that appears is different from the one you've stored in the repository or you don't have it there.
Have you checked it is really present in the Repository? You can try to just locate this element button.
Using the method of "if object not in the repository - skip the step" is not really a good idea. 1. Why would you want to skip the test/part of the test if the object was not saved in the repository?
2. If it's not there, so you need to make sure to store it.
I would assume that this "missing" object might have some values by which it's matched to the object from the repository different from test to test. You can tune the "matching" mechanism by manually setting the values by which you want QTP to locate it.

"Open With" menu for remote files

I'm getting troubles getting the applications associated with a remote file how has a URL like: "http://servername/folder/file.png".
The code I use is:
...
NSURL *url = [NSURL fileURLWithPath:#"http://servername/folder/file.png"];
NSArray *apps = (NSArray *)LSCopyApplicationURLsForURL((CFURLRef) url,kLSRolesAll);
...
I also try using URLWithString: but the result is the same.
What is the correct approach for this?
Edit after Joshua replay:
Sorry for may bad redaction. The problem is that the LSCopyApplicationURLsForURL call return nil.
First, -fileURLWithPath: expects a file system path like #"/Users/me/Desktop/MyFile.png".
Second, you don't say what the "same" results are and what is wrong with them, so it's difficult to tell you what the problem is.
The docs say this:
If the item URL’s scheme is file
(designating either a file or a
directory), the selection of suitable
applications is based on the
designated item’s filename extension,
file type, and creator signature,
along with the role specified by the
inRolesMask parameter; otherwise, it
is based on the URL scheme (such as
http, ftp, or mailto).
So what are you getting and what do you expect to get?

Resources