Statistics
| Branch: | Tag: | Revision:

dvbd / src / utils.cpp @ bcb74979

History | View | Annotate | Download (3.33 KB)

1 bfdb7446 jak
/*
2
  Copyright 2003 John Knottenbelt
3
  
4
  This program is free software; you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation; either version 2 of the License, or
7
  (at your option) any later version.
8
 
9
  This program is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
 
14
  You should have received a copy of the GNU General Public License
15
  along with this program; if not, write to the Free Software
16
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
17
*/
18
19
#include "config.h"
20
#include "utils.h"
21
#include <fcntl.h>
22
#include <sys/types.h>
23
#include <sys/socket.h>
24
#include <sys/stat.h>
25
#include <unistd.h>
26
#include <iostream>
27
#include <cctype>
28 900cea42 jak
#include <cerrno>
29 bcb74979 Csaba Kiraly
#include <string.h>
30 bfdb7446 jak
31
void setNonBlocking(int fd)
32
{
33
  long flags = fcntl(fd, F_GETFL, 0); 
34
  flags |= O_NONBLOCK;
35
  fcntl(fd, F_SETFL, flags);
36
}
37
38
int readLineStripTrailingWS(int fd, std::string &line)
39
{
40
  char data[1024];
41
  int bytesread = read(fd, data, 1023);
42
43
  if (bytesread <= 0)
44
    return bytesread;
45
46
  data[bytesread] = '\x0';
47
48
  // Strip trailing whitespace;
49
  for (int j = bytesread - 1; j >= 0 && isspace(data[j]); j--)
50
    data[j] = '\x0';
51
52
  line = data;
53
  return bytesread;
54
}
55
56
void writeString(int fd, const std::string &line)
57
{
58
  write(fd, line.data(), line.size());
59
}
60
61
std::string escapeWS(const std::string &channel)
62
{
63
  std::string result;
64
65
  for (unsigned i = 0; i < channel.size(); i++) {
66
    switch (channel[i]) {
67
    case '\\':
68
      result += "\\\\";
69
      break;
70
    case ' ':
71
      result += "\\_";
72
      break;
73
    default:
74
      result += channel[i];
75
    }
76
  }
77
78
  return result;
79
}
80
81
std::string unescapeWS(const std::string &channel)
82
{
83
  std::string result;
84
  bool escaped = false;
85
86
  for (unsigned i = 0; i < channel.size(); i++) {
87
    if (channel[i] == '\\')
88
      escaped = true;
89
    else {
90
      char ch = channel[i];
91
92
      if (escaped && ch == '_') {
93
        ch = ' ';
94
        escaped = false;
95
      }
96
97
      result += ch;
98
    }
99
  }
100
  return result;
101
}
102
103
bool readCredentials(int fd, pid_t &pid, uid_t &uid, gid_t &gid)
104
{
105
  int value = 1;
106
  if (setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &value, sizeof(value)) < 0) 
107
    std::cerr << "Failed to set SOL_SOCKET SO_PASSCRED: " << strerror(errno) << "\n";
108
109
  struct ucred ucred;
110
  socklen_t size = sizeof(ucred);
111
  if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &size) < 0) {
112
    std::cerr << "Failed to get credentials from UNIX socket: " 
113
              << strerror(errno) << "\n";
114
    return false;  
115
  }
116
117
  pid = ucred.pid;
118
  uid = ucred.uid;
119
  gid = ucred.gid;
120
  return true;
121
}
122
123
bool accessOk(const std::string &path, uid_t uid)
124
{
125
  std::string::size_type lastSlash = path.find_last_of('/');
126
  if (lastSlash == std::string::npos) 
127
    return false;
128
129
  std::string dirPart = path.substr(0, lastSlash);
130
  std::string filePart = path.substr(lastSlash + 1);
131
132
  // Client must own directory
133
  struct stat info;
134
  if (stat(dirPart.c_str(), &info) != 0)
135
    return false;
136
  
137
  if (info.st_uid != uid)
138
    return false;
139
140
  // But must still be writable by this process
141
  if (access(path.c_str(), F_OK) == 0)
142
    return access(path.c_str(), W_OK) == 0;
143
  else 
144
    return access(dirPart.c_str(), W_OK) == 0;
145
}