Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 11 months ago.
Improve this question
I'm trying to make a file install itself into the system (linux).
Every method I use (rename, system(mv), execl, etc) fails. Is there anyway to make a running executable move itself while running? The closest I've come is renaming it but only within the same directory.
The code below "copies" itself to a new destination and gets deleted after termination. Basically, the code makes a new entry (hardlink) at the specified location and removes the current one (from the calling directory). The contents of the file will be preserved, since there is no copy and deletion involved.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
int main(int argc, const char *argv[])
{
//current filepath (dir + name)
const char* file_path = argv[0];
//extract filename component (needed to append to newdir)
char* file_name_ = strdup(file_path);
char* file_name = basename(file_name_);
//make new path name
char* new_dir = "<put your destination here - with no slash ('/') at the end>";
size_t new_path_len = strlen(new_dir) + strlen(file_name) + 2; //two extra bytes: '/' + '\0'
char new_path[new_path_len];
snprintf(new_path, new_path_len, "%s/%s", new_dir, file_name);
//make a new name for a file (hardlink)
link(file_path, new_path);
//delete a name and possibly the file it refers to
unlink(file_path);
//cleanup
free(file_name_);
return 0;
}
Hint: careful study of the documenation to link is highly recommended (especially the ERRORS section).
References:
basename - parse pathname components
link - make a new name for a file
unlink - delete a name and possibly the file it refers to
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
The error says no such file or directory i moved the file to the project folder
int main(int argc, const char * argv[]) {
int i;
char singleline[150];
FILE *file;
file = fopen("test.txt", "r");
puts(singleline);
if( file == NULL ) {
perror("Error: ");}
fclose (file);
}
return 0;
}
I guess you really need help debugging why this is happening to you.
Try adding some more code to your routine to help you determine what is going on. One thing to try is to call getcwd.
#include <unistd.h>
...
char buf[PATH_MAX];
printf("cwd: %s\n", getcwd(buf, sizeof(buf)));
...
This should report to you where your program thinks it is running from.
You report you get the following output:
cwd: /Users/ahmedhossam/Library/Developer/Xcode/DerivedData/assembler-doinswpyuiekhhemczblkainroaw/Build/Products/Debug `ֿ_\377
Start with that first, and I am guessing the next steps will become obvious to you.
The reported current working directory (hence, getcwd) is not your project folder. You can copy your file to that strange directory, or you can use chdir to change your working directory to be your project folder, or you can specify the absolute path to your file as suggested below.
You can avoid the problem altogether by specifying the absolute path to your file.
file = fopen("/the/absolute/path/to/test.txt", "r");
This question already has an answer here:
Issue with S_ISDIR() result in C (maybe because stat() isn't setting its struct properly?)
(1 answer)
Closed 7 years ago.
studentsDir = opendir(lineValues);
while ((entry = readdir(studentsDir)) != NULL) {
stat(path, &dirData);
if (S_ISDIR(dirData.st_mode) && (entry->d_name[0] != '.')
&& (entry->d_name[1] != '.')) {
Im searching in a directory for folders. The problem is that stat returns dirdata with empty values for most of the folders
the code needs:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
the prototype for the function is:
int stat(const char *path, struct stat *buf);
so you also need:
struct stat dirData;
and the *path variable needs to be the actual path (can be relative or absolute), with the file name, to the target file.
Nothing in the posted code indicates any of the above has been included in the code.
and 'entry' is a pointer to a 'struct dirent' where the current file/directory name needs to be appended to 'path' before stat() uses it.
'entry' needs to be checked to assure it is not NULL before using it.
the struct dirent contains the d_name[256] field that will contain
the name of a current file (or directory) (but not the whole path)
so each time the code steps into a (sub) directory,
(which the posted code is not doing)
then the path needs to have the string from d_name[]
appended to the path string
I'm using GTK to create an interface for my C program running Linux.
I'm using this function to load my XML interface:
gtk_builder_add_from_file(builder, g_build_filename("myInterface.glade", NULL), &error);
As long as I'm in the same directory as my compiled file, it works.
But if I'm in another directory, let say a child one and I execute it: ../a.out, my program doesn't find the file.
So the idea is to first get the program path ("/home/.../program") and to add the file name to get an absolute path.
But I have no idea how can I get the program path. And I'm not sure this is the best idea to make it work.
Any idea? Thanks!
argv[0] contain the relative/full path you ran to run the program.
just scan up to the last '/' and this will be the run dir from your current location
'edit' after some more research, i found this, which works in all cases:
#include<stdio.h>
#include <unistd.h>
#include <string.h>
#include <libgen.h>
int main()
{
char path[500] = {0};
int dest_len = 500;
if (readlink ("/proc/self/exe", path, dest_len) != -1)
{
dirname (path);
strcat (path, "/");
printf("path=%s\n", path);
}
}
In your case where you are using GTK, it is better to use GResource and compile myInterface.glade directly into your program.
I am trying to add a new file member with ar_hdr format and put it right after the last element in an archive. My code compiles, but when I want to view the file name with the ar -t command, I got an error message that says: ar: hello.a: Inappropriate file type or format. Can someone take a look at my code and give me some hints on how to fix it? Thanks.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/utsname.h>
#include <ctype.h>
#include <string.h>
#include <ar.h>
#define BLOCKSIZE 1
int main (int argc, char **argv)
{
char *archive = argv[1];
char *read_file = argv[2];
int in_fd;
int out_fd;
char title[] = ARMAG; //constant define in ar.h
char buf[BLOCKSIZE];
int num_read;
int num_written;
struct stat stat_file;
struct ar_hdr my_ar;
//open read_file (i.e., text file)
if (stat(read_file, &stat_file) == -1){
perror("Error in Stat");
exit(-1);
}
//assign file info to struct dhr (my_ar)
sprintf(my_ar.ar_name, "%s", read_file);
sprintf(my_ar.ar_date, "%ld", stat_file.st_mtimespec.tv_sec);
sprintf(my_ar.ar_uid, "%i", stat_file.st_uid);
sprintf(my_ar.ar_gid, "%i", stat_file.st_gid);
sprintf(my_ar.ar_mode, "%o", stat_file.st_mode) ;
sprintf(my_ar.ar_size, "%lld", stat_file.st_size) ;
//0666 - open archive
out_fd = open(archive, O_CREAT | O_WRONLY | O_APPEND, 0666);
if (out_fd == -1) {
perror("Canot open/create output file");
exit(-1);
}
//write my_ar to archive
num_written = write(out_fd, title, sizeof(title));
num_written = write(out_fd, &my_ar, sizeof(my_ar));
printf("\n");
return 0;
}
The title should only appear once in the file, at the very beginning. If you're appending a file to an archive, you just need to write the ar_hdr for the new file, followed by the contents of the file.
So you need to check whether the file already exists. If it doesn't, and you're creating a new archive, you need to write title first. If it does exist, skip that step. Since you're opening the file in append mode, you can tell whether it's a new file using lseek():
off_t curpos = lseek(out_fd, SEEK_CUR, 0); // Get current position
if (curpos == 0) { // At beginning, it must be a new file
num_written = write(out_fd, ARMAG, SARMAG);
}
user2203774, I'm going to re-iterate: You're working with a poorly-documented file format that is not standardized. The only way to know the correct file format is to (a) study the documentation links I gave in your other question, and (b) analyze a sampling of the archive files you have, to determine whether or not the format conforms to such documentation as you have. The likelihood is that the file format will be similar, but not identical. THEN, you need to figure out what the differences are. Once you do that, create your own file format document, and work off of that.
ALSO NOTE that the first and simplest debugging step is "compare what my program generated with the equivalent as generated by ar. How are they different? Why?" (The od -c command is helpful here, or a side-by-side hex viewer).
Several points:
The magic header string ("!<arch>\n") only goes at the start of the file, not at the beginning of every record.
All the fields in the ar_hdr structure are filled with spaces, and are not null-terminated strings.
Unless you're prepared to update the symbol table (including adding one if necessary) and rewrite the entire file, you must make sure your filenames do not exceed fifteen characters.
Each filename must be immediately followed by a / character (which must not be followed by a null. Again, the rest of the field filled with spaces.)
You're never initializing the ar_fmag field of the ar_hdr structure. This needs to be initialized to a specific value.
After you write the header, you need to write the actual content of the file.
Some references indicate that when the file content is written, you must write an even number of bytes. If the file size is an odd number, a single \n should be appended as padding (and the file size as recorded in the header is NOT incremented to include the padding byte).
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
So I have this bit of C code below. When I place printf statements to test the text from the input file, I see that I'm getting a bunch of junk values, to be more specific they are not even alphabetic or numerical, I think they are diamonds with question marks in them. I assume this means it is not processing these values the way it should be. The input file a bit of MIPS assembly code, but in this context it is only a text file. I have commented out all other parts of my program and am left with this small piece and yet I still receive the bad values. What could I possibly be doing wrong here?
The command I use to run the program on the console is:
./assembler -symbols adder.asm
Where ./assembler is the driver (argv[0])
-symbols is a tag used (argv[1])
adder.asm is the input file (argv[2])
So once opened I should be able to grab text out of this file, and it's not a problem with the file as far as I believe, it was working earlier.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
FILE *fp;
FILE *fp_out;
void main(int argc, char* argv[])
{
int mode;
if (strcmp(argv[1], "-symbols") == 0)
{
fp = fopen(argv[2], "r");
mode = 1;
}
else
{
fp = fopen(argv[1], "r");
fp_out = fopen(argv[2], "w");
mode = 2;
}
}
Try to add the following line right after the open section and add #include <errno.h> to the beginning.
printf("%p, %p, %d\n", fp, ftp_out, errno);
If the fp is null then there is some problem opening the file. If you do not check the return value, you can read from a wrong buffer. Maybe there is some permission problems (or whatever). Also if errno != 0 you have a problem. Check with perror <num> the errno value in command line (or see perror(3) function).