LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-02-2012, 08:34 AM   #1
akshay_satish
Member
 
Registered: May 2011
Posts: 63

Rep: Reputation: Disabled
file existnse


Hi Guys, I seem to stumble upon something really weird.
Code:
char a[512] = "";
char *dir = NULL;
int k;

if(NULL == dir) {
sprintf(a, "%s/%s", <#def1>,<#def2>);
}

if(access(a, F_OK) == 0) {
k = unlink(a);
if(k != 0) {
printf("unable to del. file %s: %d(%s).\n", a, errno, strerror(errno));
}
}

The output I am getting is ->
unable to del. file /: 2(No such file or directory).

errno 2 indicates ENOENT which is no such file or directory.
Any idea why the o/p is showing the filename as "/" (thoughts??).
Also, i am wondering how it executed the printf(....) statement. If the filename was infact "/", it shouldn't have even tried the "unlink" operation according to the code logic right? It should have exit'd the "if" condition right after "access()".
Kindly help....

Last edited by akshay_satish; 11-02-2012 at 10:48 AM.
 
Old 11-02-2012, 08:47 AM   #2
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by akshay_satish View Post
Kindly help....
I'm not sure how you were able to get the output you describe based on the code you posted. Surely there must be more to your application than you are indicating. For example, how is the array 'a' ever populated with something other than a Null-string?

Here's a complete program that mimics what you have posted, and it functions correctly.

Code:
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char** argv)
{
    const char* pathname = "";

    if (argc > 1)
    {
        pathname = argv[1];
    }

    if (access(pathname, F_OK) == 0)
    {
        fprintf(stdout, "File %s is accessible.\n", pathname);

        if (unlink(pathname) == 0)
        {
            fprintf(stdout, "File %s has been removed.\n", pathname);
        }
        else
        {
            fprintf(stderr, "Unable to unlink (delete) file %s; reason -- %s [%d]\n", pathname, strerror(errno), errno);
        }
    }
    else
    {
        fprintf(stderr, "Failed to access file '%s'; reason -- %s [%d]\n", pathname, strerror(errno), errno);
    }

    return 0;
}
P.S. Under Linux, a file and a directory can be considered to be the same with respect to being "accessible". If you are looking to delete only files (and not directories), then I suggest you use stat() to determine the attributes of the file (ie. file type, permissions, etc.)

Last edited by dwhitney67; 11-02-2012 at 08:52 AM.
 
Old 11-02-2012, 09:26 AM   #3
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,659
Blog Entries: 4

Rep: Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941Reputation: 3941
An empty file-name could possibly be interpreted as "/" but in any case it's a nonsensical situation as-writ.
 
Old 11-02-2012, 10:07 AM   #4
akshay_satish
Member
 
Registered: May 2011
Posts: 63

Original Poster
Rep: Reputation: Disabled
Thank you DWhitney.. Yes the intent is to delete a file. I think doing a "stat" would be better as you mentioned... Yes in the first few lines of the function there is a do while loop within which if this file "a" is NULL then we break out of the loop and hit the deletion code which I've pasted above.
This confirms the issue right?
thanks again dWhitney. ur thoughts are just priceless..cheerio

Last edited by akshay_satish; 11-02-2012 at 10:15 AM.
 
Old 11-02-2012, 10:35 AM   #5
akshay_satish
Member
 
Registered: May 2011
Posts: 63

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by dwhitney67 View Post
I'm not sure how you were able to get the output you describe based on the code you posted. Surely there must be more to your application than you are indicating. For example, how is the array 'a' ever populated with something other than a Null-string?

Here's a complete program that mimics what you have posted, and it functions correctly.

Code:
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char** argv)
{
    const char* pathname = "";

    if (argc > 1)
    {
        pathname = argv[1];
    }

    if (access(pathname, F_OK) == 0)
    {
        fprintf(stdout, "File %s is accessible.\n", pathname);

        if (unlink(pathname) == 0)
        {
            fprintf(stdout, "File %s has been removed.\n", pathname);
        }
        else
        {
            fprintf(stderr, "Unable to unlink (delete) file %s; reason -- %s [%d]\n", pathname, strerror(errno), errno);
        }
    }
    else
    {
        fprintf(stderr, "Failed to access file '%s'; reason -- %s [%d]\n", pathname, strerror(errno), errno);
    }

    return 0;
}
P.S. Under Linux, a file and a directory can be considered to be the same with respect to being "accessible". If you are looking to delete only files (and not directories), then I suggest you use stat() to determine the attributes of the file (ie. file type, permissions, etc.)
I populated the pathname with "/" and performed a stat instead of access but it still hit the unlink's else case. can i know a little more about wht you were saying pls?

Last edited by akshay_satish; 11-02-2012 at 10:50 AM.
 
Old 11-02-2012, 01:18 PM   #6
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by akshay_satish View Post
I populated the pathname with "/" and performed a stat instead of access but it still hit the unlink's else case. can i know a little more about wht you were saying pls?
stat() can tell you if a file (or directory) exists based on its return value. However, you should pass a 'struct stat' object to the function to obtain additional information about the file you are querying about. For example:
Code:
#include <errno.h>
#include <string.h>
#include <stdio.h>

int main()
{
    const char* pathname = "/";
    struct stat pathInfo;

    if (stat(pathname, &pathInfo) == 0)
    {
        if (S_ISDIR(pathInfo.st_mode))
        {
            fprintf(stdout, "pathname '%s' is a directory.\n", pathname);
        }
        else if (S_ISREG(pathInfo.st_mode))
        {
            fprintf(stdout, "pathname '%s' is a regular file.\n", pathname);
        }
        else /* ... */
        {
            /* ... */
        }
    }
    else
    {
        fprintf(stderr, "Cannot obtain status about '%s'; reason -- %s [%d]\n",
                pathname, strerror(errno), errno);
    }

    return 0;
}
For more comprehensive information about stat(), it actually is more helpful to read the man-page for fstat().
 
Old 11-05-2012, 12:11 AM   #7
akshay_satish
Member
 
Registered: May 2011
Posts: 63

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by dwhitney67 View Post
stat() can tell you if a file (or directory) exists based on its return value. However, you should pass a 'struct stat' object to the function to obtain additional information about the file you are querying about. For example:
Code:
#include <errno.h>
#include <string.h>
#include <stdio.h>

int main()
{
    const char* pathname = "/";
    struct stat pathInfo;

    if (stat(pathname, &pathInfo) == 0)
    {
        if (S_ISDIR(pathInfo.st_mode))
        {
            fprintf(stdout, "pathname '%s' is a directory.\n", pathname);
        }
        else if (S_ISREG(pathInfo.st_mode))
        {
            fprintf(stdout, "pathname '%s' is a regular file.\n", pathname);
        }
        else /* ... */
        {
            /* ... */
        }
    }
    else
    {
        fprintf(stderr, "Cannot obtain status about '%s'; reason -- %s [%d]\n",
                pathname, strerror(errno), errno);
    }

    return 0;
}
For more comprehensive information about stat(), it actually is more helpful to read the man-page for fstat().
Thank you very much. Really appreciate your timely help~ cheerio.
 
Old 11-05-2012, 04:22 AM   #8
akshay_satish
Member
 
Registered: May 2011
Posts: 63

Original Poster
Rep: Reputation: Disabled
Hi Dwhitney67, i really appreciate your timely response. I have one more connected problem that I need some pointers. Pls assist:

In my header file I have a macro defined as;
Code:
#define QWE 1
....
#ifdef QWE
    #define ABC(params...) {
    fprintf(stderr, params);
    }
#else
    #define ABC(params...) {
    /*writes to a file*/
    }
#endif
....
Now in my C file, I use another macro to log statements either onto the console or into a file.

Code:
void abc() {
....
ABC("something\n");
....
}

int main()
{
abc();
}
From the above code logic, when abc() is called in main(), "something" is printed onto the console due to "STDERR". I need to find a way to log the line to the trace file without actually changing QWE to 0 in the #define. I have a switch case within which each case statements log to the stderr because of the QWE = 1 value. I need to print to the file only for one particular case. I hope u got my intent? Appreciate your response.
 
Old 11-05-2012, 11:17 AM   #9
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
fprintf() can be used to write to stdout, stderr, or any other stream (such as a file).

So I'm not sure why you require different implementations for the ABC() function, unless you are doing something drastically different when writing to a file (for example, in lieu of writing the data in ASCII format, you are writing it in binary).

So, if you are not doing anything different, then implement something like the following:
Code:
void ABC(FILE* stream, params...)
{
   fprintf(stream, ...);
}

void abc(FILE* stream)
{
    ...

    ABC(stream, ...);

    ...
}

int main()
{
    abc(stderr);

    FILE* myFile = fopen("SomeFile.txt", "w+");

    abc(myFile);

    fclose(myFile);
}
 
Old 11-05-2012, 11:45 PM   #10
akshay_satish
Member
 
Registered: May 2011
Posts: 63

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by dwhitney67 View Post
fprintf() can be used to write to stdout, stderr, or any other stream (such as a file).

So I'm not sure why you require different implementations for the ABC() function, unless you are doing something drastically different when writing to a file (for example, in lieu of writing the data in ASCII format, you are writing it in binary).

So, if you are not doing anything different, then implement something like the following:
Code:
void ABC(FILE* stream, params...)
{
   fprintf(stream, ...);
}

void abc(FILE* stream)
{
    ...

    ABC(stream, ...);

    ...
}

int main()
{
    abc(stderr);

    FILE* myFile = fopen("SomeFile.txt", "w+");

    abc(myFile);

    fclose(myFile);
}
cool! that was a silly question that shouldnt have been asked. Sorry!
 
Old 11-05-2012, 11:55 PM   #11
akshay_satish
Member
 
Registered: May 2011
Posts: 63

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by dwhitney67 View Post
stat() can tell you if a file (or directory) exists based on its return value. However, you should pass a 'struct stat' object to the function to obtain additional information about the file you are querying about. For example:
Code:
#include <errno.h>
#include <string.h>
#include <stdio.h>

int main()
{
    const char* pathname = "/";
    struct stat pathInfo;

    if (stat(pathname, &pathInfo) == 0)
    {
        if (S_ISDIR(pathInfo.st_mode))
        {
            fprintf(stdout, "pathname '%s' is a directory.\n", pathname);
        }
        else if (S_ISREG(pathInfo.st_mode))
        {
            fprintf(stdout, "pathname '%s' is a regular file.\n", pathname);
        }
        else /* ... */
        {
            /* ... */
        }
    }
    else
    {
        fprintf(stderr, "Cannot obtain status about '%s'; reason -- %s [%d]\n",
                pathname, strerror(errno), errno);
    }

    return 0;
}
For more comprehensive information about stat(), it actually is more helpful to read the man-page for fstat().
Okay so my actual problem here really is pathname should be getting a file. I am surprised why it is getting a directory!
 
Old 11-06-2012, 05:08 AM   #12
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by akshay_satish View Post
Okay so my actual problem here really is pathname should be getting a file. I am surprised why it is getting a directory!
Getting a file (name/path) from where? From the user, from another file, through a network socket??

If you are referring to '/', then that is a directory. It is the root (not to be confused with the user 'root') directory of a Linux/Unix system.
 
Old 11-20-2012, 04:37 AM   #13
akshay_satish
Member
 
Registered: May 2011
Posts: 63

Original Poster
Rep: Reputation: Disabled
Hello I would to get confirmation on this piece of code that I've written. I am basically trying do an "scp" and trying to log useful information onto the console if it fails:

Code:
error = WEXITSTATUS(status);
                if (WIFEXITED(status) && error == 0) {
                    "blah blah"
                } else {
                    "blah blah"
   
                    switch (...) {
                    case a:
                    case b:
                        printf("WHOOPS: scp exited with status %d\n", error);
                        break;
                    default:
                        break;
now the return value for error at the last line is 1 which means WEXITSTATUS failed and returned 1. I am basically trying to do an scp.
Now i want to make the error more readable not throw a print saying "scp exited with status 1"...
is this better?->
Code:
printf( "WHOOPS: scp exited with status %s\n", strerror(error));
With this I get an error saying, "operation is not permitted".. I wanted to get your thoughts whether I am doing the right thing by using strerror or am I printing a string that is not coherent with the return value?

Last edited by akshay_satish; 11-20-2012 at 04:38 AM.
 
Old 11-20-2012, 05:09 AM   #14
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
akshay_satish -

You should have created a new thread for your latest query; it is unrelated to the one that you used to open this thread.

But to answer your question, the command 'scp' returns 0 on success, and some number greater than 0 (this could be any number!) on a failure. If a failure occurs, I don't believe the error number corresponds to anything other than to denote that an error occurred. Thus the use of strerror() would not be wise in this situation.

On my system, a failed 'scp' request, using the system() command, returns a status of 256; this translates to "Unknown error" when passed to strerror().

My recommendation is to avoid using system(), and instead use popen() so that you may read the output produced by the system command.
 
Old 11-20-2012, 07:14 AM   #15
akshay_satish
Member
 
Registered: May 2011
Posts: 63

Original Poster
Rep: Reputation: Disabled
I am extremely sorry DWhitney67.. Should I create one more now or can you forgive me for this question? I'll make sure to create unique threads for separate questions. Thank you very again for your valuable thoughts...Adding on...
Actually this is how I am doing the scp;

Code:
//argv will contain the scp cmd
       ret = posix_spawnp(
            &pid,
            argv[0], 
            NULL, NULL,
            argv,
            NULL);                      //After this i perform a waitpid();

ret = waitpid(pid,&status,0);
if(ret != pid) {
/*failed*/
}
else{
error = WEXITSTATUS(status);
                if (WIFEXITED(status) && error == 0) {
                    "blah blah"
                } else {
                    "blah blah" //failed the downld.
   
                    switch (...) {
                    case a:
                    case b:
                        printf("WHOOPS: scp exited with status %d\n", error);
                        break;
                    default:
                        break;
}
}
Can you pls suggest now. You examples are always intriguing.. thanks again for your help. Hi, I am not able to see my replies or ur new replies anymore, i.e., page 2 onwards. has it been removed?

Last edited by akshay_satish; 11-20-2012 at 07:33 PM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Shell script to get name of file, delete original file, rename blank file chrisgti Linux - General 11 09-15-2012 02:49 AM
Mencoder adds the extension of the original file to the output file ex: file.flv.mp4 linuxlicious Linux - General 2 04-17-2012 02:22 PM
Mencoder adds the extension of the original file to the output file ex: file.flv.mp4 linuxlicious Linux - General 1 04-15-2012 04:07 AM
How to play a media file/ video file/mp3 file recorded in harddisk/cd-rom arindam Linux - Newbie 2 09-05-2003 10:31 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:12 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration