Using SHGetSpecialFolderPath+SubFolder with SHFileOperation - c

I want to delete the folder C:\Users\username\AppData\Roaming\appname when the users uninstall the application appname.
First, I use the following code to get the path C:\Users\username\AppData\Roaming:
TCHAR dir[MAX_PATH];
dir[0] = '\0';
BOOL ok = SHGetSpecialFolderPath(NULL, dir, CSIDL_APPDATA, TRUE);
appname is defined as _T("appname")
The first question is: How to append "appname" to "dir"?
Suppose the above is done. Then I need to use SHFileOperation to delete the non-empty folder C:\Users\username\AppData\Roaming\appname. So I need a double null-terminated string in a SHFILEOPSTRUCT structure. So
How to get a double null-terminated string from the result of the first step? Just append _T("\0\0") to it?
Update: I can use TCHAR *dir2 = lstrcat(dir, appname); to get the path. But when I tried to use TCHAR *dir3 = lstrcat(dir2, _T("\0\0"));, the folder is not deleted. Any number of \0 won't work.
p.s:
If I do the following directly, I got it to work. The problem is that I want to it to be user-independent.
TCHAR path[] = _T("C:\\Users\\username\\AppData\\Roaming\\appname");
memcpy(path + sizeof(path) / sizeof(TCHAR) - 1, _T("\0\0\0"), 3);

For appending paths see PathAppend function.
TCHAR dir[MAX_PATH] = {0};
BOOL ok = SHGetSpecialFolderPath(NULL, dir, CSIDL_APPDATA, TRUE);
PathAppend(dir, _T("appname"));
If you want ensure double null terminating of dir variable:
dir[MAX_PATH - 1] = 0;
dir[MAX_PATH - 2] = 0;

Related

Fopen function returns null when given an existing path

When trying to open a file with fopen(path, "2"); i get NULL on an existing path
iv'e tried to enter only the file name and it works but i want the program to write the file in the path...
Yes, i write the path with double backslashes "\\" when it's necesary.
Yes the path without doubt exists.
FILE* log;
char directory_path[PATH_LEN] = { 0 };
char directory_file[PATH_LEN] = { 0 };
//directory_path is the directory, entered by the user
//LOG_NAME is the files name without the path - "log.txt"
//#define PATH_LEN 100
printf("Folder to scan: ");
fgets(directory_path, PATH_LEN, stdin);
directory_path[strlen(directory_path) - 1] = 0;
//this section connects the path with the file name.
strcpy(directory_file, directory_path);
strcat(directory_file, "\\");
strcat(directory_file, LOG_NAME);
if ((log = fopen(directory_file, "w")) == NULL)
{
printf("Error");
}
My program worked until i tried to write into a file in order to create a log file. This means that the path is correct without doubt.
Can anyone tell me the problem here?
You have several issues in your code:
For one, fopen(path, "2"); is not valid.
The mode argument needs to include one of a, r, and w and can optionally include b or +.
As another thing, directory_path[strlen(directory_path) - 1] = 0; may truncate the end of your path (if it's over PATH_LEN characters long).
There also may be a possible issue with buffer overflow due to the fact that you copy a string to a buffer of the same size and then concatenate two other strings to it. Therefore, you should change this line:
char directory_file[PATH_LEN] = { 0 };
to this:
char directory_file[PATH_LEN+sizeof(LOG_NAME)+1] = { 0 };
To debug this issue, you should print the string entered and ask for confirmation before using it (wrap this in #ifdef DEBUG).

sprintf add special character in C

can anyone help me. I'm trying to create a folder, but when I use sprintf, it concatenates at the end special characters like OUUUU, how can I fix it?
there is an image (link below) where you can see the directory variable that has "/home/mia" and the buffer has "mkdir/home/miaOUUUU"
Any suggestions?
i'm using codeblocks in debian...
https://drive.google.com/file/d/1q3KKBbyDjA8_dfwKT54_OT_5QeREIz7k/view?usp=sharing
You should post the code in the body of the question, with copy+paste from your IDE and one extra indentation level (select the code and type Alt-K for that), not as a link to a bitmap, it is very rude.
directorio is not null terminated. You must declare it with one extra element as char directorio[i + 1]; and make sure to initialize directorio[i] to '\0'.
The memset is useless since you overwrite the whole buffer in the subsequent for loop. Do this instead:
char directorio[i + 1];
memcpy(directorio, path, i);
directorio[i] = '\0';
DIRP *dirp = opendir(directorio);
if (dirp == NULL) {
...
} else {
// do not forget to close the directory
closedir(dirp);
}
Also note that you should create directories from the root directory to the final path, and you should handle the spurious case of an existing file with the same name as one of the directories along the path.

How to set path environment variable in linux in C language code

I want to set a path environment variable in bash by C program.
So I coded using 'setenv' function, But it was not the answer to solve.
Could anybody suggest another way to solve this problem in C programming?
I thought the other solution that the program read the profile file, then modify and save, but actually when I opened this file there's no string I wanted about PATH variable.
You can use setenv() and putenv() to set environment variables. But these will only be set for the given program. You cannot set environment variables for the shell or its parent process.
Here an example to define the Python path.
It is created a string path and append it to the python path.
char *append_path = malloc(sizeof(char) * 1000);
append_path = "/trunk/software/hmac_sha256/:.";
printf("Append to path is:\n%s\n", append_path);
setenv("PYTHONPATH",append_path,1);//Set PYTHONPATH TO working directory https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.bpxbd00/setenv.htm
char *path = Py_GetPath();
printf("Python search path is:\n%s\n", path);
This should append the string to the PYTHONPATH environment variable. For me it is working as stated before.
In case the variable is replaced and not appended, then you just need to read the environment variable before, append the new string and then do the "setenv".
for example
//include string functions
#include <string.h>
....
char *current_path = malloc(sizeof(char) * 1000);
current_path = Py_GetPath();
printf("Current search path is:\n%s\n", current_path);
char *new_path = malloc(sizeof(char) * 1000);
new_path = "/trunk/software/hmac_sha256/:.";
printf("New to add path is:\n%s\n", new_path);
snprintf(current_path, sizeof(char) * 1000, "%s%s", current_path,new_path);//this concatenate both strings
setenv("PYTHONPATH",current_path,1);//Set PYTHONPATH TO working directory https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.1.0/com.ibm.zos.v2r1.bpxbd00/setenv.htm
char *path = Py_GetPath();
printf("Python search path is:\n%s\n", path);

Generate correct path for RegSetValueEx()

I am writing this C code that will store a Key in Registry which points in the current path of the application. Here is the code.
HKEY hKey;
LPCTSTR appPath;
LPCTSTR regPath = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
char buffer[300];
GetModuleFileName(NULL,buffer,300);
appPath = buffer;
if(RegOpenKeyEx(HKEY_CURRENT_USER,regPath,0,KEY_ALL_ACCESS,&hKey)== ERROR_SUCCESS)
{
RegSetValueEx(hKey,"storing.exe",0,REG_SZ,appPath,sizeof(appPath));
RegCloseKey(hKey);
}
The problem is that GetModuleFileName() returns the path in that form :
C:\Documents and Settings\User\Desktop\storing.exe
while in the RegSetValueEx() is expected a path in that form :
C:\\Document and Settings\\User\\Desktop\\storring.exe
Is there any way to convert the first path into the second one ?
Tried many ways to replace that string but no one worked.
Thank you.
Try the answer of this question.
This should be enough to solve your problem.
str_replace(appPath, "\", "\\");

a recursive function to manipulate a given path

I am working on modifying the didactic OS xv6 (written in c) to support symbolic links (AKA shortcuts).
A symbolic link is a file of type T_SYM that contains a path to it's destination.
For doing that, i wrote a recursive function that gets a path and a buffer and fills the buffer with the "real" path (i.e. if the path contains a link, it should be replaced by the real path, and a link can occur at any level in the path).
Basically, if i have a path a/b/c/d, and a link from f to a/b, the following operations should be equivalent:
cd a/b/c/d
cd f/c/d
Now, the code is written, but the problem that i try to solve is the problem of starting the path with "/" (meaning that the path is absolute and not relative).
Right now, if i run it with a path named /dir1 it treats it like dir1 (relative instead of absolute).
This is the main function, it calls the recursive function.
pathname is the given path, buf will contain the real path.
int readlink(char *pathname, char *buf, size_t bufsize){
char name[DIRSIZ];
char realpathname[100];
memset(realpathname,0,100);
realpathname[0] = '/';
if(get_real_path(pathname, name, realpathname, 0, 0)){
memmove(buf, realpathname, strlen(realpathname));
return strlen(realpathname);
}
return -1;
}
This is the recursive part.
the function returns an inode structure (which represents a file or directory in the system). it builds the real path inside realpath.
ilock an iunlock are being used to use the inode safely.
struct inode* get_real_path(char *path, char *name, char* realpath, int position){
struct inode *ip, *next;
char buf[100];
char newpath[100];
if(*path == '/')
ip = iget(ROOTDEV, ROOTINO);// ip gets the root directory
else
ip = idup(proc->cwd); // ip gets the current working directory
while((path = skipelem(path, name)) != 0){name will get the next directory in the path, path will get the rest of the directories
ilock(ip);
if(ip->type != T_DIR){//if ip is a directory
realpath[position-1] = '\0';
iunlockput(ip);
return 0;
}
if((next = dirlookup(ip, name, 0)) == 0){//next will get the inode of the next directory
realpath[position-1] = '\0';
iunlockput(ip);
return 0;
}
iunlock(ip);
ilock(next);
if (next->type == T_SYM){ //if next is a symbolic link
readi(next, buf, 0, next->size); //buf contains the path inside the symbolic link (which is a path)
buf[next->size] = 0;
iunlockput(next);
next = get_real_path(buf, name, newpath, 0);//call it recursively (might still be a symbolic link)
if(next == 0){
realpath[position-1] = '\0';
iput(ip);
return 0;
}
name = newpath;
position = 0;
}
else
iunlock(next);
memmove(realpath + position, name, strlen(name));
position += strlen(name);
realpath[position++]='/';
realpath[position] = '\0';
iput(ip);
ip = next;
}
realpath[position-1] = '\0';
return ip;
}
I have tried many ways to do it right but with no success. If anyone sees the problem, i'd be happy to hear the solution.
Thanks,
Eyal
I think it's clear that after running get_real_path(pathname, name, realpathname, 0, 0) the realpathname cannot possibly start with a slash.
Provided the function executes successfully, the memmove(realpath + position, name, strlen(name)) ensures that realpath starts with name, as the position variable always contains zero at the first invocation of memmove.
I'd suggest something like
if(*path == '/') {
ip = iget(ROOTDEV, ROOTINO); // ip gets the root
realpath[position++] = '/';
} else
ip = idup(proc->cwd); // ip gets the current working directory
P.S. I'm not sure why you put a slash into the realpathname before executing the get_real_path, since at this point you don't really know whether the path provided is an absolute one.
Ok, found the problem...
The problem was deeper than what i thought...
Somehow the realpath was changed sometimes with no visible reason... but the reason was the line:
name = newpath;
the solution was to change that line to
strcpy(name,newpath);
the previous line made a binding between the name and the realpath... which can be ok if we were not dealing with softlinks. When dereferencing a subpath, this binding ruined everything.
Thanks for the attempts

Resources