Getting ACL_ENTRY_ERROR after acl_create_entry on Linux - linux

I'm writing a program that sets acl permissions for a given user/group. Very similar to the "setfacl" command.
According to a given user/group I search first if the entry already exists. If I get a NULL then I call acl_create_entry. When I check the ACL via acl_check, I get an ACL_ENTRY_ERROR.
The function is something similar to this:
/*ar_pobj=Path or file name, ar_tagType=ACL_USER or ACL_GROUP, ar_ptagQual=User name or group name, ar_pperms=string with permissions "rwx-"*/
int addPermissions(char *ar_pobj, acl_tag_t ar_tagType, char *ar_ptagQual, char *ar_pperms)
{
acl_t la_acl;
id_t la_qual;
acl_entry_t la_entry;
int la_error;
la_acl=acl_get_file(par_obj,ACL_TYPE_ACCESS);
if (la_acl == NULL)
{
return -1;
}
switch(ar_tagType)
{
case ACL_USER:
la_qual=userIdFromName(ar_ptagQual);/*This function works fine*/
if(-1==la_qual)
{
acl_free(la_acl);
return -1;
}
break;
case ACL_GROUP:
la_qual=groupIdFromName(ar_ptagQual);/*This function works fine*/
if(-1==la_qual)
{
acl_free(la_acl);
return -1;
}
break;
default:
acl_free(la_acl);
return -1;
}
la_entry = findEntry(la_acl,ar_tagType,la_qual);/*This function returns NULL as the entry was not found*/
if(NULL==la_entry)
{
if (acl_create_entry(&la_acl, &la_entry) == -1)/*Returns OK*/
{
acl_free(la_acl);
return -1;
}
la_error=acl_check(la_acl,NULL);/*HERE IS WHERW I GET THE ERROR*/
...
}
...
}
Any clues? Thank you in advance.
edit This error always happens if you did not set the tag type and qualifier. But I am still getting it after doing this

¡Issue solved! The problem was that I forgot to recalculate the ACL mask. Calling acl_calc_mask(&la_acl) right before calling acl_set_file solved the problem.

Related

How to Fix the Following Error: Cannot invoke "String.length()" because "this.inputStr" is null

/* Returns the count of the user's character. */
public int getUserCharCount(){
inputStr = inputStr;
for (int i = 0; i < inputStr.length(); i++) {
if (inputStr.charAt(i) == userChar) {
userCharCount ++;
}
}
return userCharCount;
}
By default, inputStr is "" in the Main code. It should be updating to the user input.
You can log inputStr
maybe user set it to null.
also you may check if your variable is null before action.
It hard to say what wrong because you not provide class that hold your variable, and not provide way that class are created and modified.
may be you create new one with null, may be user change value to null

Return result of Invoking a Delegate from another thread

I've got a GUI with a TabControl. Each new TabPage is created via a new Thread. I want to call this->tabControl->TabCount, but the tabControl is owned by a thread other than the one I'm calling from. Therefore, I need to Invoke a delegate. However, all the examples I find online show printing to std::cout from each of the delegate methods. I need a return value, in this case an int.
delegate int MyDel();
int InvokeTabCount()
{
if (this->InvokeRequired)
{
MyDel^ del = gcnew MyDel(this, &MyTabControl::InvokeTabCount);
auto temp = this->Invoke(del); // can't just "return this->Invoke(del)"
return temp; // Invoke() returns a System::Object^
}
else
{
return this->tabControl->TabCount;
}
}
void CreateNewTab()
{
// do stuff
this->tabControl->TabPages->Insert(InvokeTabCount() - 1, myNewTab); // insert a tab
this->tabControl->SelectTab(InvokeTabCount() - 2); // OutOfBounds and tabPageNew
}
System::Void MethodToAddNewTabPage() //actually a click event but whatever
{
System::Threading::Thread^ newThread =
gcnew System::Threading::Thread(
gcnew System::Threading::ThreadStart(this, &MyTabControl::CreateNewTab));
newThread->Start();
}
Currently, my InvokeTabCount() method is returning -1 when I simply this->Invoke(del) without returning it. And I am unable to return it because my method expects to return an int instead of a System::Object^ which is what Invoke() returns. However, when debugging I find that auto temp contains the value 2 which is correct. And temp->ToString() contains the value "2" which would also be correct.
How do I return this->Invoke(del)?
Do I need to set the value of a global variable from within my InvokeTabCount() method? I suppose I could find a way to translate from System::String^ to std::string to utilize std::stoi(), but that seems like an odd workaround.
Current solution:
delegate int MyDel();
int InvokeTabCount()
{
if (this->InvokeRequired)
{
MyDel^ del = gcnew MyDel(this, &MyTabControl::InvokeTabCount);
auto temp = this->Invoke(del);
return int::Parse(temp->ToString());
}
else
{
return this->tabControl->TabCount;
}
}
The result is an integer, boxed and contained in an Object^ reference. You should be able to simply cast it to int.
If you want to be extra safe, do a null check and verify that temp->GetType() returns int::typeid, but that's probably overkill since you're creating the delegate (still in the typed form) right there.

How to get installed application path for executable in COM

I am trying to get the installed location of all application using COM. I am able to get the display name of each application. But I am not able to get installed path of each application.
MY Code:
CComPtr<IShellItem> spPrinters;
CoInitialize(nullptr);
HRESULT hresult = ::SHCreateItemFromParsingName(L"::{26EE0668-A00A-44D7-9371-BEB064C98683}\\8\\"
L"::{7B81BE6A-CE2B-4676-A29E-EB907A5126C5}", nullptr, IID_PPV_ARGS(&spPrinters));
CComPtr<IEnumShellItems> spEnum;
spPrinters->BindToHandler(nullptr, BHID_EnumItems, IID_PPV_ARGS(&spEnum));
for (CComPtr<IShellItem> spProgram; spEnum->Next(1, &spProgram, nullptr) == S_OK; spProgram.Release())
{
CComHeapPtr<wchar_t> spszName;
spProgram->GetDisplayName(SIGDN_NORMALDISPLAY, &spszName);
CString cDisplayName = spszName;
}
Any idea how to get installed path from IEnumShellItems?
Here is a piece of code that will dump this out. The child's IPropertyStore does not return these, I don't know why, so we have to use the old
IShellFolder2::GetDetailsEx method with a special column id (which is the same as a PROPERTYKEY).
CComPtr<IShellItem> cpl;
CComPtr<IShellFolder2> folder;
CComPtr<IEnumShellItems> enumerator;
PROPERTYKEY pkLocation;
SHCreateItemFromParsingName(L"::{26EE0668-A00A-44D7-9371-BEB064C98683}\\8\\::{7B81BE6A-CE2B-4676-A29E-EB907A5126C5}", nullptr, IID_PPV_ARGS(&cpl));
// bind to IShellFolder
cpl->BindToHandler(NULL, BHID_SFObject, IID_PPV_ARGS(&folder));
// bind to IEnumShellItems
cpl->BindToHandler(NULL, BHID_EnumItems, IID_PPV_ARGS(&enumerator));
// get this property key's value
PSGetPropertyKeyFromName(L"System.Software.InstallLocation", &pkLocation);
for (CComPtr<IShellItem> child; enumerator->Next(1, &child, nullptr) == S_OK; child.Release())
{
// get child's display name
CComHeapPtr<wchar_t> name;
child->GetDisplayName(SIGDN_NORMALDISPLAY, &name);
wprintf(L"%s\n", name);
// get child's PIDL
CComHeapPtr<ITEMIDLIST> pidl;
SHGetIDListFromObject(child, &pidl);
// the PIDL is absolute, we need the relative one (the last itemId in the list)
// get it's install location
CComVariant v;
if (SUCCEEDED(folder->GetDetailsEx(ILFindLastID(pidl), &pkLocation, &v)))
{
// it's a VT_BSTR
wprintf(L" %s\n", v.bstrVal);
}
}
Note it's using an undocumented System.Software.InstallLocation PROPERTYKEY. To find it I just dumped all columns with a code like this for each child:
int iCol = 0;
do
{
SHCOLUMNID colId;
if (FAILED(folder->MapColumnToSCID(iCol, &colId)))
break; // last column
CComHeapPtr<wchar_t> name;
PSGetNameFromPropertyKey(colId, &name);
CComVariant v;
if (SUCCEEDED(folder->GetDetailsEx(ILFindLastID(pidl), &colId, &v)))
{
if (v.vt == VT_BSTR)
{
wprintf(L" %s: %s\n", name, v.bstrVal);
}
else
{
wprintf(L" %s vt: %i\n", name, v.vt);
}
}
iCol++;
} while (true);
}
PS: I've not added much error checking, but you should.

FileInfo.Exists Returns False after file is copied

In the below code test.txt exists before it is run and test2.txt does not. When run destFile.Exists returns null after the file is copied to destFile's location. What is causing this? I cannot find any information in msdn that supports what is happening.
var origFile = new FileInfo(#"C:\Users\user\Desktop\CopyTest\test.txt");
var destFile = new FileInfo(#"C:\Users\user\Desktop\CopyTest\test2.txt");
if (!destFile.Exists && origFile.Exists)
origFile.CopyTo(destFile.FullName);
if (destFile.Exists)
Console.WriteLine("The file was found");
Console.ReadLine();
Try to use destFile.Refresh(); before you access the property
destFile.Refresh();
if (destFile.Exists)
Console.WriteLine("The file was found");
or use the static method File.Exists:
if (File.Exists(#"C:\Users\user\Desktop\CopyTest\test2.txt"))
Console.WriteLine("The file was found");
The FileInfo provides a lot of informations, but this is a snapshot which will be initialized the first time you access it and will not be updated later. So use it only if you need current state and if you need multiple informations. Otherwise use the static methods in System.IO.File.
Here you can see the current implementation of the Exists property. You see that it's initializing it the first time you access it, later the old state will be returned:
public override bool Exists {
[System.Security.SecuritySafeCritical] // auto-generated
get {
try {
if (_dataInitialised == -1)
Refresh();
if (_dataInitialised != 0) {
// Refresh was unable to initialise the data.
// We should normally be throwing an exception here,
// but Exists is supposed to return true or false.
return false;
}
return (_data.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) == 0;
}
catch
{
return false;
}
}

wxDirDialog Returns the Wrong Directory on Vista

I recently ported the following code to wx3.0 under visual studio 2013:
void PanelFileControl::on_retrieve_clicked(wxCommandEvent &event)
{
if(!chosen_files.empty())
{
Csi::ModalCounter counter;
wxDirDialog query(
this,
make_wxString(my_strings[strid_choose_retrieve_dir]),
make_wxString(wxGetApp().get_config()->get_last_prog_dir()));
int rcd;
query.CentreOnParent();
rcd = query.ShowModal();
if(rcd == wxID_OK)
{
// we need to generate an operation for every selected file.
StrAsc path(make_StrAsc(query.GetPath()));
DlgFileControl::operations_type operations;
if(path.last() != Csi::FileSystemObject::dir_separator())
path.append(Csi::FileSystemObject::dir_separator());
for(files_type::iterator fi = chosen_files.begin(); fi != chosen_files.end(); ++fi)
{
file_type const &file(*fi);
StrAsc file_path(path + file.get_file_name());
bool use_file(true);
if(Csi::file_exists(file_path.c_str()))
{
OwxStringStream message;
message << boost::format(my_strings[strid_overwrite_file_confirm].c_str()) %
file_path;
wxMessageDialog overwrite_query(
this,
message.str(),
wxT(""),
wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
int rcd;
overwrite_query.CentreOnParent();
rcd = overwrite_query.ShowModal();
if(rcd != wxID_YES)
use_file = false;
}
if(use_file)
operations.push_back(new ReceiveFileOperation(file, file_path));
}
// we can now display the operation dialogue
if(!operations.empty())
{
DlgFileControl dialogue(this, device_name, operations);
dialogue.show_modal();
}
}
}
} // on_retrieve_clicked
Following this change (which didn't require any changes to the code above), I have received complaints that, if the user selects the desktop and then double clicks on a directory on the desktop, that the file save operation fails. This appears to be a result of the path produced by the wxDirDialog::GetPath() and has only been seen under windows vista. I have followed up some testing and I find that, under Vista, the last path component is mentioned twice in the string returned by GetPath().
Has anyone seen this issue? Are there any work arounds?
I found that I can address the issue by preventing the wxDirDialog from using the IFILEDIALOG interface from being used. My ShowModal() method now looks like this:
int wxDirDialog::ShowModal()
{
WX_HOOK_MODAL_DIALOG();
wxWindow* const parent = GetParent();
WXHWND hWndParent = parent ? GetHwndOf(parent) : NULL;
// Use IFileDialog under new enough Windows, it's more user-friendly.
int rc;
#if wxUSE_IFILEDIALOG
if ( wxGetWinVersion() > wxWinVersion_Vista )
{
rc = ShowIFileDialog(hWndParent);
}
else
{
rc = wxID_NONE;
}
if ( rc == wxID_NONE )
#endif // wxUSE_IFILEDIALOG
{
rc = ShowSHBrowseForFolder(hWndParent);
}
// change current working directory if asked so
if ( rc == wxID_OK && HasFlag(wxDD_CHANGE_DIR) )
wxSetWorkingDirectory(m_path);
return rc;
}

Resources