~ubuntu-branches/ubuntu/wily/steam/wily

« back to all changes in this revision

Viewing changes to spm/spm.in

  • Committer: Package Import Robot
  • Author(s): Felix Geyer
  • Date: 2013-10-29 19:51:18 UTC
  • mfrom: (1.1.4) (0.1.4 trusty-proposed)
  • Revision ID: package-import@ubuntu.com-20131029195118-b9bxciz5hwx5z459
Tags: 1:1.0.0.39-2ubuntu1
Add an epoch to the version number as there was an unrelated steam package
in the archive with a higher version number.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!@steamcore@/steam
2
 
 
3
 
/* Copyright (C) 2000-2005  Thomas Bopp, Thorsten Hampel, Ludger Merkens
4
 
 *
5
 
 *  This program is free software; you can redistribute it and/or modify
6
 
 *  it under the terms of the GNU General Public License as published by
7
 
 *  the Free Software Foundation; either version 2 of the License, or
8
 
 *  (at your option) any later version.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
 
 * 
19
 
 * $Id: spm.in,v 1.13 2006/10/09 21:59:49 exodusd Exp $
20
 
 */
21
 
 
22
 
constant cvs_version="$Id: spm.in,v 1.13 2006/10/09 21:59:49 exodusd Exp $";
23
 
 
24
 
//! steam package manager main script
25
 
//! Installs packages into the main server 
26
 
//! Uploads files by coal and runs pike scripts for preinst and postinst
27
 
inherit "../config";
28
 
 
29
 
#include "../server/include/classes.h"
30
 
#include "../server/include/attributes.h"
31
 
 
32
 
string tmp_dir = "/tmp";
33
 
string pck_name = "";
34
 
 
35
 
string tmp_dir_name;
36
 
 
37
 
static object oInstall;
38
 
 
39
 
static int debug_output = 0;
40
 
static int force = 0;
41
 
 
42
 
object find_object(int id)
43
 
{
44
 
    if ( objectp(oInstall) )
45
 
        oInstall->find_object(id);
46
 
    return 0;
47
 
}
48
 
 
49
 
void list_packages( void|string name )
50
 
{
51
 
  if ( stringp(name) && sizeof(name) < 1 ) name = UNDEFINED;
52
 
  object conn = ((program)"connection.pike")();
53
 
  conn->set_debug( debug_output );
54
 
 
55
 
  conn->start( "steam.open-steam.org", 1900, "guest", "guest" );
56
 
 
57
 
  object _filepath = conn->send_cmd( 0, "get_module", "filepath:tree" );
58
 
  object _packages = conn->send_cmd( _filepath, "path_to_object",
59
 
                                    "/home/admin/packages" );
60
 
  array package_objs = conn->send_cmd( _packages, "get_inventory" );
61
 
  mapping packages = ([ ]);
62
 
  foreach ( package_objs, object pck ) {
63
 
    string desc = conn->send_cmd( pck, "query_attribute", OBJ_DESC );
64
 
    if ( !stringp(desc) ) desc = "";
65
 
    packages[pck->get_identifier()] = desc;
66
 
  }
67
 
 
68
 
  werror("List of packages " + (stringp(name) ? "containing '"+name+"' " : "") + "on sTeam server:\n");
69
 
  foreach( sort(indices(packages)), string package ) {
70
 
    if ( stringp(name) && (search(package, name) < 0) ) continue;
71
 
    werror(" " + package + " : \t" + (string)packages[package] + "\n");
72
 
  }
73
 
}
74
 
 
75
 
int get_package(string pck_name, string filename)
76
 
{
77
 
    object conn = ((program)"connection.pike")();
78
 
    conn->set_debug( debug_output );
79
 
    
80
 
    conn->start("steam.open-steam.org", 1900, "guest", "guest");
81
 
    string content = conn->get_package(pck_name);
82
 
    if ( !stringp(content) )
83
 
    return 0;
84
 
    conn->close();
85
 
    object f = Stdio.File(filename, "wct", 0600);
86
 
    f->write(content);
87
 
    f->close();
88
 
    return 1;
89
 
}
90
 
 
91
 
static string|int get_value(string val)
92
 
{
93
 
   int      d;
94
 
   if ( sscanf(val, "%d", d) == 1 && (string)d == val )
95
 
     return d;
96
 
   return val;
97
 
}
98
 
 
99
 
void read_configs(string fname)
100
 
{
101
 
    string configs = Stdio.read_file(fname);
102
 
    mapping conf = ([ ]);
103
 
 
104
 
    if ( !stringp(configs) )
105
 
    error("failed to find config file at "+ fname);
106
 
    array lines = configs / "\n";
107
 
    foreach(lines, string line) {
108
 
     if ( strlen(line) == 0 )
109
 
       continue;
110
 
     if ( line[0] == '#' ) // comment
111
 
       continue;
112
 
     string key;
113
 
     mixed  val;
114
 
 
115
 
     if ( sscanf(line, "%s=%s", key, val) != 2 ) {
116
 
       continue;
117
 
     } 
118
 
     string v;
119
 
     if ( sscanf(val, "hbs(%s)", v) > 0 ) {
120
 
       conf[key] = get_value(v);
121
 
       continue;
122
 
     }
123
 
     conf[key] = get_value(val);
124
 
    }
125
 
    vars = conf;
126
 
}
127
 
 
128
 
/** Generate a random valid name for a new directory
129
 
 * Returns the string of a valid directory name in the given directory and
130
 
 * with the given prefix and suffix. The name will thus be
131
 
 * dir+prefix+random+suffix.
132
 
 * At the time of calling, no file with this name existed. The directory
133
 
 * will be created and the path returned.
134
 
 */
135
 
string make_tmp_dirname ( string dir, string prefix, string suffix ) {
136
 
  if ( stringp(tmp_dir_name) && sizeof(tmp_dir_name)>0 )
137
 
    return tmp_dir_name;
138
 
  string full_prefix = dir;
139
 
  if ( ! has_suffix( full_prefix, "/" ) ) full_prefix += "/";
140
 
  full_prefix += prefix;
141
 
  string random_name = "";
142
 
  Stdio.File tmp_file;
143
 
  mixed err = 0;
144
 
  do {
145
 
    random_name = full_prefix + replace(MIME.encode_base64(random_string(20),1) + suffix,"/","X");
146
 
  } while ( Stdio.exist(random_name) );
147
 
  if ( !Stdio.mkdirhier( random_name ) ) {
148
 
    werror( "Could not create tmp directory: %s\n", random_name );
149
 
    exit( 1 );
150
 
  }
151
 
  tmp_dir_name = random_name;
152
 
  return tmp_dir_name;
153
 
}
154
 
 
155
 
 
156
 
static void cleanup ()
157
 
{
158
 
  // delete the temporary dir:
159
 
  if ( stringp(tmp_dir_name) && sizeof(tmp_dir_name)>0 ) {
160
 
    if ( Stdio.exist(tmp_dir_name) ) {
161
 
      write( "Deleting temporary directory ...\n", tmp_dir_name );
162
 
      if ( !Stdio.recursive_rm( tmp_dir_name ) )
163
 
        werror( "Could not delete temporary directory: %s\n", tmp_dir_name );
164
 
    }
165
 
  }
166
 
  //if ( search(pck_name,tmp_dir) == 0 )
167
 
  //  Filesystem.System()->rm( pck_name );
168
 
}
169
 
 
170
 
int check_spm(string pname, object spmModule, object connection, void|int force)
171
 
{
172
 
    object tfs = Filesystem.Tar(pname);
173
 
    if ( !objectp(tfs) ) {
174
 
      werror(pname + " not a valid SPM !\n");
175
 
      return 0;
176
 
    }
177
 
    mixed xml = tfs->open("package.xml", "r");
178
 
    string packageXML = xml->read();
179
 
    xml->close();
180
 
    mapping config =spmModule->spm_check_configuration(packageXML);
181
 
    mapping pmod = connection->send_cmd(0, "get_module", config->name);
182
 
    if ( !objectp(pmod) )
183
 
      pmod = connection->send_cmd(0, "get_module", "package:"+config->name);
184
 
    if ( objectp(pmod) ) {
185
 
      if ( spmModule->spm_version_value(config->version) <= spmModule->spm_version_value(pmod->get_version()) ) {
186
 
        if ( force ) {
187
 
          write("Found installed module with version %O, forcing installation anyway.\n", pmod->get_version());
188
 
        }
189
 
        else {
190
 
          werror("Found installed module with version %O, skipping installation !\n", pmod->get_version());
191
 
          return 0;
192
 
        }
193
 
      }
194
 
      else {
195
 
        werror("Found installed module - updating to %O (previous version %O)\n",
196
 
               config->version, pmod->get_version());
197
 
      }
198
 
    }
199
 
    return 1;
200
 
}
201
 
 
202
 
 
203
 
//! Call Script with package to install, for example
204
 
//! install web.spm
205
 
//! spm is a packed archive with the following directories:
206
 
//! sources/ - files to upload on the server with the present structure
207
 
//! xml/ - xml code to set attributes, access and so on in server files
208
 
//! steam/ - meta information of the package and installation perequesites
209
 
//!
210
 
int main(int argc, array(string) argv)
211
 
{
212
 
  string server_path = "@steamcore@";
213
 
  string config_path = "@configdir@";
214
 
 
215
 
  if ( config_path == "" )
216
 
    config_path = server_path + "/config";
217
 
 
218
 
  if ( search(argv, "--help") >= 0 ) { 
219
 
      write("SPM: sTeam package manager.\n"+
220
 
        "This utility connects to a running local sTeam server and\n"+
221
 
        "installs new packages. Usage is spm <options>:\n"+
222
 
        " -i --install <package-name>: Installs ar updates a package.\n"+
223
 
        "    The package is either retrieved from the main sTeam server\n"+
224
 
        "    or located on the local disk (package-name can be a path name).\n"+
225
 
        " -o --old-install <package-name>: Installs or updates a package\n"+
226
 
        "    using the old installation mechanism. This is deprecated and\n"+
227
 
        "    you should only use this method when instructed to.\n"+
228
 
        " -f --force : Forces installation of a package, even if the\n"+
229
 
        "              package is already installed with that version.\n"+
230
 
        " -l --list [name] : Lists all packages available for installation\n"+
231
 
        "    on the main sTeam server (www.open-steam.org). If an argument\n"+
232
 
        "    is given, only packages which contain that text are listed.\n"+
233
 
        " -d --dest <directory> : Install the package to the destination"+
234
 
        "    directory.\n"+
235
 
        " -s --server <hostname> : Install on a given server.\n"+
236
 
        " -p --port <port> : use another port for installation\n"+
237
 
        "    (default is 1900).\n"+
238
 
        " -c --configure <package-name> : Just configure a package\n"+
239
 
        "    (if already installed).\n");
240
 
      return 0;
241
 
  }
242
 
 
243
 
  atexit( cleanup );
244
 
 
245
 
  // get all command line options:
246
 
  array tmp_options = Getopt.find_all_options( argv, ({
247
 
    ({ "install", Getopt.HAS_ARG, ({ "-i", "--install" }) }),
248
 
    ({ "old-install", Getopt.HAS_ARG, ({ "-o", "--old-install" }) }),
249
 
    ({ "list", Getopt.MAY_HAVE_ARG, ({ "-l", "--list" }), ({ }), "" }),
250
 
    ({ "dest", Getopt.HAS_ARG, ({ "-d", "--dest" }) }),
251
 
    ({ "configure", Getopt.HAS_ARG, ({ "-c", "--configure" }) }),
252
 
    ({ "server", Getopt.HAS_ARG, ({ "-s", "--server" }) }),
253
 
    ({ "port", Getopt.HAS_ARG, ({ "-p", "--port" }) }),
254
 
    ({ "debug", Getopt.NO_ARG, ({ "--debug" }) }),
255
 
    ({ "force", Getopt.NO_ARG, ({ "-f", "--force" }) }),
256
 
  }) );
257
 
  // make a mapping out of the options:
258
 
  mapping options = ([ ]);
259
 
  foreach ( tmp_options, array option ) options[ option[0] ] = option[1];
260
 
  if ( options["debug"] ) debug_output = 1;
261
 
  if ( options["force"] ) force = 1;
262
 
 
263
 
  master()->add_include_path(server_path+"/server/include");
264
 
  master()->add_program_path(server_path+"/server/");
265
 
  master()->add_program_path(server_path+"/spm/");
266
 
  master()->add_module_path(server_path+"/server/libraries");
267
 
  master()->add_program_path(server_path+"/server/net/coal");
268
 
  add_constant("find_object", find_object);
269
 
  read_configs(config_path+"/steam.cfg");
270
 
 
271
 
  if ( options["list"] ) {
272
 
      list_packages( options["list"] );
273
 
      return 0;
274
 
  }
275
 
  
276
 
  pck_name = options["install"];
277
 
  if ( !stringp(pck_name) ) pck_name = options["old-install"];
278
 
  if ( !stringp(pck_name) ) pck_name = options["configure"];
279
 
 
280
 
  if ( !stringp(pck_name) ) {
281
 
      werror("Missing filename or URL for installation / configuration...\n");
282
 
      return 1;
283
 
  }
284
 
  string spm_filename = basename( pck_name );
285
 
  sscanf( spm_filename, "%s.gz", spm_filename );
286
 
 
287
 
  string url;
288
 
  mkdir(dirname(tmp_dir));
289
 
 
290
 
  if ( sscanf(pck_name, "http://%s", url) > 0 ) {
291
 
      // the temporary file for download...
292
 
      
293
 
      mapping headers = ([ ]);
294
 
      string user, pass;
295
 
      if ( sscanf(url, "%s:%s@%s", user, pass, url) == 3 ) {
296
 
      write("User: "+ user + "\n");
297
 
      headers = ([ "authorization": "Basic " + 
298
 
        MIME.encode_base64(user+":"+pass), ]);
299
 
      }
300
 
      write("Connecting to http://" + url+"\n");
301
 
      object query = Protocols.HTTP.get_url("http://"+url, ([ ]), headers);
302
 
      mapping d = query->cast("mapping");
303
 
      //werror("RESULT=\n"+sprintf("%O\n",indices(d)));
304
 
      string data = d->data;
305
 
      string fname;
306
 
      sscanf(url, "%*s/%s", fname);
307
 
      write("Transfered " + strlen(data) + " bytes...\n");
308
 
      tmp_dir_name = make_tmp_dirname(tmp_dir,"spm_","");
309
 
      pck_name = tmp_dir_name + "/" + fname;
310
 
      object f = Stdio.File(pck_name, "wct",0600);
311
 
      f->write(data);
312
 
      f->close();
313
 
      
314
 
      write("Package received...\n");
315
 
  }
316
 
 
317
 
  if ( !Stdio.exist(pck_name) ) {
318
 
      write("Getting file from package server...\n");
319
 
      tmp_dir_name = make_tmp_dirname(tmp_dir,"spm_","");
320
 
      string tmp_filename = tmp_dir_name + "/" + pck_name;
321
 
      if ( !get_package(pck_name, tmp_filename) ) {
322
 
        werror("Package not found on server ... Try -l to list packages.\n");
323
 
        return 1;
324
 
      }
325
 
      pck_name = tmp_filename;
326
 
  }
327
 
  master()->add_program_path("../spm");
328
 
 
329
 
  if ( sscanf(pck_name, "%s.gz", pck_name) >= 1 ) {
330
 
    write("Unzipping...\n");
331
 
    string destname = pck_name;
332
 
    if ( search(destname,tmp_dir) != 0 ) {
333
 
      tmp_dir_name = make_tmp_dirname(tmp_dir,"spm_","");
334
 
      destname = tmp_dir_name + "/" + destname;
335
 
    }
336
 
    object f = Stdio.File(destname, "wct");
337
 
    int ret = Process.create_process( ({ "gunzip", "-c", "-f",
338
 
        pck_name+".gz" }), ([ "stdout" : f ]))->wait();
339
 
    f->close();
340
 
    if ( search(pck_name,tmp_dir) == 0 )
341
 
      Filesystem.System()->rm( pck_name+".gz" );
342
 
    pck_name = destname;
343
 
  }
344
 
 
345
 
  write("Opening spm archive ...");
346
 
  object fsystem = Filesystem.Tar(pck_name);
347
 
  write("ok.\n");
348
 
 
349
 
  // check for package.xml
350
 
  if ( !objectp(fsystem) ) {
351
 
    werror("Not a valid spm package (not a tar archive): %s\n", spm_filename);
352
 
    return 1;
353
 
  }
354
 
  if ( options["install"] && search( fsystem->get_dir(), "/package.xml" )<0 ) {
355
 
    werror("The package %s is deprecated (it doesn't contain a /package.xml"
356
 
      +" file).\nYou need to install it with the -o or --old-install "
357
 
      +"command instead:\n  spm -o %s\n", spm_filename, spm_filename);
358
 
    return 1;
359
 
  }
360
 
  if ( options["old-install"]
361
 
       && search( fsystem->get_dir(), "/package.xml" ) >= 0 ) {
362
 
    werror("The package %s is not deprecated (it contains a /package.xml"
363
 
      +" file).\nYou need to install it with the -i or --install "
364
 
      +"command instead:\n  spm -i %s\n", spm_filename, spm_filename);
365
 
    return 1;
366
 
  }
367
 
 
368
 
 
369
 
  string server = options["server"];
370
 
  int port = (int)(vars["port"]);
371
 
  if ( stringp(server) ) port = 1900;
372
 
  else if ( stringp(vars["ip"]) && sizeof(vars["ip"]) )
373
 
    server = vars["ip"];
374
 
  else
375
 
    server = "localhost";
376
 
  if ( stringp(options["port"]) )
377
 
    sscanf( options["port"], "%d", port );
378
 
 
379
 
  write("Connecting sTeam on "+server+":"+port+"\n");
380
 
  object conn = ((program)"connection.pike")();
381
 
  conn->set_debug( debug_output );
382
 
  string pw = read_password("Root Password for server", "steam");
383
 
 
384
 
  string pname;
385
 
  if ( sscanf(pck_name, "%s.spm", pname) != 1 ) {
386
 
      pname = pck_name;
387
 
  }
388
 
 
389
 
  vars["package"] = (pname / "/")[-1];
390
 
  vars["fs"] = pname+".spm";
391
 
  if ( !stringp(options["dest"]) )
392
 
        vars["dest"] = "/";
393
 
  else 
394
 
        vars["dest"] = options["dest"];
395
 
 
396
 
  conn->set_fsystem(fsystem, vars);
397
 
  conn->start(server, port, "root", pw);
398
 
  if ( options->configure ) {
399
 
        //TODO: this is hardcoded to configure only the web package!?
400
 
        conn->configure_web();
401
 
        werror("Configuration of package completed !");
402
 
        return 0;
403
 
  }
404
 
 
405
 
  // connect to the server and register the new package module
406
 
  if ( options["old-install"] ) {
407
 
    conn->upload_package(vars);
408
 
    werror("\nInstallation successfull ("+conn->iInstall + " new Files, "+
409
 
           conn->iUpdate + " updated).\n\n");
410
 
    return 0;
411
 
  } else if ( options["install"] ) {
412
 
    object package_file = Stdio.File( pck_name, "r" );
413
 
    object _filepath = conn->send_cmd( 0, "get_module", "filepath:tree" );
414
 
    if ( !objectp(_filepath) ) {
415
 
      werror( "Unable to find filepath module on server!\n" );
416
 
      return 1;
417
 
    }
418
 
    object _spm = conn->send_cmd( 0, "get_module", "SPM" );
419
 
    if ( !objectp(_spm) ) {
420
 
      werror( "Unable to find spm module on server!\n" );
421
 
      return 1;
422
 
    }
423
 
    object dir = conn->send_cmd( _filepath, "path_to_object", "/packages" );
424
 
    object root_dir = conn->send_cmd( _filepath, "path_to_object", "/" );
425
 
    if ( !objectp(dir) || !objectp(root_dir) ) {
426
 
      werror( "Unable to find package or root directory on server!" );
427
 
      return 1;
428
 
    }
429
 
   if ( !check_spm(pck_name, _spm, conn, force) )
430
 
        return 1;
431
 
    object new_obj = conn->send_cmd( dir, "get_object_byname", spm_filename );
432
 
    if ( !objectp(new_obj) ) {
433
 
      object _docfactory = conn->send_cmd( 0, "get_factory", CLASS_DOCUMENT );
434
 
      if ( !objectp(_docfactory) ) {
435
 
        werror( "Unable to find document factory on server!\n" );
436
 
        return 1;
437
 
      }
438
 
      new_obj = conn->send_cmd( _docfactory, "execute", ([ "name": spm_filename, ]) );
439
 
      if ( !objectp(new_obj) ) {
440
 
        werror( "Could not create temporary package file on server!\n" );
441
 
        return 1;
442
 
      }
443
 
      conn->send_cmd( new_obj, "move", dir );
444
 
    }
445
 
    conn->send_cmd( new_obj, "set_content", package_file->read() );
446
 
    package_file->close();
447
 
    write( "Uploaded package %s ...\n", spm_filename );
448
 
    // install:
449
 
    conn->send_cmd( _spm, "install_spm", ({ new_obj, root_dir }) );
450
 
    write( "Installed package %s ...\n", spm_filename );
451
 
    // delete temporary package on server
452
 
    conn->send_cmd( new_obj, "delete" );
453
 
    write( "Deleted temporary package file on server\n" );
454
 
  }
455
 
}