I am having a weird problem. I am trying to create a unix socket in a directory but it does not create the one I want. I have cut down the code to the below example.
#include <iostream>
#include <string>
#include <cstdlib>
#include <string.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <errno.h>
#include <limits.h>
int main(int argc, char *argv[])
{
std::string socketname(argv[1]);
socketname += "my_socket";
int fd;
int result;
struct sockaddr_un addr;
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1)
{
std::cerr << "socket returned " << errno << ": " << strerror(errno) << std::endl;
exit(1);
}
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socketname.c_str(), sizeof(addr.sun_path) - 1);
result = bind(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
if (result == -1)
{
std::cerr << "bind returned " << errno << ": " << strerror(errno ) << std::endl;
exit(1);
}
return 0;
}
The problem is that when I run program like
./a.out /home/rasterblaster/local/media/video/television/UnitedStates/series/Californication/SeasonOne/xvid-conversions
I do not get “my_socket”. Instead I find some random socket named like “xvid-convers”.
/home/rasterblaster/local/media/video/television/UnitedStates/series/Californication/SeasonOne$ ls -la
drwxrwxrwx 3 rasterblaster rasterblaster 4096 2012-03-08 22:06 .
drwxrwxrwx 3 rasterblaster rasterblaster 4096 2012-03-08 21:39 ..
srwxrwxr-x 1 rasterblaster rasterblaster 0 2012-03-08 22:06:08 xvid-convers
drwxrwxrwx 2 rasterblaster rasterblaster 4096 2012-03-08 21:39 xvid-conversions
What am I doing wrong?
There is nothing really weird going on. If you look at the result of
sizeof(addr.sun_path)it should be about 100 or so bytes. When you try to copy more than that size into it withstrncpy()you are truncating the path to what fits into sun_path and bind() is just creating a filesystem entry for any name beyond the last valid directory name.There is no benefit to placing a socket this deep into a directory structure. You can just as easily put it in /tmp or /run or some common directory that just clients and the server have permission if you want a bit more security.
Also, you probably want
just in case the path named passed doesn’t end in a slash.