I need to delete a directory in a given path using unlinkat(), the program runs fine but it doesn't delete (unlink) the directory (is empty by the way). Using the man7 documentation for unlinkat() I have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <dirent.h>
#include <fcntl.h>
void main(int argc,char *argv[]){
DIR *dirp;
if ((dirp = opendir(argv[1]))== NULL){
fprintf(stderr, "Couldn't open the directory %s: %s \n",argv[1],strerror(errno) );
exit(1);
}
unlinkat(dirp,argv[1],AT_REMOVEDIR);
exit(0);
}
The path given in the arguments is relative from the father of the folder I want to erase
Your dirp is a pointer to a directory handle (DIR *), but the first argument to unlinkat() must be a directory descriptor, or AT_FDCWD (for "current working directory"). This is clearly stated in the unlinkat() man page.
You should always enable compiler warnings (-Wall for gcc). It would have pointed you to the problem in this case, too.
To get hold of the underlying descriptor for dirp, use dirfd(dirp).
Here is an actual example. It removes the (empty) directories specified in the second and further parameters, relative to the directory/path specified as the first parameter. The directory specified in the first parameter is not removed.
#define _POSIX_C_SOURCE 200809L
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
int main(int argc, char *argv[])
{
DIR *dirp;
int arg, retval;
if (argc < 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
fprintf(stderr, " %s BASE-DIRECTORY ITEM-TO-REMOVE ...\n", argv[0]);
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
dirp = opendir(argv[1]);
if (!dirp) {
fprintf(stderr, "%s: %s.\n", argv[1], strerror(errno));
return EXIT_FAILURE;
}
retval = EXIT_SUCCESS;
for (arg = 2; arg < argc; arg++) {
if (unlinkat(dirfd(dirp), argv[arg], AT_REMOVEDIR)) {
fprintf(stderr, "%s: %s.\n", argv[arg], strerror(errno));
retval = EXIT_FAILURE;
}
}
closedir(dirp);
return retval;
}
Related
Is there a way I can rewrite the following code which reproduce the functionality of the grep command in linux, in less lines of code? Or is there something I can make to save some memory or yo make the code even more efficient?
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <error.h>
#include "ourhdr.h"
#define size 1024
int main(int argc, char **argv)
{
char fis[100],car[10],buff[size];
FILE *file;
if(argc!=3)
{
printf("Not all parameters were given <./a.out> <char> <numefisier>\n");
}
else
{
file=fopen(argv[2],"r");
if (file==NULL)
{
err_ret("Fisierul sursa nu exista %s", argv[2]);
exit(0);
}
strcpy(fis,argv[2]);
strcpy(car,argv[1]);
while((!feof(file)))
{
while(fgets(buff,size,file)!=NULL)
{
if(strstr(buff,car))
printf("%s \n",buff);
}
}
fclose(file);
}
return 0;
}
When I run:
ls -l /proc/123/fd/80
I can see for example:
89-> socket:[38676]
How can I get this information in C? How can I know that this fd point to a socket/pipe and get the number inside the brackets (the 38676 between [ ])
By the way, is the number between brackets the size of buffer's socket?
man fstat will give you all the documentation you need.
The man page gives an example you can easily adapt:
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
struct stat sb;
if (argc != 2) {
fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (stat(argv[1], &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
if (S_IFSOCK != (sb.st_mode & S_IFMT)) {
printf("Not a socket.\n");
exit(EXIT_FAILURE);
}
printf("socket: %ld\n", (long) sb.st_ino);
exit(EXIT_SUCCESS);
}
I want to check if two device files are equal in C, without accessing the underlying devices.
Can this be done using stat and lstat?
To determine if two device files are the same, call stat on each of them, and check that they're both the same type of device (block or character) and that their .st_rdev members are equal.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
int main(int arc, char **argv)
{
struct stat s1, s2;
char *err;
if (stat(argv[1], &s1) < 0) {
err = strerror(errno);
fprintf(stderr, "Can't stat %s: %s\n", argv[1], err);
exit(1);
}
if (stat(argv[2], &s2) < 0) {
err = strerror(errno);
fprintf(stderr, "Can't stat %s: %s\n", argv[2], err);
exit(1);
}
if (S_ISCHR(s1.st_mode) && S_ISCHR(s2.st_mode) && s1.st_rdev == s2.st_rdev) {
printf("Same char device\n");
exit(0);
}
if (S_ISBLK(s1.st_mode) && S_ISBLK(s2.st_mode) && s1.st_rdev == s2.st_rdev) {
printf("Same block device\n");
exit(0);
}
printf("devices do not match\n");
exit(1);
}
Have you looked at stat structure? You can find the size of a file, and many many things. .st_dev should works in your case.
I am trying to read a path from the cmd line and then run the 'ls' cmd to print only the hidden files and their long information in the path specified, and then to a text file. My problem is that 'ls' returns:
ls: illegal option --
ls: illegal option -- .
ls: illegal option -- ?
ls: illegal option -- *
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define NUMARG 2
/* start main */
int main(int argc, char *argv[]){
/* define data */
DIR *dirptr;
struct dirent *dp;
int pid;
int fd = open("output_file", O_WRONLY|O_CREAT, 0666);
/* Command Line Check */
if(argc != NUMARG){
fprintf(stderr, "usage: %s dirname\n", argv[0]);
exit(1);
}
/* Open the specified directory */
if((dirptr = opendir(argv[1])) == NULL){
fprintf(stderr, "Could not open directory %s\n", argv[1]);
exit(1);
}
/* fork another process */
switch(pid = fork()){
/* succesfull child process */
case 0:
dup2(fd, 1);
close(fd);
printf("Running ls\n");
execlp( "ls", "ls" , "-ld .?*", argv[1], (char*)NULL);
perror("execlp");
exit(1);
default:
sleep(5);
printf("Hitting default...\n");
break;
case -1:
perror("err");
exit(1);
}
}
Run ls through a shell
execlp("/bin/sh", "/bin/sh", "-c", "ls -l .?*", (char *) NULL);
that way you get access to shell wildcards.
did you try splitting the args like that:
execlp( "ls", "ls" , "-ld", ".?*", argv[1], (char*)NULL); // does not work due to ".?*" has to be expanded by bash
Use find instead of ls:
execlp( "find", "find", argv[1], "-maxdepth", "1", "-name", ".?*", (char*)NULL);
Just a hint: here's one possible sample - this part of code should do the listing of invisible files from the current directory...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char s [256] ;
strcat(s, "ls -ld .?*");
system(s);
return 0;
}
I'm writing a code for printing out the path from root to current directory or referred directory, using recursive function. but I can't get the directory name, only get ..
Problem happened among base case and call
dirent->name.
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
static void list_dir (const char * dir_name)
{
DIR * d;
struct dirent *e;
struct stat sb;
struct stat sb2;
long childIno;
long parentIno;
char parent[200];
stat(dir_name, &sb);
if (stat(dir_name, &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
childIno = (long) sb.st_ino;
/* get parent dir name */
snprintf(parent, sizeof(parent), "%s/..", dir_name);
d = opendir(parent);
stat(parent, &sb2);
if (stat(parent, &sb2) == -1) {
perror("stat2");
printf("parent name: \n");
exit(EXIT_FAILURE);
}
parentIno = (long) sb2.st_ino;
if (d == NULL) {
printf("Cannot open dircetory '%s'\n", parent);
}
/*below code is really messed up*/
if (childIno == parentIno) {
while ((e = readdir(d)) != NULL) {
printf("base case %s\n", e->d_name);
break;
}
}else{
list_dir(parent);
}
/*code above here is really messed up*/
/* After going through all the entries, close the directory. */
closedir (d);
}
int main (int argc, char** argv)
{
list_dir (argv[1]);
return 0;
}
right result should be when typing command line
./pathto .
should print out path from root directory to my current directory
or if command line as this
./pathto file.txt
should print out path from root directory to file.txt
Doing this using <dirent.h> and stat is possible, but really tricky. POSIX offers a function for this called realpath. Omitting error checking:
#include <limits.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char buf[PATH_MAX];
puts(realpath(argv[1], buf));
return 0;
}