I have made a small service application that writes it's output to several files. The service has to run on both Windows and Linux. Everything is hunky-dory on Windows, but on Linux the files get created, but are all empty.
The following small program shows exactly the same behaviour:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
f, err := os.OpenFile("test.txt", os.O_APPEND|os.O_CREATE, 0777)
if err != nil {
fmt.Println(err.Error())
return
}
defer f.Close()
w := bufio.NewWriter(f)
_, err = w.Write([]byte("hello"))
if err != nil {
fmt.Println(err.Error())
}
w.Flush()
}
When run, the above code does not seem to output any errors on Linux. As can be seen by the file size of test.txt, it does write content to the file on Windows, while it does not do so on Linux.
Directory on Windows:
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 14.04.2016 10:37 345 main.go
-a---- 14.04.2016 10:45 10 test.txt
-a---- 14.04.2016 10:37 2635264 writetest.exe
Directory on Linux:
drwxrwxr-x 2 localuser localuser 4096 Apr 14 10:55 ./
drwxr-xr-x 8 localuser localuser 4096 Apr 14 10:27 ../
-rw-rw-r-- 1 localuser localuser 345 Apr 14 10:37 main.go
-rwxrwxr-x 1 localuser localuser 0 Apr 14 10:55 test.txt*
What am I missing here?
Change your flag, from os.O_APPEND|os.O_CREATE to os.O_RDWR|os.O_APPEND|os.O_CREATE will work on Linux and Mac OSX.
The key idea is event you want to append the file, you still need to open with Write flag in Linux and Mac OSX.
Related
I'm the teacher's assistant for my university's system's programming class. Lately the students have been working on an assignment that involves replicating the program pwd.
Some of the students are noticing what appears to be an inconsistency. When they read the ino from a readdir entry, it gives a different inode from when they stat the same directory. Many of them are asking why.
Shouldn't the directory entry's inode point to the inode to the target directory exists at? If so, why does stat give a different inode?
Here is some sample code to demonstrate:
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#define DIR_NAME "~redacted~"
int getReaddirInode(char* entName)
{
DIR* directory;
struct dirent* entry;
ino_t result;
if ((directory = opendir(".")) == NULL)
{
perror("opendir");
exit(1);
}
while ((entry = readdir(directory)) != NULL)
{
if (strcmp(entName, entry->d_name) == 0)
{
result = entry->d_ino;
break;
}
}
if (entry == NULL)
{
fprintf(stderr, "No such directory: %s.\n", entName);
exit(1);
}
if (closedir(directory) == -1)
{
perror("closedir");
exit(1);
}
return result;
}
int getStatInode(char* entName)
{
struct stat buf;
if (stat(entName, &buf) == -1)
{
perror("stat");
exit(1);
}
return buf.st_ino;
}
int main()
{
if (chdir("/home") == -1)
{
perror("chdir");
return 1;
}
printf("readdir (3) gives an inode of:%9d.\n", getReaddirInode(DIR_NAME));
printf("stat (2) gives an inode of: %9d.\n", getStatInode(DIR_NAME));
return 0;
}
Output:
unix3:~ $ ./a.out
readdir (3) gives an inode of: 4053392.
stat (2) gives an inode of: 69205302.
Edit:
I can confirm that DIR_NAME is a mount point:
unix3:~ $ mount | grep ~redacted~
csc-na01.csc.~redacted~.edu:/student01/student01/0_t/~redacted~ on /home/~redacted~ type nfs (rw,relatime,vers=3,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=129.65.158.8,mountvers=3,mountport=635,mountproto=udp,local_lock=none,addr=129.65.158.8)
Edit2:
The inodes only seem to change at the nfs filesystem changeover. My question is why. What inode is readdir pointing to and what inode is stat pointing to?
Both these inodes have changed in the last 4 hours since I posted this.
I do not have permission to unmount.
I checked another directory mounted from the same address and both the inodes were different from the first directory, suggesting that each directory does have two inodes which are unique to that directory, but I don't understand why.
A directory will have an inode:
$ ls -li
total 4
264332 drwx------ 2 attie attie 4096 Nov 3 22:46 mnt
In this case, the inode of the mnt directory is 264322.
But if we now mount a filesystem on that directory, the inode will appear to change:
$ truncate -s $((5 * 1024 * 1024)) myfs.ext2
$ mkfs.ext2 ./myfs.ext2
mke2fs 1.42.13 (17-May-2015)
Discarding device blocks: done
Creating filesystem with 5120 1k blocks and 1280 inodes
Allocating group tables: done
Writing inode tables: done
Writing superblocks and filesystem accounting information: done
$ sudo mount -o loop myfs.ext2 ./mnt
$ ls -li
total 265
2 drwxr-xr-x 3 root root 1024 Nov 3 22:49 mnt
264339 -rw------- 1 attie attie 5242880 Nov 3 22:49 myfs.ext2
Now, it would appear that the inode for mnt is 2...?! (note that the owner/group has changed too).
If we were to run your application on this directory (removing the chdir() and changing DIR_NAME to mnt), then we get an interesting result:
$ ./test
readdir (3) gives an inode of: 264332.
stat (2) gives an inode of: 2.
readdir() is saying 264332
Which is the inode of the mnt directory, on the underlying filesystem.
stat() is saying 2
Which is the inode of the root of the mounted filesystem.
This makes sense, because readdir() is walking through the nodes of the given directory, returning information for each (but it isn't inspecting them in full)... while stat() is returning information for the full path given, including resolving any mountpoints.
In your case, you have an NFS mount, that remote filesystem is mounted on a directory (which has an inode) on this system... but it is also a directory (which has an inode) on the remote system.
We can prove this further, by doing the following:
$ ls -lia /
total 137
2 drwxr-xr-x 25 root root 4096 Oct 11 17:17 .
2 drwxr-xr-x 25 root root 4096 Oct 11 17:17 ..
2097153 drwxr-xr-x 2 root root 12288 Oct 10 13:36 bin
[...]
As you can see, the root of the filesystem mounted at / also has an inode of 2... inodes are not globally unique, but only unique within the filesystem.
If you're involved in the marking of assignments, then I'd say that both answers are acceptable... This is a pretty subtle and complex thing for students who are probably new to this world to fully comprehend.
The stat() answer can easily be checked with ls -i.
I think that checking the readdir() answer is going to be fiddly without writing a little application (which isn't a problem)... You could employ a bind mount if you have permission:
$ mkdir mnt2
$ sudo mount -o bind . ./mnt2
$ ls -li
total 285
2 drwxr-xr-x 3 root root 1024 Nov 3 22:49 mnt
264319 drwx------ 4 attie attie 4096 Nov 3 23:09 mnt2
264339 -rw------- 1 attie attie 5242880 Nov 3 22:49 myfs.ext2
264346 -rwx------ 1 attie attie 9160 Nov 3 23:00 test
264349 -rw------- 1 attie attie 956 Nov 3 23:00 test.c
$ ls -li mnt2
total 288
264332 drwx------ 2 attie attie 4096 Nov 3 22:46 mnt
264347 drwx------ 2 attie attie 4096 Nov 3 23:09 mnt2
264339 -rw------- 1 attie attie 5242880 Nov 3 22:49 myfs.ext2
264346 -rwx------ 1 attie attie 9160 Nov 3 23:00 test
264349 -rw------- 1 attie attie 956 Nov 3 23:00 test.c
here is part of code
scanf("%[^\n]%*c",command);
int pid;
pid=fork();
if (pid == 0) {
// Child process
char *argv[]={command ,NULL};
execvp(argv[0], argv);
exit (0);
}
When I give as input ls I want as output
1 copy of mysh1.c mysh1.c mysh3.c mysh.c New Folder
a.out helpmanual.desktop mysh2.c mysh4.c New File
and when i give ls -l /tmp
i'm waiting
total 12
-rw------- 1 antre antre 0 Nov 4 17:31 config-err-KT9sEZ
drwx------ 2 antre antre 4096 Nov 4 19:21 mozilla_antre0
drwx------ 2 antre antre 4096 Jan 1 1970 orbit-antre
drwx------ 2 antre antre 4096 Nov 4 17:31 ssh-HaOFtKdeIQnQ `
but i take:
1 copy of mysh1.c mysh1.c mysh3.c mysh.c New Folder
a.out helpmanual.desktop mysh2.c mysh4.c New File
It seems that you're trying to parse the output of ls -l in a C program for some reason.
That's unlikely to be the “right” thing to do. The usual mechanism is to use opendir and readdir to read the directory file, directly.
If you have some truly strange situation in which you cannot opendir (the only case that comes to mind is if you're running ls on a remote system, eg, over ssh), there is a mode in GNU ls specifically for producing an output record format that can be parsed by another program.
From the GNU coreutils info:
10.1.2 What information is listed
‘-D’
‘--dired’
With the long listing (‘-l’) format, print an additional line after
the main output:
//DIRED// BEG1 END1 BEG2 END2 ...
The BEGN and ENDN are unsigned integers that record the byte
position of the beginning and end of each file name in the output.
This makes it easy for Emacs to find the names, even when they
contain unusual characters such as space or newline, without fancy
searching.
If directories are being listed recursively (‘-R’), output a
similar line with offsets for each subdirectory name:
//SUBDIRED// BEG1 END1 ...
Finally, output a line of the form:
//DIRED-OPTIONS// --quoting-style=WORD
where WORD is the quoting style (*note Formatting the file
names::).
Here is an actual example:
$ mkdir -p a/sub/deeper a/sub2
$ touch a/f1 a/f2
$ touch a/sub/deeper/file
$ ls -gloRF --dired a
a:
total 8
-rw-r--r-- 1 0 Jun 10 12:27 f1
-rw-r--r-- 1 0 Jun 10 12:27 f2
drwxr-xr-x 3 4096 Jun 10 12:27 sub/
drwxr-xr-x 2 4096 Jun 10 12:27 sub2/
a/sub:
total 4
drwxr-xr-x 2 4096 Jun 10 12:27 deeper/
a/sub/deeper:
total 0
-rw-r--r-- 1 0 Jun 10 12:27 file
a/sub2:
total 0
//DIRED// 48 50 84 86 120 123 158 162 217 223 282 286
//SUBDIRED// 2 3 167 172 228 240 290 296
//DIRED-OPTIONS// --quoting-style=literal
Note that the pairs of offsets on the ‘//DIRED//’ line above
delimit these names: ‘f1’, ‘f2’, ‘sub’, ‘sub2’, ‘deeper’, ‘file’.
The offsets on the ‘//SUBDIRED//’ line delimit the following
directory names: ‘a’, ‘a/sub’, ‘a/sub/deeper’, ‘a/sub2’.
Here is an example of how to extract the fifth entry name,
‘deeper’, corresponding to the pair of offsets, 222 and 228:
$ ls -gloRF --dired a > out
$ dd bs=1 skip=222 count=6 < out 2>/dev/null; echo
deeper
Note that although the listing above includes a trailing slash for
the ‘deeper’ entry, the offsets select the name without the
trailing slash. However, if you invoke ‘ls’ with ‘--dired’ along
with an option like ‘--escape’ (aka ‘-b’) and operate on a file
whose name contains special characters, notice that the backslash
is included:
$ touch 'a b'
$ ls -blog --dired 'a b'
-rw-r--r-- 1 0 Jun 10 12:28 a\ b
//DIRED// 30 34
//DIRED-OPTIONS// --quoting-style=escape
If you use a quoting style that adds quote marks (e.g.,
‘--quoting-style=c’), then the offsets include the quote marks. So
beware that the user may select the quoting style via the
environment variable ‘QUOTING_STYLE’. Hence, applications using
‘--dired’ should either specify an explicit
‘--quoting-style=literal’ option (aka ‘-N’ or ‘--literal’) on the
command line, or else be prepared to parse the escaped names.
i just only needed to use strtok
If I run:
$ ls -l /tmp
total 16
drwxr-xr-x 2 noaccess noaccess 177 Nov 18 09:53 hsperfdata_noaccess
drwxr-xr-x 2 root root 117 Nov 18 09:53 hsperfdata_root
I get the expected result running:
]$ ls -l /tmp | tr -s '[:space:]'
total 16
drwxr-xr-x 2 noaccess noaccess 177 Nov 18 09:53 hsperfdata_noaccess
drwxr-xr-x 2 root root 117 Nov 18 09:53 hsperfdata_root
Yet tr will not impact file output:
$ file /tmp/dummy
/tmp/dummy: empty file
$ file /tmp/dummy | tr -s '[:space:]'
/tmp/dummy: empty file
(the same if I use [:blank:])
I was expecting:
$ file /tmp/dummy | tr -s '[:space:]'
/tmp/dummy: empty file
Am I misusing file? tr? Must I awk? I'm using bash 3.2.51 on SunOS 5.10 and would like to tell XML and gz files apart.
The Solaris 5.10 version of file is producing output that uses tabs instead of spaces:
$ touch /tmp/dummy
$ file /tmp/dummy | cat -vet
/tmp/dummy:^Iempty file$
$
In this case, tr -s squashes a single tab character down to a single tab character...
I was reading wayland/weston code, the setting up tty part. I found it tries to acquire an available tty for doing KMS and start windows.
This is how it does:
if (!wl->new_user) {
wl->tty = STDIN_FILENO;
} else if (tty) {
t = ttyname(STDIN_FILENO);
if (t && strcmp(t, tty) == 0)
wl->tty = STDIN_FILENO;
else
wl->tty = open(tty, O_RDWR | O_NOCTTY);
} else {
int tty0 = open("/dev/tty0", O_WRONLY | O_CLOEXEC);
char filename[16];
if (tty0 < 0)
error(1, errno, "could not open tty0");
if (ioctl(tty0, VT_OPENQRY, &wl->ttynr) < 0 || wl->ttynr == -1)
error(1, errno, "failed to find non-opened console");
snprintf(filename, sizeof filename, "/dev/tty%d", wl->ttynr);
wl->tty = open(filename, O_RDWR | O_NOCTTY);
close(tty0);
}
in src/weston-launch.c.
It tries to open('/dev/tty0') and find a tty that available if no tty is specified.
But you can't do that, neither /dev/tty0 nor 'available tty' belongs to you. I tested with my simpler version. And of course I couldn't open /dev/tty0.
Do you guys know how this magic is done?
The actual available devices for a tty depend on the system. On most interactive Unix/Unix-like systems you will have a "tty" whose name can be found from the command-line program tty. For example:
$ tty
/dev/pts/2
Likely, you also have a device named "tty", e.g.,
$ ls -l /dev/tty
lrwxrwxrwx 1 root other 26 Feb 9 2014 /dev/tty -> ../devices/pseudo/sy#0:tty
$ ls -lL /dev/tty
crw-rw-rw- 1 root tty 22, 0 Feb 9 2014 /dev/tty
You cannot open just any tty device, because most of them are owned by root (or other users to which they have been assigned).
For further discussion about the differences between /dev/console, /dev/tty and other tty-devices, see Cannot open /dev/console.
According to the console_codes(4) manual page:
VT_OPENQRY
Returns the first available (non-opened) console. argp points to an int which is set to the number of the vt (1 <= *argp <= MAX_NR_CONSOLES).
and for example on a Linux system I see this in /dev:
crw-rw-rw- 1 root 5, 0 Mon 04:20:13 tty
crw------- 1 root 4, 0 Mon 03:58:52 tty0
crw------- 1 root 4, 1 Mon 04:00:41 tty1
crw------- 1 tom 4, 2 Mon 04:30:31 tty2
crw------- 1 root 4, 3 Mon 04:00:41 tty3
crw------- 1 root 4, 4 Mon 04:00:41 tty4
crw------- 1 root 4, 5 Mon 04:00:41 tty5
crw------- 1 root 4, 6 Mon 04:00:41 tty6
crw------- 1 root 4, 7 Mon 03:58:52 tty7
crw------- 1 root 4, 8 Mon 03:58:52 tty8
crw------- 1 root 4, 9 Mon 03:58:52 tty9
crw------- 1 root 4, 10 Mon 03:58:52 tty10
crw------- 1 root 4, 11 Mon 03:58:52 tty11
All of those tty devices except one for which I have opened a console session are owned by root. To be able to log into one, a program such as getty acts to temporarily change its ownership. Doing a ps on my machine shows for example
root 2977 1 0 04:00 tty1 00:00:00 /sbin/getty 38400 tty1
root 2978 1 0 04:00 tty2 00:00:00 /bin/login --
root 2979 1 0 04:00 tty3 00:00:00 /sbin/getty 38400 tty3
root 2980 1 0 04:00 tty4 00:00:00 /sbin/getty 38400 tty4
root 2981 1 0 04:00 tty5 00:00:00 /sbin/getty 38400 tty5
root 2982 1 0 04:00 tty6 00:00:00 /sbin/getty 38400 tty6
Note that getty is running as root. That gives it the privilege to change the ownership of the tty device as needed. That is, while the ioctl may identify an unused tty, you need elevated privileges to actually open it. Linux (like any other Unix-like system) does not have a way to provide ensure that one process has truly exclusive access to a terminal. So it uses the device ownership and permissions to ensure this access.
If you're not the superuser then you should only try to access /dev/tty. That is a special device synonym for whichever tty is controlling the current process.
I'm printing files from two directories using C language. Here is my code:
char *list1[30], *list2[30];
int i=0, x=0;
struct dirent *ent, *ent1;
/* print all the files and directories within directory */
while ((ent = readdir (dirSource)) != NULL) {
list1[i] = ent->d_name;
i++;
}
i=0;
while((ent1 = readdir (dirDest)) != NULL) {
list2[i] = ent1->d_name;
i++;
}
while(x != i){
printf("Daemon - %s\n", list1[x]);
printf("Daemon1 - %s\n", list2[x]);
x++;
}
I can print all the files, but everytime I print the files in a directory, the end result is this:
Daemon - .
Daemon1 - .
Daemon - ..
Daemon1 - ..
Daemon - fich5
Daemon1 - fich4
Daemon - fich3
Daemon1 - fich3
I don't understand why there are dots in the beginning.
Obs.: I don't if it matters, but I'm using Ubuntu 14.04 on a pen, meaning every time I use Ubuntu, I use the trial instead of using dual boot on my pc.
. and .. are two special files which are in every directory in Linux and other Unix-like systems. . represents the current directory and .. represents the parent directory.
Every directory in Unix has the entry . (meaning current directory) and .. (the parent directory).
Give that they start with "." they are hidden files; ls normally do not show them unless you use "-a" option.
See:
[:~/tmp/lilla/uff] % ls -l
total 0
-rw-rw-r-- 1 romano romano 0 May 17 18:48 a
-rw-rw-r-- 1 romano romano 0 May 17 18:48 b
[:~/tmp/lilla/uff] % ls -la
total 8
drwxrwxr-x 2 romano romano 4096 May 17 18:48 .
drwxrwxr-x 3 romano romano 4096 May 17 18:47 ..
-rw-rw-r-- 1 romano romano 0 May 17 18:48 a
-rw-rw-r-- 1 romano romano 0 May 17 18:48 b