| File: | obj-scan-build/ftpfs/../../ftpfs/ftpfs.c |
| Location: | line 244, column 20 |
| Description: | Null pointer passed as an argument to a 'nonnull' parameter |
| 1 | /* Ftp filesystem | |||
| 2 | ||||
| 3 | Copyright (C) 1997,98,2002 Free Software Foundation, Inc. | |||
| 4 | Written by Miles Bader <miles@gnu.org> | |||
| 5 | This file is part of the GNU Hurd. | |||
| 6 | ||||
| 7 | The GNU Hurd is free software; you can redistribute it and/or | |||
| 8 | modify it under the terms of the GNU General Public License as | |||
| 9 | published by the Free Software Foundation; either version 2, or (at | |||
| 10 | your option) any later version. | |||
| 11 | ||||
| 12 | The GNU Hurd is distributed in the hope that it will be useful, but | |||
| 13 | WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
| 15 | General Public License for more details. | |||
| 16 | ||||
| 17 | You should have received a copy of the GNU General Public License | |||
| 18 | along with this program; if not, write to the Free Software | |||
| 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ | |||
| 20 | ||||
| 21 | #include <string.h> | |||
| 22 | #include <unistd.h> | |||
| 23 | #include <argp.h> | |||
| 24 | #include <error.h> | |||
| 25 | #include <argz.h> | |||
| 26 | #include <netdb.h> | |||
| 27 | #include <sys/stat.h> | |||
| 28 | ||||
| 29 | #include <version.h> | |||
| 30 | ||||
| 31 | #include <hurd/netfs.h> | |||
| 32 | ||||
| 33 | #include "ftpfs.h" | |||
| 34 | ||||
| 35 | char *netfs_server_name = "ftpfs"; | |||
| 36 | char *netfs_server_version = HURD_VERSION"0.5"; | |||
| 37 | ||||
| 38 | const char *argp_program_version = STANDARD_HURD_VERSION (ftpfs)"ftpfs" " (GNU Hurd) " "0.5"; | |||
| 39 | ||||
| 40 | static char *args_doc = "REMOTE_FS [SERVER]"; | |||
| 41 | static char *doc = "Hurd ftp filesystem translator." | |||
| 42 | "\vIf SERVER is not specified, an attempt is made to extract" | |||
| 43 | " it from REMOTE_FS, using `SERVER:FS' notation." | |||
| 44 | " SERVER can be a hostname, in which case anonymous ftp is used," | |||
| 45 | " or may include a user and password like `USER:PASSWORD@HOST' (the" | |||
| 46 | " `:PASSWORD' part is optional)."; | |||
| 47 | ||||
| 48 | /* The filesystem. */ | |||
| 49 | struct ftpfs *ftpfs; | |||
| 50 | ||||
| 51 | /* Parameters describing the server we're connecting to. */ | |||
| 52 | struct ftp_conn_params *ftpfs_ftp_params = 0; | |||
| 53 | ||||
| 54 | /* customization hooks. */ | |||
| 55 | struct ftp_conn_hooks ftpfs_ftp_hooks = { interrupt_check: ports_self_interrupted }; | |||
| 56 | ||||
| 57 | /* The (user-specified) name of the SERVER:FILESYSTEM we're connected too. */ | |||
| 58 | char *ftpfs_remote_fs; | |||
| 59 | ||||
| 60 | /* The FILESYSTEM component of FTPFS_REMOTE_FS. */ | |||
| 61 | char *ftpfs_remote_root; | |||
| 62 | ||||
| 63 | /* Random parameters for the filesystem. */ | |||
| 64 | struct ftpfs_params ftpfs_params; | |||
| 65 | ||||
| 66 | volatile struct mapped_time_value *ftpfs_maptime; | |||
| 67 | ||||
| 68 | int netfs_maxsymlinks = 12; | |||
| 69 | ||||
| 70 | extern error_t lookup_server (const char *server, | |||
| 71 | struct ftp_conn_params **params, int *h_err); | |||
| 72 | ||||
| 73 | static FILE *debug_stream = 0; | |||
| 74 | static char *debug_stream_name = 0; | |||
| 75 | static pthread_mutex_t debug_lock = PTHREAD_MUTEX_INITIALIZER{ ((__pthread_spinlock_t) 0), ((__pthread_spinlock_t) 0), 0, 0 , 0, 0, 0, 0 }; | |||
| 76 | ||||
| 77 | /* Prints ftp connection log to DEBUG_STREAM. */ | |||
| 78 | static void | |||
| 79 | cntl_debug (struct ftp_conn *conn, int type, const char *txt) | |||
| 80 | { | |||
| 81 | char *type_str; | |||
| 82 | ||||
| 83 | switch (type) | |||
| 84 | { | |||
| 85 | case FTP_CONN_CNTL_DEBUG_CMD1: type_str = ">"; break; | |||
| 86 | case FTP_CONN_CNTL_DEBUG_REPLY2: type_str = "="; break; | |||
| 87 | default: type_str = "?"; break; | |||
| 88 | } | |||
| 89 | ||||
| 90 | pthread_mutex_lock (&debug_lock); | |||
| 91 | if (debug_stream) | |||
| 92 | { | |||
| 93 | fprintf (debug_stream, "%u.%s%s\n", | |||
| 94 | (unsigned)(uintptr_t)conn->hook, type_str, txt); | |||
| 95 | fflush (debug_stream); | |||
| 96 | } | |||
| 97 | pthread_mutex_unlock (&debug_lock); | |||
| 98 | } | |||
| 99 | ||||
| 100 | /* Various default parameters. */ | |||
| 101 | #define DEFAULT_NAME_TIMEOUT300 300 | |||
| 102 | #define DEFAULT_STAT_TIMEOUT120 120 | |||
| 103 | ||||
| 104 | #define DEFAULT_BULK_STAT_PERIOD10 10 | |||
| 105 | #define DEFAULT_BULK_STAT_THRESHOLD5 5 | |||
| 106 | ||||
| 107 | #define DEFAULT_NODE_CACHE_MAX50 50 | |||
| 108 | ||||
| 109 | /* Return a string corresponding to the printed rep of DEFAULT_what */ | |||
| 110 | #define ___D(what)"what" #what | |||
| 111 | #define __D(what)"what" ___D(what)"what" | |||
| 112 | #define _D(what)"DEFAULT_what" __D(DEFAULT_ ## what)"DEFAULT_ ## what" | |||
| 113 | ||||
| 114 | /* Common (runtime & startup) options. */ | |||
| 115 | ||||
| 116 | #define OPT_NO_DEBUG1 1 | |||
| 117 | ||||
| 118 | #define OPT_NAME_TIMEOUT5 5 | |||
| 119 | #define OPT_STAT_TIMEOUT7 7 | |||
| 120 | #define OPT_NODE_CACHE_MAX8 8 | |||
| 121 | #define OPT_BULK_STAT_PERIOD9 9 | |||
| 122 | #define OPT_BULK_STAT_THRESHOLD10 10 | |||
| 123 | ||||
| 124 | /* Options usable both at startup and at runtime. */ | |||
| 125 | static const struct argp_option common_options[] = | |||
| 126 | { | |||
| 127 | {"debug", 'D', "FILE", OPTION_ARG_OPTIONAL0x1, "Print debug output to FILE"}, | |||
| 128 | {"no-debug", OPT_NO_DEBUG1, 0, OPTION_HIDDEN0x2 }, | |||
| 129 | ||||
| 130 | {0,0,0,0, "Parameters:"}, | |||
| 131 | {"name-timeout", OPT_NAME_TIMEOUT5, "SECS", 0, | |||
| 132 | "Time directory names are cached (default " _D(NAME_TIMEOUT)"300" ")"}, | |||
| 133 | {"stat-timeout", OPT_STAT_TIMEOUT7, "SECS", 0, | |||
| 134 | "Time stat information is cached (default " _D(STAT_TIMEOUT)"120" ")"}, | |||
| 135 | {"node-cache-size", OPT_NODE_CACHE_MAX8, "ENTRIES", 0, | |||
| 136 | "Number of recently used filesystem nodes that are cached (default " | |||
| 137 | _D(NODE_CACHE_MAX)"50" ")"}, | |||
| 138 | ||||
| 139 | {"bulk-stat-period", OPT_BULK_STAT_PERIOD9, "SECS", 0, | |||
| 140 | "Period for detecting bulk stats (default " _D(BULK_STAT_PERIOD)"10" ")"}, | |||
| 141 | {"bulk-stat-threshold", OPT_BULK_STAT_THRESHOLD10, "SECS", 0, | |||
| 142 | "Number of stats within the bulk-stat-period that trigger a bulk stat" | |||
| 143 | " (default " _D(BULK_STAT_THRESHOLD)"5" ")"}, | |||
| 144 | ||||
| 145 | {0, 0} | |||
| 146 | }; | |||
| 147 | ||||
| 148 | static error_t | |||
| 149 | parse_common_opt (int key, char *arg, struct argp_state *state) | |||
| 150 | { | |||
| 151 | error_t err = 0; | |||
| 152 | struct ftpfs_params *params = state->input; | |||
| 153 | ||||
| 154 | switch (key) | |||
| 155 | { | |||
| 156 | case 'D': | |||
| 157 | pthread_mutex_lock (&debug_lock); | |||
| 158 | ||||
| 159 | if (debug_stream && debug_stream != stderrstderr) | |||
| 160 | fclose (debug_stream); | |||
| 161 | if (debug_stream_name) | |||
| 162 | { | |||
| 163 | free (debug_stream_name); | |||
| 164 | debug_stream_name = 0; | |||
| 165 | } | |||
| 166 | ||||
| 167 | if (arg) | |||
| 168 | { | |||
| 169 | debug_stream_name = strdup (arg); | |||
| 170 | if (! debug_stream_name) | |||
| 171 | { | |||
| 172 | argp_failure (state, 0, ENOMEM((0x10 << 26) | ((12) & 0x3fff)), "%s: Cannot open debugging file", arg); | |||
| 173 | err = ENOMEM((0x10 << 26) | ((12) & 0x3fff)); | |||
| 174 | } | |||
| 175 | ||||
| 176 | if (! err) | |||
| 177 | { | |||
| 178 | debug_stream = fopen (arg, "w+"); | |||
| 179 | if (! debug_stream) | |||
| 180 | { | |||
| 181 | err = errno(*__errno_location ()); | |||
| 182 | argp_failure (state, 0, err, "%s: Cannot open debugging file", arg); | |||
| 183 | } | |||
| 184 | } | |||
| 185 | } | |||
| 186 | else | |||
| 187 | debug_stream = stderrstderr; | |||
| 188 | ||||
| 189 | if (! err) | |||
| 190 | ftpfs_ftp_hooks.cntl_debug = cntl_debug; | |||
| 191 | ||||
| 192 | pthread_mutex_unlock (&debug_lock); | |||
| 193 | ||||
| 194 | return err; | |||
| 195 | ||||
| 196 | case OPT_NO_DEBUG1: | |||
| 197 | pthread_mutex_lock (&debug_lock); | |||
| 198 | if (debug_stream && debug_stream != stderrstderr) | |||
| 199 | fclose (debug_stream); | |||
| 200 | ftpfs_ftp_hooks.cntl_debug = 0; | |||
| 201 | pthread_mutex_unlock (&debug_lock); | |||
| 202 | break; | |||
| 203 | ||||
| 204 | case OPT_NODE_CACHE_MAX8: | |||
| 205 | params->node_cache_max = atoi (arg); break; | |||
| 206 | case OPT_NAME_TIMEOUT5: | |||
| 207 | params->name_timeout = atoi (arg); break; | |||
| 208 | case OPT_STAT_TIMEOUT7: | |||
| 209 | params->stat_timeout = atoi (arg); break; | |||
| 210 | default: | |||
| 211 | return ARGP_ERR_UNKNOWN((0x10 << 26) | ((7) & 0x3fff)); | |||
| 212 | } | |||
| 213 | ||||
| 214 | return 0; | |||
| 215 | } | |||
| 216 | ||||
| 217 | static struct argp common_argp = { common_options, parse_common_opt }; | |||
| 218 | ||||
| 219 | /* Startup options. */ | |||
| 220 | ||||
| 221 | static const struct argp_option startup_options[] = | |||
| 222 | { | |||
| 223 | { 0 } | |||
| 224 | }; | |||
| 225 | ||||
| 226 | /* Parse a single command line option/argument. */ | |||
| 227 | static error_t | |||
| 228 | parse_startup_opt (int key, char *arg, struct argp_state *state) | |||
| 229 | { | |||
| 230 | switch (key) | |||
| ||||
| 231 | { | |||
| 232 | case ARGP_KEY_ARG0: | |||
| 233 | if (state->arg_num > 1) | |||
| 234 | argp_usage (state); | |||
| 235 | else if (state->arg_num == 0) | |||
| 236 | ftpfs_remote_fs = arg; | |||
| 237 | else | |||
| 238 | /* If the fs & server are two separate args, glom them together into the | |||
| 239 | ":" notation. */ | |||
| 240 | { | |||
| 241 | char *rfs = malloc (strlen (ftpfs_remote_fs) + 1 + strlen (arg) + 1); | |||
| 242 | if (! rfs) | |||
| 243 | argp_failure (state, 99, ENOMEM((0x10 << 26) | ((12) & 0x3fff)), "%s", arg); | |||
| 244 | stpcpy (stpcpy (stpcpy (rfs, arg), ":"), ftpfs_remote_fs); | |||
| ||||
| 245 | ftpfs_remote_fs = rfs; | |||
| 246 | } | |||
| 247 | break; | |||
| 248 | ||||
| 249 | case ARGP_KEY_SUCCESS0x1000004: | |||
| 250 | /* Validate the remote fs arg; at this point FTPFS_REMOTE_FS is in | |||
| 251 | SERVER:FS notation. */ | |||
| 252 | if (state->arg_num == 0) | |||
| 253 | argp_error (state, "No remote filesystem specified"); | |||
| 254 | else | |||
| 255 | { | |||
| 256 | int h_err; /* Host lookup error. */ | |||
| 257 | error_t err; | |||
| 258 | char *sep = strrchr (ftpfs_remote_fs, '@'); | |||
| 259 | ||||
| 260 | if (sep) | |||
| 261 | /* FTPFS_REMOTE_FS includes a '@', which means that it's in | |||
| 262 | USER[:PASS]@HOST:FS notation, so we have to be careful not to | |||
| 263 | choose the wrong `:' as the SERVER-FS separator. */ | |||
| 264 | sep = strchr (sep, ':'); | |||
| 265 | else | |||
| 266 | sep = strchr (ftpfs_remote_fs, ':'); | |||
| 267 | ||||
| 268 | if (! sep) | |||
| 269 | /* We have just a host name, so treat it as "HOST:/". */ | |||
| 270 | ftpfs_remote_root = "/"; | |||
| 271 | else | |||
| 272 | ftpfs_remote_root = sep + 1; | |||
| 273 | ||||
| 274 | /* Lookup the ftp server (the part before the `:'). */ | |||
| 275 | if (sep) | |||
| 276 | *sep = '\0'; | |||
| 277 | err = lookup_server (ftpfs_remote_fs, &ftpfs_ftp_params, &h_err); | |||
| 278 | if (err == EINVAL((0x10 << 26) | ((22) & 0x3fff))) | |||
| 279 | argp_failure (state, 10, 0, "%s: %s", | |||
| 280 | ftpfs_remote_fs, hstrerror (h_err)); | |||
| 281 | else if (err) | |||
| 282 | argp_failure (state, 11, err, "%s", ftpfs_remote_fs); | |||
| 283 | if (sep) | |||
| 284 | *sep = ':'; | |||
| 285 | } | |||
| 286 | ||||
| 287 | case ARGP_KEY_INIT0x1000003: | |||
| 288 | /* Setup up state for our first child parser (common options). */ | |||
| 289 | state->child_inputs[0] = &ftpfs_params; | |||
| 290 | break; | |||
| 291 | ||||
| 292 | default: | |||
| 293 | return ARGP_ERR_UNKNOWN((0x10 << 26) | ((7) & 0x3fff)); | |||
| 294 | } | |||
| 295 | ||||
| 296 | return 0; | |||
| 297 | } | |||
| 298 | ||||
| 299 | /* Runtime options. */ | |||
| 300 | ||||
| 301 | /* Parse a single command line option/argument. */ | |||
| 302 | static error_t | |||
| 303 | parse_runtime_opt (int key, char *arg, struct argp_state *state) | |||
| 304 | { | |||
| 305 | if (key == ARGP_KEY_INIT0x1000003) | |||
| 306 | /* Setup up state for our first child parser (common options). */ | |||
| 307 | { | |||
| 308 | state->child_inputs[0] = &ftpfs->params; | |||
| 309 | return 0; | |||
| 310 | } | |||
| 311 | else | |||
| 312 | return ARGP_ERR_UNKNOWN((0x10 << 26) | ((7) & 0x3fff)); | |||
| 313 | } | |||
| 314 | ||||
| 315 | static const struct argp_child runtime_argp_children[] = | |||
| 316 | { {&common_argp}, {&netfs_std_runtime_argp}, {0} }; | |||
| 317 | static struct argp runtime_argp = | |||
| 318 | { 0, parse_runtime_opt, 0, 0, runtime_argp_children }; | |||
| 319 | ||||
| 320 | /* Use by netfs_set_options to handle runtime option parsing. */ | |||
| 321 | struct argp *netfs_runtime_argp = &runtime_argp; | |||
| 322 | ||||
| 323 | /* Return an argz string describing the current options. Fill *ARGZ | |||
| 324 | with a pointer to newly malloced storage holding the list and *LEN | |||
| 325 | to the length of that storage. */ | |||
| 326 | error_t | |||
| 327 | netfs_append_args (char **argz, size_t *argz_len) | |||
| 328 | { | |||
| 329 | char buf[80]; | |||
| 330 | error_t err = 0; | |||
| 331 | ||||
| 332 | #define FOPT(fmt, arg)do { if (! err) { snprintf (buf, sizeof buf, fmt, arg); err = argz_add (argz, argz_len, buf); } } while (0) \ | |||
| 333 | do { \ | |||
| 334 | if (! err) \ | |||
| 335 | { \ | |||
| 336 | snprintf (buf, sizeof buf, fmt, arg); \ | |||
| 337 | err = argz_add (argz, argz_len, buf); \ | |||
| 338 | } \ | |||
| 339 | } while (0) | |||
| 340 | ||||
| 341 | pthread_mutex_lock (&debug_lock); | |||
| 342 | if (ftpfs_ftp_hooks.cntl_debug && debug_stream) | |||
| 343 | { | |||
| 344 | if (debug_stream != stderrstderr) | |||
| 345 | { | |||
| 346 | char *rep; | |||
| 347 | asprintf (&rep, "--debug=%s", debug_stream_name); | |||
| 348 | err = argz_add (argz, argz_len, rep); | |||
| 349 | free (rep); | |||
| 350 | } | |||
| 351 | else | |||
| 352 | err = argz_add (argz, argz_len, "--debug"); | |||
| 353 | } | |||
| 354 | pthread_mutex_unlock (&debug_lock); | |||
| 355 | ||||
| 356 | if (ftpfs->params.name_timeout != DEFAULT_NAME_TIMEOUT300) | |||
| 357 | FOPT ("--name-timeout=%ld", ftpfs->params.name_timeout)do { if (! err) { snprintf (buf, sizeof buf, "--name-timeout=%ld" , ftpfs->params.name_timeout); err = argz_add (argz, argz_len , buf); } } while (0); | |||
| 358 | if (ftpfs->params.stat_timeout != DEFAULT_STAT_TIMEOUT120) | |||
| 359 | FOPT ("--stat-timeout=%ld", ftpfs->params.stat_timeout)do { if (! err) { snprintf (buf, sizeof buf, "--stat-timeout=%ld" , ftpfs->params.stat_timeout); err = argz_add (argz, argz_len , buf); } } while (0); | |||
| 360 | if (ftpfs->params.node_cache_max != DEFAULT_NODE_CACHE_MAX50) | |||
| 361 | FOPT ("--node-cache-size=%Zu", ftpfs->params.node_cache_max)do { if (! err) { snprintf (buf, sizeof buf, "--node-cache-size=%Zu" , ftpfs->params.node_cache_max); err = argz_add (argz, argz_len , buf); } } while (0); | |||
| 362 | if (ftpfs->params.bulk_stat_period != DEFAULT_BULK_STAT_PERIOD10) | |||
| 363 | FOPT ("--bulk-stat-period=%ld", ftpfs->params.bulk_stat_period)do { if (! err) { snprintf (buf, sizeof buf, "--bulk-stat-period=%ld" , ftpfs->params.bulk_stat_period); err = argz_add (argz, argz_len , buf); } } while (0); | |||
| 364 | if (ftpfs->params.bulk_stat_threshold != DEFAULT_BULK_STAT_THRESHOLD5) | |||
| 365 | FOPT ("--bulk-stat-threshold=%d", ftpfs->params.bulk_stat_threshold)do { if (! err) { snprintf (buf, sizeof buf, "--bulk-stat-threshold=%d" , ftpfs->params.bulk_stat_threshold); err = argz_add (argz , argz_len, buf); } } while (0); | |||
| 366 | ||||
| 367 | return argz_add (argz, argz_len, ftpfs_remote_fs); | |||
| 368 | } | |||
| 369 | ||||
| 370 | /* Program entry point. */ | |||
| 371 | int | |||
| 372 | main (int argc, char **argv) | |||
| 373 | { | |||
| 374 | error_t err; | |||
| 375 | mach_port_t bootstrap, underlying_node; | |||
| 376 | struct stat underlying_stat; | |||
| 377 | const struct argp_child argp_children[] = | |||
| 378 | { {&common_argp}, {&netfs_std_startup_argp}, {0} }; | |||
| 379 | struct argp argp = | |||
| 380 | { startup_options, parse_startup_opt, args_doc, doc, argp_children }; | |||
| 381 | ||||
| 382 | ftpfs_params.name_timeout = DEFAULT_NAME_TIMEOUT300; | |||
| 383 | ftpfs_params.stat_timeout = DEFAULT_STAT_TIMEOUT120; | |||
| 384 | ftpfs_params.node_cache_max = DEFAULT_NODE_CACHE_MAX50; | |||
| 385 | ftpfs_params.bulk_stat_period = DEFAULT_BULK_STAT_PERIOD10; | |||
| 386 | ftpfs_params.bulk_stat_threshold = DEFAULT_BULK_STAT_THRESHOLD5; | |||
| 387 | ||||
| 388 | argp_parse (&argp, argc, argv, 0, 0, 0); | |||
| 389 | ||||
| 390 | task_get_bootstrap_port (mach_task_self (), &bootstrap)(task_get_special_port((((__mach_task_self_ + 0))), 4, (& bootstrap))); | |||
| 391 | ||||
| 392 | netfs_init (); | |||
| 393 | ||||
| 394 | err = maptime_map (0, 0, &ftpfs_maptime); | |||
| 395 | if (err) | |||
| 396 | error (3, err, "mapping time"); | |||
| 397 | ||||
| 398 | err = ftpfs_create (ftpfs_remote_root, getpid (), | |||
| 399 | ftpfs_ftp_params, &ftpfs_ftp_hooks, | |||
| 400 | &ftpfs_params, &ftpfs); | |||
| 401 | if (err) | |||
| 402 | error (4, err, "%s", ftpfs_remote_fs); | |||
| 403 | ||||
| 404 | netfs_root_node = ftpfs->root; | |||
| 405 | ||||
| 406 | underlying_node = netfs_startup (bootstrap, 0); | |||
| 407 | err = io_stat (underlying_node, &underlying_stat); | |||
| 408 | if (err) | |||
| 409 | error (1, err, "cannot stat underling node"); | |||
| 410 | ||||
| 411 | /* Initialize stat information of the root node. */ | |||
| 412 | netfs_root_node->nn_stat = underlying_stat; | |||
| 413 | netfs_root_node->nn_stat.st_mode = | |||
| 414 | S_IFDIR0040000 | (underlying_stat.st_mode & ~S_IFMT0170000 & ~S_ITRANS000070000000); | |||
| 415 | ||||
| 416 | /* If the underlying node isn't a directory, propagate read permission to | |||
| 417 | execute permission since we need that for lookups. */ | |||
| 418 | if (! S_ISDIR (underlying_stat.st_mode)((((underlying_stat.st_mode)) & 0170000) == (0040000))) | |||
| 419 | { | |||
| 420 | if (underlying_stat.st_mode & S_IRUSR00400) | |||
| 421 | netfs_root_node->nn_stat.st_mode |= S_IXUSR00100; | |||
| 422 | if (underlying_stat.st_mode & S_IRGRP(00400 >> 3)) | |||
| 423 | netfs_root_node->nn_stat.st_mode |= S_IXGRP(00100 >> 3); | |||
| 424 | if (underlying_stat.st_mode & S_IROTH((00400 >> 3) >> 3)) | |||
| 425 | netfs_root_node->nn_stat.st_mode |= S_IXOTH((00100 >> 3) >> 3); | |||
| 426 | } | |||
| 427 | ||||
| 428 | for (;;) | |||
| 429 | netfs_server_loop (); | |||
| 430 | } |