XRootD
XrdOssMSS.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d O s s M S S . c c */
4 /* */
5 /* (C) 2003 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* All Rights Reserved */
7 /* Produced by Andrew Hanushevsky for Stanford University under contract */
8 /* DE-AC02-76-SFO0515 with the Deprtment of Energy */
9 /* */
10 /* This file is part of the XRootD software suite. */
11 /* */
12 /* XRootD is free software: you can redistribute it and/or modify it under */
13 /* the terms of the GNU Lesser General Public License as published by the */
14 /* Free Software Foundation, either version 3 of the License, or (at your */
15 /* option) any later version. */
16 /* */
17 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
18 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
19 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
20 /* License for more details. */
21 /* */
22 /* You should have received a copy of the GNU Lesser General Public License */
23 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
24 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
25 /* */
26 /* The copyright holder's institutional names and contributor's names may not */
27 /* be used to endorse or promote products derived from this software without */
28 /* specific prior written permission of the institution or contributor. */
29 /******************************************************************************/
30 
31 #include <dirent.h>
32 #include <unistd.h>
33 #include <cerrno>
34 #include <strings.h>
35 #include <signal.h>
36 #include <cstdio>
37 #include <ctime>
38 #if defined(AIX) || defined(__solaris__)
39 #include <sys/vnode.h>
40 #include <sys/mode.h>
41 #endif
42 #include <sys/param.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <sys/wait.h>
46 
47 #include "XrdNet/XrdNetOpts.hh"
48 #include "XrdNet/XrdNetSocket.hh"
49 #include "XrdOss/XrdOssApi.hh"
50 #include "XrdOss/XrdOssConfig.hh"
51 #include "XrdOss/XrdOssError.hh"
52 #include "XrdOss/XrdOssTrace.hh"
53 #include "XrdOuc/XrdOucProg.hh"
54 #include "XrdOuc/XrdOucStream.hh"
55 #include "XrdSys/XrdSysError.hh"
56 #include "XrdSys/XrdSysHeaders.hh"
57 #include "XrdSys/XrdSysLogger.hh"
58 #include "XrdSys/XrdSysPlatform.hh"
59 
60 /******************************************************************************/
61 /* E r r o r R o u t i n g O b j e c t */
62 /******************************************************************************/
63 
64 extern XrdSysError OssEroute;
65 
66 extern XrdSysTrace OssTrace;
67 
68 /******************************************************************************/
69 /* d e f i n e s */
70 /******************************************************************************/
71 
72 #define NegVal(x) (x <= 0 ? (x < 0 ? x : -1) : -x)
73 
74 /******************************************************************************/
75 /* f i l e h a n d l e */
76 /******************************************************************************/
77 
78 /* These are private data structures. They are allocated dynamically to the
79  appropriate size (yes, that means dbx has a tough time).
80 */
81 
83  {int hflag;
85 
86  XrdOssHandle(int type, XrdOucStream *newsp=0) {hflag = type; sp = newsp;}
87  ~XrdOssHandle() {if (sp) delete sp; hflag = 0;}
88 
89  };
90 
91 #define XRDOSS_HT_EOF 1
92 #define XRDOSS_HT_DIR 4
93 
94 /******************************************************************************/
95 /* M a s s S t o r a g e R e l a t e d M e t h o d s */
96 /******************************************************************************/
97 
98 /******************************************************************************/
99 /* o p e n d i r */
100 /******************************************************************************/
101 
102 void *XrdOssSys::MSS_Opendir(const char *dir_path, int &rc) {
103 /*
104  Function: Open the directory `path' and prepare for reading.
105 
106  Input: path - The fully qualified name of the directory to open.
107 
108  Output: Returns a directory handle to be used for subsequent
109  operations. If an error occurs, (-errno) is returned.
110 */
111  const char *epname = "MSS_Opendir";
112  struct XrdOssHandle *oh;
113  XrdOucStream *sp;
114 
115  // Make sure the path is not too long.
116  //
117  if (strlen(dir_path) > MAXPATHLEN)
118  {OssEroute.Emsg(epname, "mss path too long - ", dir_path);
119  rc = -ENAMETOOLONG;
120  return (void *)0;
121  }
122 
123  // Issue it now to trap any errors but defer reading the result until
124  // readdir() is called. This does tie up a process, sigh.
125  //
126  if ( (rc = MSS_Xeq(&sp, ENOENT, "dlist", dir_path)))
127  return (void *)0;
128 
129  // Allocate storage for the handle and return a copy of it.
130  //
131  if (!(oh = new XrdOssHandle(XRDOSS_HT_DIR, sp)))
132  {delete sp; rc = -ENOMEM; return (void *)0;}
133  return (void *)oh;
134 }
135 
136 /******************************************************************************/
137 /* r e a d d i r */
138 /******************************************************************************/
139 
140 int XrdOssSys::MSS_Readdir(void *dir_handle, char *buff, int blen) {
141 /*
142  Function: Read the next entry if directory 'dir_handle'.
143 
144  Input: dir_handle - The value returned by a successful opendir() call.
145  buff - Buffer to hold directory name.
146  blen - Size of the buffer.
147 
148  Output: Upon success, places the contents of the next directory entry
149  in buff. When the end of the directory is encountered buff
150  will be set to a null string.
151 
152  Upon failure, returns a (-errno).
153 */
154  const char *epname = "MSS_Readdir";
155  int retc;
156  struct XrdOssHandle *oh = (struct XrdOssHandle *)dir_handle;
157  char *resp;
158 
159  // Verify that the handle is correct.
160  //
161  if ( !(oh->hflag & XRDOSS_HT_DIR) )
162  {OssEroute.Emsg(epname, "invalid mss handle"); return -EBADF;}
163 
164  // Read a record from the directory, if possible.
165  //
166  if (oh->hflag & XRDOSS_HT_EOF) *buff = '\0';
167  else if ((resp = oh->sp->GetLine()))
168  {if ( ((int)strlen(resp)) >= blen )
169  {*buff = '\0';
170  return OssEroute.Emsg(epname, -EOVERFLOW,
171  "readdir rmt", resp);
172  }
173  strlcpy(buff, resp, blen);
174  } else {
175  if ((retc = oh->sp->LastError())) return NegVal(retc);
176  else {*buff = '\0'; oh->hflag |= XRDOSS_HT_EOF;}
177  }
178  return XrdOssOK;
179 }
180 
181 /******************************************************************************/
182 /* c l o s e d i r */
183 /******************************************************************************/
184 
185 int XrdOssSys::MSS_Closedir(void *dir_handle) {
186 /*
187  Function: Close the directory associated with handle "dir_handle".
188 
189  Input: dir_handle - The handle returned by opendir().
190 
191  Output: Returns 0 upon success and (-errno) upon failure.
192 */
193  const char *epname = "MSS_Closedir";
194  struct XrdOssHandle *oh = (struct XrdOssHandle *)dir_handle;
195 
196  if ( !(oh->hflag & XRDOSS_HT_DIR) )
197  {OssEroute.Emsg(epname, "invalid mss handle"); return -EBADF;}
198  delete oh;
199  return XrdOssOK;
200 }
201 
202 /******************************************************************************/
203 /* c r e a t e */
204 /******************************************************************************/
205 
206 int XrdOssSys::MSS_Create(const char *path, mode_t file_mode, XrdOucEnv &env)
207 /*
208  Function: Create a file named `path' with 'file_mode' access mode bits set.
209 
210  Input: path - The fully qualified name of the file to create.
211  file_mode - The Posix access mode bits to be assigned to the file.
212  These bits correspond to the standard Unix permission
213  bits (e.g., 744 == "rwxr--r--").
214  env Enviornmental information.
215 
216  Output: Returns zero upon success and (-errno) otherwise.
217 */
218 {
219  const char *epname = "MSS_Create";
220  char myMode[16];
221 
222  // Make sure the path is not too long.
223  //
224  if (strlen(path) > MAXPATHLEN)
225  {OssEroute.Emsg(epname, "mss path too long - ", path);
226  return -ENAMETOOLONG;
227  }
228 
229  // Construct the cmd to create the file. We currently don't support cosid.
230  //
231  sprintf(myMode, "%o", static_cast<int>(file_mode));
232 
233  // Create the file in in the mass store system
234  //
235  return MSS_Xeq(0, 0, "create", path, myMode);
236 }
237 
238 
239 /******************************************************************************/
240 /* s t a t */
241 /******************************************************************************/
242 
243 /*
244  Function: Determine if file 'path' actually exists.
245 
246  Input: path - Is the fully qualified name of the file to be tested.
247  buff - pointer to a 'stat' structure to hold the attributes
248  of the file.
249 
250  Output: Returns 0 upon success and -errno upon failure.
251 */
252 
253 int XrdOssSys::MSS_Stat(const char *path, struct stat *buff)
254 {
255  const char *epname = "MSS_Stat";
256  char ftype, mtype[10], *resp;
257  int retc, xt_nlink;
258  long xt_uid, xt_gid, atime, ctime, mtime, xt_blksize, xt_blocks;
259  long long xt_size;
260  XrdOucStream *sfd;
261 
262  // Make sure the path is not too long.
263  //
264  if (strlen(path) > MAXPATHLEN)
265  {OssEroute.Emsg(epname, "mss path too long - ", path);
266  return -ENAMETOOLONG;
267  }
268 
269  // Issue the command. This may be an immediate exists a or full statx.
270  //
271  if (!buff) return MSS_Xeq(0, ENOENT, (isMSSC ? "statx" : "exists"), path);
272  if ((retc = MSS_Xeq(&sfd, ENOENT, "statx", path))) return retc;
273 
274  // Read in the results.
275  //
276  if ( !(resp = sfd ->GetLine()))
277  return OssEroute.Emsg(epname,-XRDOSS_E8012,"process ",path);
278 
279  // Extract data from the response.
280  //
281  sscanf(resp, "%c %9s %d %ld %ld %ld %ld %ld %lld %ld %ld", &ftype, mtype,
282  &xt_nlink, &xt_uid, &xt_gid, &atime, &ctime, &mtime,
283  &xt_size, &xt_blksize, &xt_blocks);
284 
285  // Set the stat buffer, appropriately.
286  //
287  memset( (char *)buff, 0, sizeof(struct stat) );
288  buff->st_nlink = static_cast<nlink_t>(xt_nlink);
289  buff->st_uid = static_cast<uid_t>(xt_uid);
290  buff->st_gid = static_cast<gid_t>(xt_gid);
291  buff->st_atime = static_cast<time_t>(atime);
292  buff->st_ctime = static_cast<time_t>(ctime);
293  buff->st_mtime = static_cast<time_t>(mtime);
294  buff->st_size = static_cast<off_t>(xt_size);
295  buff->st_blksize=static_cast<long>(xt_blksize);
296 #ifdef __APPLE__
297  buff->st_blocks = xt_blocks;
298 #else
299  buff->st_blocks =static_cast<blkcnt_t>(xt_blocks);
300 #endif
301 
302  if (ftype == 'd') buff->st_mode |= S_IFDIR;
303  else if (ftype == 'l') buff->st_mode |= S_IFLNK;
304  else buff->st_mode |= S_IFREG;
305 
306  buff->st_mode |= tranmode(&mtype[0]) << 6;
307  buff->st_mode |= tranmode(&mtype[3]) << 3;
308  buff->st_mode |= tranmode(&mtype[6]);
309 
310  delete sfd;
311  return 0;
312 }
313 
314 int XrdOssSys::tranmode(char *mode) {
315  int mbits = 0;
316  if (mode[0] == 'r') mbits |= S_IROTH;
317  if (mode[1] == 'w') mbits |= S_IWOTH;
318  if (mode[2] == 'x') mbits |= S_IXOTH;
319  return mbits;
320 }
321 
322 /******************************************************************************/
323 /* r e m o v e */
324 /******************************************************************************/
325 
326 /*
327  Function: Delete a file from the namespace and release it's data storage.
328 
329  Input: path - Is the fully qualified name of the file to be removed.
330 
331  Output: Returns 0 upon success and -errno upon failure.
332 */
333 int XrdOssSys::MSS_Unlink(const char *path) {
334  const char *epname = "MSS_Unlink";
335 
336  // Make sure the path is not too long.
337  //
338  if (strlen(path) > MAXPATHLEN)
339  {OssEroute.Emsg(epname, "mss path too long - ", path);
340  return -ENAMETOOLONG;
341  }
342 
343  // Remove the file in Mass Store System.
344  //
345  return MSS_Xeq(0, ENOENT, "rm", path);
346 }
347 
348 /******************************************************************************/
349 /* r e n a m e */
350 /******************************************************************************/
351 
352 /*
353  Function: Renames a file with name 'old_name' to 'new_name'.
354 
355  Input: old_name - Is the fully qualified name of the file to be renamed.
356  new_name - Is the fully qualified name that the file is to have.
357 
358  Output: Returns 0 upon success and -errno upon failure.
359 */
360 int XrdOssSys::MSS_Rename(const char *oldname, const char *newname) {
361  const char *epname = "MSS_Rename";
362 
363  // Make sure the path is not too long.
364  //
365  if (strlen(oldname) > MAXPATHLEN
366  || strlen(newname) > MAXPATHLEN)
367  {OssEroute.Emsg(epname,"mss path too long - ", oldname, newname);
368  return -ENAMETOOLONG;
369  }
370 
371  // Rename the file in Mass Store System
372  //
373  return MSS_Xeq(0, 0, "mv", oldname, newname);
374 }
375 
376 /******************************************************************************/
377 /* P R I V A T E S E C T I O N */
378 /******************************************************************************/
379 /******************************************************************************/
380 /* M S S _ X e q */
381 /******************************************************************************/
382 
383 int XrdOssSys::MSS_Xeq(XrdOucStream **xfd, int okerr,
384  const char *cmd, const char *arg1, const char *arg2)
385 {
386  EPNAME("MSS_Xeq")
387  static int NoResp = 0;
388  char *resp;
389  int retc;
390  XrdOucStream *sp;
391 
392 // If we have no gateway command, return an error
393 //
394  if (!RSSProg) return -XRDOSS_E8013;
395 
396 // Allocate a stream for this command
397 //
398  if (!(sp = new XrdOucStream(&OssEroute)))
399  return OssEroute.Emsg("MSS_Xeq",-ENOMEM,"create stream for",RSSCmd);
400 
401 // Run the command
402 //
403  DEBUG("Invoking '" <<RSSCmd <<' ' <<cmd <<' ' <<(arg1 ? arg1 : "")
404  <<' ' <<(arg2 ? arg2 : ""));
405  if ((retc = RSSProg->Run(sp, cmd, arg1, arg2)))
406  {delete sp; return NegVal(retc);}
407 
408 // Wait for data to appear. We do this to avoid hanging up and chewing through
409 // all of the threads while clients retry the requests with a new connection.
410 //
411  if ((retc = sp->Wait4Data(RSSTout)))
412  {if (retc < 0)
413  {if (!(0xff & NoResp++))
414  OssEroute.Emsg("MSS_Xeq", -ETIMEDOUT, "execute", cmd);
415  retc = ETIMEDOUT;
416  }
417  delete sp; return NegVal(retc);
418  }
419 
420 // Read back the first record. The first records must be the return code
421 // from the command followed by any output. Make sure that this is the case.
422 //
423  if ( !(resp = sp->GetLine()) ) retc = XRDOSS_E8023;
424  else
425  {DEBUG("received '" <<resp <<"'");
426  if (sscanf(resp, "%d", &retc) <= 0) retc = XRDOSS_E8024;
427  }
428  if (retc)
429  {if (retc != -okerr)
430  OssEroute.Emsg("MSS_Xeq", NegVal(retc), "execute", cmd);
431  delete sp;
432  return NegVal(retc);
433  }
434 
435 // If the caller wants the stream pointer; return it. Otherwise close it.
436 //
437  if (xfd) *xfd = sp;
438  else delete sp;
439  return 0;
440 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
#define XRDOSS_E8013
Definition: XrdOssError.hh:47
#define XRDOSS_E8023
Definition: XrdOssError.hh:57
#define XRDOSS_E8012
Definition: XrdOssError.hh:46
#define XRDOSS_E8024
Definition: XrdOssError.hh:58
#define XRDOSS_HT_DIR
Definition: XrdOssMSS.cc:92
#define NegVal(x)
Definition: XrdOssMSS.cc:72
XrdSysTrace OssTrace
#define XRDOSS_HT_EOF
Definition: XrdOssMSS.cc:91
XrdSysError OssEroute
#define XrdOssOK
Definition: XrdOss.hh:50
int stat(const char *path, struct stat *buf)
size_t strlcpy(char *dst, const char *src, size_t sz)
int MSS_Readdir(void *fd, char *buff, int blen)
Definition: XrdOssMSS.cc:140
int MSS_Rename(const char *, const char *)
Definition: XrdOssMSS.cc:360
int tranmode(char *)
Definition: XrdOssMSS.cc:314
int isMSSC
Definition: XrdOssApi.hh:239
int MSS_Closedir(void *)
Definition: XrdOssMSS.cc:185
int RSSTout
Definition: XrdOssApi.hh:240
int MSS_Unlink(const char *)
Definition: XrdOssMSS.cc:333
XrdOucProg * RSSProg
Definition: XrdOssApi.hh:307
int MSS_Stat(const char *, struct stat *buff=0)
Definition: XrdOssMSS.cc:253
int MSS_Create(const char *path, mode_t, XrdOucEnv &)
Definition: XrdOssMSS.cc:206
int MSS_Xeq(XrdOucStream **xfd, int okerr, const char *cmd, const char *arg1=0, const char *arg2=0)
Definition: XrdOssMSS.cc:383
char * RSSCmd
Definition: XrdOssApi.hh:238
void * MSS_Opendir(const char *, int &rc)
Definition: XrdOssMSS.cc:102
int Run(XrdOucStream *Sp, const char *argV[], int argc=0, const char *envV[]=0) const
Definition: XrdOucProg.cc:108
char * GetLine()
int Wait4Data(int msMax=-1)
int Emsg(const char *esfx, int ecode, const char *text1, const char *text2=0)
Definition: XrdSysError.cc:95
XrdOssHandle(int type, XrdOucStream *newsp=0)
Definition: XrdOssMSS.cc:86
XrdOucStream * sp
Definition: XrdOssMSS.cc:84