I need to print the names of all files in the current directory.
but I must do it only with system calls, so I have the SYS_OPEN, SYS_GETDENTS, SYS_READ etc. I'm working on Ubuntu.
How can I do it?
I tried to use this:
system_call(SYS_OPEN, ".", 0, 0777);
and then to READ from and write to STDOUT.. but it's not working.
** I cannot use the standard library.
Thank you!
EDIT:
an example code:
** there is a file in assembly, with the function "system call" that do the call.
#include "util.h"
#define SYS_WRITE 4
#define SYS_OPEN 5
#define SYS_CLOSE 6
#define SYS_READ 3
#define SYS_LSEEK 19
#define SYS_GETDENTS 141
#define BUF_SIZE 1024
#define STDOUT 1
struct linux_dirent {
long d_ino;
int d_off;
unsigned short d_reclen;
char d_name[];
};
int main (int argc , char* argv[], char* envp[])
{
int fd=0;
int nread;
char * nread_str;
char buf[BUF_SIZE];
struct linux_dirent *d;
int bpos;
char d_type;
fd=system_call(SYS_OPEN,".", 0 , 0);
for ( ; ; ) {
nread = system_call(SYS_GETDENTS, fd, buf, BUF_SIZE);
if (nread == -1)
system_call(SYS_WRITE,STDOUT, "error-getdents",BUF_SIZE);
if (nread == 0)
break;
system_call(SYS_WRITE,STDOUT, "--------------- nread=%d ---------------\n",100);
nread_str=itoa(nread);
system_call(SYS_WRITE,STDOUT, nread_str,100);
system_call(SYS_WRITE,STDOUT, "i-node# file type d_reclen d_off d_name\n",100);
for (bpos = 0; bpos < nread;) {
d = (struct linux_dirent *) (buf + bpos);
/* printf("%8ld ", d->d_ino);**/
d_type = *(buf + bpos + d->d_reclen - 1);
/* printf("%4d %10lld %s\n", d->d_reclen,
(long long) d->d_off, (char *) d->d_name);**/
bpos += d->d_reclen;
}
}
}
return 0;
}
#include <fstream>
#include <iostream>
#include <string>
#include <dirent.h>
using namespace std;
int main()
{
DIR *dir;
struct dirent *ent;
if ((dir = opendir ("c:\\")) != NULL) {
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL) {
printf ("%s\n", ent->d_name);
}
closedir (dir);
} else {
/* could not open directory */
perror ("");
return EXIT_FAILURE;}
}
Read the manual pages for opendir etc.
See http://linux.die.net/man/3/opendir
Related
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
void cp(char* src, char* dest)
{
int infile, outfile;
const int BUFF_SIZE = 65536;
struct stat instats, outstats;
long bytes;
char *buff;
/* Open source and destination files */
if ((infile = open(src, O_RDONLY)) == -1) exit(1);
if ((outfile = open(dest, O_WRONLY | O_APPEND | O_CREAT)) == -1) exit(1);
/* Calculate optimal buffer size */
//fstat(infile, &instats);
//fstat(outfile, &outstats);
//optimal = LCM(instats.st_blksize, outfile.st_blksize);
//buff_size = MIN(optimal, 65536);
buff = (char*)malloc(sizeof(char) * BUFF_SIZE);
/* Copy file */
while((bytes = read(infile, buff, BUFF_SIZE)) > 0)
write(outfile, buff, bytes);
close(infile);
close(outfile);
free(buff);
}
int main()
{
DIR* dirp;
dirp = opendir(".");
if(dirp == NULL) exit(1);
else
{
struct dirent* dentry;
dentry = readdir(dirp);
while(dentry != NULL)
{
struct stat fst;
int statr = stat(dentry->d_name, &fst);
char* src = (char*)malloc(sizeof(char) * (2 + 1024));
src = strcpy(src, "./");
src = strcat(src, dentry->d_name);
//printf("%s", src);
if(!statr)
{
if(S_ISREG(fst.st_mode))
{
printf("NAME: %s\n", src);
cp(src, "archive");
}
}
dentry = readdir(dirp);
free(src);
}
}
return 0;
}
This is my current code. I want to take all regular files in the working directory and append their contents to a file called "archive" so that they may be recreated from the archive file. I don't quite know what is going wrong as I am opening the archive file with O_APPEND flag and the data I'm attempting to write is not appending to the file.
The problem I'm running into is that when the file tries to copy, it only copies part of the file and the other part is a bunch of unreadable characters. This is for an academic assignment that wants us to use barrier synchronization so we need to use open, write, and read.
I've reworked the thread function many times but if it's the problem I can change it again, I haven't changed the for loop in main at all so even that might be the problem but I don't know what it could be. Lastly, I don't really know what to do with the barrier; my professor was very vague and I can't really ask him questions, maybe the barrier is the part that I'm truly missing.
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
typedef struct args {
int fd;
int copy;
long int start;
long int size;
}threadarg;
int barrier = 0;
int main(int argc, char *argv[])
{
void usage(char *progname);
int chkdst(char **argv);
void die(char *why);
long int filesize(char *srcpath);
void buildpath(char *src, char *dst, char **dstpath);
int isvalid(char *path, char *dst);
void *dowork(void *arg);
if (argc < 4) usage("a8");
int workers, i;
char *check;
workers = strtol(argv[3], &check, 10);
if (!check) usage("a8");
else if (!chkdst(&argv[2])) die ("DST not valid!");
long int size = filesize(argv[1]);
if (size == -1) die ("Could not find file size");
char *dstpath; buildpath(argv[1], argv[2], &dstpath);
if (!isvalid(argv[1], dstpath)) die ("scr not valid!");
long int chunksize = size / workers;
long int remainder = size % workers;
int fd = open(argv[1], O_RDONLY);
int copy = open(dstpath, O_CREAT | O_RDWR, 0644);
if (fd < 0 || copy < 0) die("Fail to access or create files");
barrier = workers;
threadarg threadargs[workers];
pthread_t threads[workers];
for (i = 0; i < workers; i++)
{
threadargs[i].fd = fd;
threadargs[i].copy = copy;
threadargs[i].start = i * chunksize;
if (i == workers - 1)
threadargs[i].size = chunksize + remainder;
else
threadargs[i].size = chunksize;
if (pthread_create(&threads[i], NULL, dowork, (void *) &threadargs[i]))
die("Thread Creation Failure");
}
for (i = 0; i < workers; i++)
pthread_join(threads[i], NULL);
}
void usage(char *progname)
{
fprintf(stderr, "./%s srcpath dstpath workercount\n", progname);
exit(0);
}
void die(char *why)
{
fprintf(stderr, "Program Killed...\nReason: %s\n", why);
exit(1);
}
long int filesize(char *srcpath)
{
struct stat st;
if(stat(srcpath, &st) != 0) return 0;
return st.st_size;
}
/*
void domd5(char *path)
{
}
*/
void *dowork(void *arg)
{
threadarg *args = (threadarg *)arg;
int fd = args->fd,
copy = args->copy, rd;
long int start = args->start,
size = args->size;
char bufs[2048], *remains;
lseek(fd, start, SEEK_SET);
lseek(copy, start, SEEK_SET);
printf("%d thread with offset %ldKB, reached barrier\n", (int) pthread_self(), start);
barrier--;
while (barrier > 0);
long int count = 0, remainder = 0, i;
for (i = 0; i < size; i += 2048)
{
if (i + 2048 > size)
{
remainder = size - count;
remains = malloc(remainder * sizeof(char));
rd = read (fd, remains, sizeof(remains));
if (write(copy, remains, rd) != rd)
die("Error accessing files during copy");
count += remainder;
}
else
{
rd = read(fd, bufs, sizeof(bufs));
if (write(copy, bufs, rd) != rd)
die("Error accessing files during copy");
count += 2048;
}
}
pthread_exit(NULL);
}
/* Takes a single pointer, *argv, and passes it to isdir()
to check if the directory exists. If isdir returns a 1 a
1 is returned from this module. Otherwise, an error message
is printed and a 0 is returned.
Calls isdir().
Called by main().
*/
int chkdst(char **argv)
{
int isdir(char *path);
if (isdir(*argv)) return 1;
return 0;
}
/* Uses the Stat struct to construct a struct, sbuf,
and uses stat() to obtain information from the file and
write it to sbuf. Uses S_ISDIR() on sbuf.st_mode to see
the mode of the file. A 1 is returned if the file is a
directory otherwise a 0 is returned.
Called by isvalid().
*/
int isdir(char *path)
{
struct stat sbuf;
if (stat(path, &sbuf)) return 0;
return S_ISDIR(sbuf.st_mode);
}
/* Uses the Stat struct to construct a struct, sbuf,
and uses stat() to obtain information from the file and
write it to sbuf. Uses S_ISREG on sbuf.st_mode to see if
the file is regular. A 1 is returned if the S_ISREG is true
otherwise a 0 is returned.
Called by isvalid().
*/
int isregular(char *path)
{
struct stat sbuf;
if (stat(path, &sbuf)) return 0;
return S_ISREG(sbuf.st_mode);
}
/* Checks if the source path is a directory first, then if its
a regular file return 0 if it is dir and if it isn't a regular
file, then checks if the destionation path was created or if
the file exist at the destination if either return 0, if none
of these return 1.
Calls isdir() and isregular().
Called by copyfiles().
*/
int isvalid(char *path, char *dst)
{
if (isdir(path))
{
return 0;
}
else if (!isregular(path))
{
return 0;
}
else if (dst == NULL)
{
return 0;
}
else if (isregular(dst))
{
return 0;
}
return 1;
}
/* Builds destination-path using strrchr() function from library,
dstpath is null on error and defined otherwise. The src file has
its original destination removed and replaced with the new one if
it has a original destination on it otherwise it is just added to
the end of the existing name of the file.
Called by copyfiles().
*/
void buildpath(char *src, char *dst, char **dstpath)
{
char *ptr;
int n;
ptr = strrchr(src, '/');
if (ptr) n = strlen(dst) + strlen(ptr) + 2;
else n = strlen(dst) + strlen(src) + 2;
*dstpath = malloc(n);
if (!dstpath) return;
if (ptr)
{
strcpy(*dstpath, dst);
strcat(*dstpath, ptr);
}
else
{
strcpy(*dstpath, dst);
strcat(*dstpath, "/");
strcat(*dstpath, src);
}
}
This question already has answers here:
When using regex in C, \d does not work but [0-9] does
(4 answers)
Closed 3 years ago.
In the following code, I am trying to filter out using regex ONLY, the file called test.jpg, what am I doing wrong as the code below is not filtering this out?
I know there are simpler ways, but eventually I would like to change the regex to ^(image_)\\d{3,6}_201412\\d{2}_\\d{6}\\.(jpg)
and also my folder contains 100,000+ files, so I can only use the c getdents function which is super fast compared to any other way
I get the following output:
**************found*******
image_0179_20141212_060714.jpg
#define _GNU_SOURCE
#include <dirent.h> /* Defines DT_* constants */
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <string.h>
#include <regex.h>
#include <stdio.h>
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct linux_dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[];
};
#define BUF_SIZE 1024*1024*5
int
main(int argc, char *argv[])
{
int fd, nread;
char buf[BUF_SIZE];
struct linux_dirent *d;
int bpos;
char d_type;
regex_t reg;
regmatch_t pmatch[40];
#define NAME "image_0179_20141212_060714.jpg"
const char *pattern = "^(image_)\\d{3,6}_201412\\d{2}_\\d{6}\\.(jpg)";
regcomp(®, pattern, REG_ICASE | REG_EXTENDED);
int retval = 0;
char buffer[1024] = "";
fd = open(argc > 1 ? argv[1] : ".", O_RDONLY | O_DIRECTORY);
if (fd == -1)
handle_error("open");
for ( ; ; )
{
nread = syscall(SYS_getdents, fd, buf, BUF_SIZE);
if (nread == -1)
handle_error("getdents");
if (nread == 0)
break;
for (bpos = 0; bpos < nread;)
{
d = (struct linux_dirent *) (buf + bpos);
d_type = *(buf + bpos + d->d_reclen - 1);
if( d->d_ino != 0 && d_type == DT_REG )
{
//printf("%s\n", (char *)d->d_name );
if (strstr(d->d_name, NAME) != NULL)
{
printf("**************found*******\n");
printf("%s\n", (char *)d->d_name );
};
retval = regexec(®, d->d_name, 2, pmatch, 0);
//printf("%d\n",retval);
if(retval==0)
{
printf("**************found regex*******\n");
printf("%s\n", (char *)d->d_name );
}
}
bpos += d->d_reclen;
}
}
regfree(®);
exit(EXIT_SUCCESS);
}
use the following regex instead
^image_[0-9]{3,6}_201412[0-9]{2}_[0-9]{6}\.jpg$
My C code for recursively listing directories and files get executed multiple times. I am not sure how to fix it and why it keeps happening... It is not infinite its just like 10 times shows the current directory.
void printdir(char *dir, int depth)
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;
int spaces = depth;
dp = opendir(dir);
while((entry = readdir(dp))) {
lstat(entry->d_name,&statbuf);
if(S_ISDIR(statbuf.st_mode)) {
/* Found a directory, but ignore . and .. */
if(strcmp(".",entry->d_name) == 0 ||
strcmp("..",entry->d_name) == 0)
continue;
printf("%*s%s/\n",spaces,"",entry->d_name);
/* Recurse at a new indent level */
printdir(entry->d_name,depth+1);
}
else printf("%*s%s\n",spaces,"",entry->d_name);
}
closedir(dp);
}
int print_file(char *file, char *dir, struct stat buf, int showinode, int showlong, int showRec)
{
if (showinode)
printf("%lld ", buf.st_ino);
if (showlong)
print_long(file, dir, buf);
if (showRec)
printdir(dir, 0);
else
printf("%s\n", file);
return 0;
}
Here's a recursive function that lists the directories it comes across, using openat(), fdopendir(), fstatat() to avoid string-operations on paths (and, possibly, race-conditions on the directory-tree):
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int sanerecursivedirsearch(int dirfd)
{
DIR *curdir = fdopendir(dirfd);
if (!curdir)
{
perror("fdopendir()");
close(dirfd);
return -1;
}
struct dirent *direp;
while (!!(direp = readdir(curdir)))
{
if (!strcmp(direp->d_name, "..") || !strcmp(direp->d_name, "."))
continue;
struct stat statbuf;
fstatat(dirfd, direp->d_name, &statbuf, 0);
if (S_ISDIR(statbuf.st_mode))
{
int newfd = openat(dirfd, direp->d_name,
O_RDONLY | O_DIRECTORY);
if (newfd == -1)
{
perror("openat()");
continue;
}
printf("directory found:\t%s\n", direp->d_name);
sanerecursivedirsearch(newfd);
}
}
closedir(curdir);
return 0;
}
int main(int argc, char **argv)
{
if (argc < 2)
{
fprintf(stderr, "insufficient command-line arguments");
exit(EXIT_FAILURE);
}
int fd = openat(AT_FDCWD, argv[1],
O_RDONLY | O_DIRECTORY);
if (fd == -1)
{
perror("openat()");
exit(EXIT_FAILURE);
}
sanerecursivedirsearch(fd);
return 0;
}
I am new in C programming
Here i want to detect USB is inserted or not in Linux
I want to detect this things on my embedded linux device. which have customized linux.
So i want to detect the block of USB where i have to mount this block. like sda,sdb or sdc.
I want to o this thing in C programming for linux.
Here i have path for usb devices /sys/bus/usb/devices
i can see usb information is available is here /sys/bus/usb/devices/1-x
so i want to fetch the address of block where this usb is inserted like sda,sdb or sdc.
So now after fetching this address name i have to mount usb on particular path.
so can anybody please suggest me how can i detect usb is inserted or not if inserted than how can i know address of this
Set up a hotplug event handler: You will get a hotplug block event when a block device appears or goes away, which you can use to mount/umount and run your handler scripts and apps.
Udisk can meet your needs, but You should have some understanding of the D-Bus.
And the d-bus daemon should run in you embedded linux first.
the follows I write is to detect udisk program before I known D-Bus. It's very bad, But may be give your prompt.
key path: "/dev/disk/by-uuid"
key file: "/etc/mtab"
This show how to mount the udisk by comparing them.
/*
* This program demonstrates method
* detect U disk and mount it
* if main exit umount it
*
* note: run as root
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
int main(int argc, char *argv[])
{
char *dirpath;
char *filename;
dirpath = "/dev/disk/by-uuid";
filename = "/etc/mtab";
//step 1. open dir and file
DIR *dirp;
FILE *mtab;
//FILE *fopen(const char *path, const char *mode);
if((mtab = fopen(filename, "r")) == NULL){
fprintf(stderr, "open %s failed\n", filename);
exit(1);
}
//DIR *opendir(const char *name);
if((dirp = opendir(dirpath)) == NULL){
fprintf(stdout, "opendir %s failed\n", dirpath);
exit(1);
}else{
fprintf(stdout, "opendir %s successfully\n", dirpath);
}
//step 1.5 show content of dirpath
#if 0
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported
by all file system types */
char d_name[256]; /* filename */
};
#endif
struct dirent *direntp;
errno = 0;
//struct dirent *readdir(DIR *dirp);
while((direntp = readdir(dirp)) != NULL){
fprintf(stdout, "%s\n", direntp->d_name);
}
if(errno != 0){
perror("readdir failed");
exit(1);
}
//void rewinddir(DIR *dirp);
rewinddir(dirp);
//step 1.6 get mounted device name
char mdev[64][255];
int i;
int devnum;
i = 0;
//int fscanf(FILE *stream, const char *format, ...);
while(fscanf(mtab, "%s", mdev[i]) != EOF){
//int getc(FILE *stream);
while(getc(mtab) != '\n')
;
//int strncmp(const char *s1, const char *s2, size_t n);
if(strncmp(mdev[i], "/dev/sd", 7) == 0 &&
strncmp(mdev[i], "/dev/sda", 8) != 0){
fprintf(stdout, "mdev: %s\n", mdev[i]);
i++;
}
}
strncpy(mdev[i], "", 1);
//step 2. check content
char buf[255];
char path[255];
char cmd[255];
char *p;
int flag; /* if 0 not mount, if 1 mount */
devnum = i;
errno = 0;
//struct dirent *readdir(DIR *dirp);
while((direntp = readdir(dirp)) != NULL){
flag = 1;
if(direntp->d_name[0] == '.'){ /* remove . and .. */
continue;
}
//int snprintf(char *str, size_t size, const char *format, ...);
snprintf(path, sizeof(path) - 1, "%s/%s",dirpath, direntp->d_name);
//ssize_t readlink(const char *path, char *buf, size_t bufsiz);
if(readlink(path, buf, sizeof(buf) - 1) < 0){
perror("readlink failed");
exit(1);
}
p = strrchr(buf, '/');
if(p != NULL && strncmp(p, "/sda", 4) != 0){ /* remove sda* */
//char *strchr(const char *s, int c);
snprintf(path, sizeof(path) - 1, "/dev%s", p);
fprintf(stdout, "step 2. %s, devnum = %d\n", path, devnum);
for(i = 0; i < devnum; i++){ /* check mount */
if(strcmp(mdev[i], path) == 0){
flag = 0;
break;
}
}
//step 3. mount umounted usb
if(flag == 1){
fprintf(stdout, "need mount %s\n", path);
//int snprintf(char *str, size_t size, const char *format, ...);
snprintf(cmd, sizeof(cmd) - 1, "sudo mount %s /mnt", path);
if(system(cmd) < 0){
fprintf(stderr, "system() %s failed: %s\n",
path, strerror(errno));
}
}
}
}
if(errno != 0){
perror("readdir failed");
exit(1);
}
sleep(10);
//step 4. umount usb
//int snprintf(char *str, size_t size, const char *format, ...);
snprintf(cmd, sizeof(cmd) - 1, "sudo umount /mnt");
if(system(cmd) < 0){
fprintf(stderr, "system() %s failed: %s\n",
path, strerror(errno));
}
//step 5. close dir
//int closedir(DIR *dirp);
closedir(dirp);
fclose(mtab);
return 0;
}