1 /*
2    Copyright (c) 2003, 2021, Oracle and/or its affiliates.
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, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #include <ndb_global.h>
26 
27 #include "Filename.hpp"
28 #include "ErrorHandlingMacros.hpp"
29 #include "RefConvert.hpp"
30 #include "DebuggerNames.hpp"
31 #include "Ndbfs.hpp"
32 
33 #include <signaldata/FsOpenReq.hpp>
34 
35 #define JAM_FILE_ID 383
36 
37 
38 static const char* fileExtension[] = {
39   ".Data",
40   ".FragLog",
41   ".LocLog",
42   ".FragList",
43   ".TableList",
44   ".SchemaLog",
45   ".sysfile",
46   ".log",
47   ".ctl"
48 };
49 
50 static const Uint32 noOfExtensions = sizeof(fileExtension)/sizeof(char*);
51 
Filename()52 Filename::Filename()
53 {
54 }
55 
~Filename()56 Filename::~Filename(){
57 }
58 
59 void
set(Ndbfs * fs,BlockReference blockReference,const Uint32 filenumber[4],bool dir,SegmentedSectionPtr ptr)60 Filename::set(Ndbfs* fs,
61               BlockReference blockReference,
62               const Uint32 filenumber[4], bool dir,
63               SegmentedSectionPtr ptr)
64 {
65   char buf[PATH_MAX];
66 
67   const Uint32 type = FsOpenReq::getSuffix(filenumber);
68   const Uint32 version = FsOpenReq::getVersion(filenumber);
69 
70   size_t sz;
71   if (version == 2)
72   {
73     sz = BaseString::snprintf(theName, sizeof(theName), "%s",
74                               fs->get_base_path(FsOpenReq::BP_BACKUP).c_str());
75     m_base_name = theName + fs->get_base_path(FsOpenReq::BP_BACKUP).length();
76   }
77   else
78   {
79     sz = BaseString::snprintf(theName, sizeof(theName), "%s",
80                               fs->get_base_path(FsOpenReq::BP_FS).c_str());
81     m_base_name = theName + fs->get_base_path(FsOpenReq::BP_FS).length();
82   }
83 
84   switch(version){
85   case 1 :{
86     const Uint32 diskNo = FsOpenReq::v1_getDisk(filenumber);
87     const Uint32 table  = FsOpenReq::v1_getTable(filenumber);
88     const Uint32 frag   = FsOpenReq::v1_getFragment(filenumber);
89     const Uint32 S_val  = FsOpenReq::v1_getS(filenumber);
90     const Uint32 P_val  = FsOpenReq::v1_getP(filenumber);
91 
92     if (diskNo < 0xff){
93       BaseString::snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
94       strcat(theName, buf);
95     }
96 
97     {
98       const char* blockName = getBlockName( refToMain(blockReference) );
99       if (blockName == NULL){
100 	ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","No Block Name");
101 	return;
102       }
103       BaseString::snprintf(buf, sizeof(buf), "%s%s", blockName, DIR_SEPARATOR);
104       strcat(theName, buf);
105     }
106 
107     if (table < 0xffffffff){
108       BaseString::snprintf(buf, sizeof(buf), "T%d%s", table, DIR_SEPARATOR);
109       strcat(theName, buf);
110     }
111 
112     if (frag < 0xffffffff){
113       BaseString::snprintf(buf, sizeof(buf), "F%d%s", frag, DIR_SEPARATOR);
114       strcat(theName, buf);
115     }
116 
117 
118     if (S_val < 0xffffffff){
119       BaseString::snprintf(buf, sizeof(buf), "S%d", S_val);
120       strcat(theName, buf);
121     }
122 
123     if (P_val < 0xff){
124       BaseString::snprintf(buf, sizeof(buf), "P%d", P_val);
125       strcat(theName, buf);
126     }
127 
128   }
129   break;
130   case 2:{
131     const Uint32 seq = FsOpenReq::v2_getSequence(filenumber);
132     const Uint32 nodeId = FsOpenReq::v2_getNodeId(filenumber);
133     const Uint32 count = FsOpenReq::v2_getCount(filenumber);
134 
135     BaseString::snprintf(buf, sizeof(buf), "BACKUP%sBACKUP-%u%s",
136 	     DIR_SEPARATOR, seq, DIR_SEPARATOR);
137     strcat(theName, buf);
138     if(count == 0xffffffff) {
139       BaseString::snprintf(buf, sizeof(buf), "BACKUP-%u.%d",
140 	       seq, nodeId); strcat(theName, buf);
141     } else {
142       BaseString::snprintf(buf, sizeof(buf), "BACKUP-%u-%d.%d",
143 	       seq, count, nodeId); strcat(theName, buf);
144     }
145     break;
146   }
147   break;
148   case 3:{
149     const Uint32 diskNo = FsOpenReq::v1_getDisk(filenumber);
150 
151     if(diskNo == 0xFF){
152       ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","Invalid disk specification");
153     }
154 
155     BaseString::snprintf(buf, sizeof(buf), "D%d%s", diskNo, DIR_SEPARATOR);
156     strcat(theName, buf);
157   }
158     break;
159   case 4:
160   {
161     char buf[PATH_MAX];
162     copy((Uint32*)&buf[0], ptr);
163     if(buf[0] == DIR_SEPARATOR[0])
164     {
165       strncpy(theName, buf, PATH_MAX);
166       m_base_name = theName;
167     }
168     else
169     {
170 #ifdef NDB_WIN32
171       char* b= buf;
172       while((b= strchr(b, '/')) && b)
173       {
174         *b= '\\';
175       }
176 #endif
177       Uint32 bp = FsOpenReq::v4_getBasePath(filenumber);
178       BaseString::snprintf(theName, sizeof(theName), "%s%s",
179                fs->get_base_path(bp).c_str(), buf);
180       m_base_name = theName + fs->get_base_path(bp).length();
181     }
182     return; // No extension
183   }
184   case 5:
185   {
186     Uint32 tableId = FsOpenReq::v5_getTableId(filenumber);
187     Uint32 lcpNo = FsOpenReq::v5_getLcpNo(filenumber);
188     Uint32 fragId = FsOpenReq::v5_getFragmentId(filenumber);
189     BaseString::snprintf(buf, sizeof(buf), "LCP%s%d%sT%dF%d", DIR_SEPARATOR, lcpNo, DIR_SEPARATOR, tableId, fragId);
190     strcat(theName, buf);
191     break;
192   }
193   case 6:
194   {
195     Uint32 bp = FsOpenReq::v5_getLcpNo(filenumber);
196     sz = BaseString::snprintf(theName, sizeof(theName), "%s",
197                               fs->get_base_path(bp).c_str());
198     break;
199   }
200   default:
201     ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","Wrong version");
202   }
203   if (type >= noOfExtensions){
204     ERROR_SET(ecError, NDBD_EXIT_AFS_PARAMETER,"","File Type doesn't exist");
205     return;
206   }
207   strcat(theName, fileExtension[type]);
208 
209   if(dir == true){
210     for(int l = (int)strlen(theName) - 1; l >= 0; l--){
211       if(theName[l] == DIR_SEPARATOR[0]){
212 	theName[l] = 0;
213 	break;
214       }
215     }
216   }
217 }
218